Scripts To Footer - Version 0.6.0

Version Description

Large number of improvements: - Add settings page with global disable options for home page, search pages, post type archives, taxonomy archives, and other archives. - Update uninstall.php to remove things correctly. - Add FAQ to readme.txt and readme.md. - Add a changelog as a separate file. - Change the custom post type filter. Refer to updated FAQ and documentation. - Add support for custom taxonomy archives. - Change the exclude filter, to be more relevant to the new options. Older filter is depreciated, but still supported (for now). - Update the post meta for disabling the plugin on specific posts/pages. - Add Github Updater support. - Removed CMB and built metaboxes the old fashion way. - Added debug logging to better track any potential errors moving forward.

Download this release

Release Info

Developer joshuadnelson
Plugin Icon wp plugin Scripts To Footer
Version 0.6.0
Comparing to
See all releases

Code changes from version 0.5 to 0.6.0

CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Changelog
2
+
3
+ ##### 0.6
4
+ - Add settings page with global disable options for home page, search pages, post type archives, taxonomy archives, and other archives.
5
+ - Update uninstall.php to remove things correctly.
6
+ - Add FAQ to readme.txt and readme.md.
7
+ - Add this changelog as a separate file.
8
+ - Change the custom post type filter. Refer to updated [FAQ](https://github.com/joshuadavidnelson/scripts-to-footer/#faq) and [documentation](https://github.com/joshuadavidnelson/scripts-to-footer/wiki).
9
+ - Add support for custom taxonomy archives.
10
+ - Change the exclude filter, to be more relevant to the new options. Older filter is depreciated, but still supported (for now).
11
+ - Update the post meta for disabling the plugin on specific posts/pages.
12
+ - Add Github Updater support.
13
+ - Removed CMB and built metaboxes the old fashion way.
14
+ - Added debug logging to better track any potential errors moving forward.
15
+
16
+ ##### 0.5
17
+ Reverted metabox version to previous - invalid error was sneaking through.
18
+
19
+ ##### 0.4
20
+ Added filter to exclude pages, updated metabox version, plugin version bump and updated readme.txt file.
21
+
22
+ ##### 0.3
23
+ Added conditional to disable on plugin on admin dashboard, version bump.
24
+
25
+ ##### 0.2
26
+ Updating code to be object-oriented and added page metabox to disable plugin on specific pages.
27
+
28
+ ##### 0.1
29
+ Initial release
README.md ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Scripts To Footer
2
+ =================
3
+
4
+ Move your scripts to the footer to speed up perceived page load times and improve user experience.
5
+
6
+ Please utilize the [issues](https://github.com/joshuadavidnelson/scripts-to-footer/issues) section if you run into problems or have suggestions for making the plugin better. You can also view the most recent official, stable release on the WordPress repo linked below.
7
+
8
+ *See the [wiki](https://github.com/joshuadavidnelson/scripts-to-footer/wiki) for specifics on usage, like filters and work-arounds for specific scripts*
9
+
10
+ ### WordPress Plugin
11
+
12
+ Download for your WordPress site here: [http://wordpress.org/plugins/scripts-to-footerphp/](http://wordpress.org/plugins/scripts-to-footerphp/)
13
+
14
+ ### FAQ
15
+ 1. My scripts are not moving to the footer. This is likely due to one of three things:
16
+ 1. The theme you're using is not enqueuing scripts per [WordPress standards](https://codex.wordpress.org/Function_Reference/wp_enqueue_script#Using_a_Hook).
17
+ 2. You have a plugin that is not enqueing scripts [per standards](https://codex.wordpress.org/Function_Reference/wp_enqueue_script#Using_a_Hook).
18
+ 3. (Less common) There is a conflict with this plugin and another one. Deactivate all plugins and revert to a built-in theme (like TwentyTwelve or TwentyFifteen). Then activate Scripts-to-Footer. Check your HTML source to confirm it's working.
19
+
20
+ If so, proceed to activate each of your other plugins one at a time, checking your HTML source each time to see if the scripts behavior changes. Eventually you'll find a conflict, if not with the plugins then activate your theme and check.
21
+
22
+ Please feel free to open a [Github Issue](https://github.com/joshuadavidnelson/scripts-to-footer/issues) to report conflicts or goto [the WP.org support forum](https://wordpress.org/support/plugin/scripts-to-footerphp). If there is something wrong with Scripts-to-Footer, we'll update it. However, if it's a another plugin or theme we can only contact the developer with the issue to attempt to resolve it.
23
+
24
+ 2. Everything Breaks!!
25
+ - There are lots of scripts that require things like jQuery in the header. Try checking the "Keep jQuery in the header" option in Settings > Scripts to Footer or using the `stf_exclude_scripts` filter noted in the [documentation](https://github.com/joshuadavidnelson/scripts-to-footer/wiki) (Note: only for version 0.6 and higher).
26
+
27
+ 3. My Slider stopped working.
28
+ - See number 2.
29
+
30
+ 4. My Page Speed hasn't improved (or it's worse)
31
+ - Actually, this plugin should not change your actual page speed - the same scripts are being loaded, that takes the same amount of time. However, by placing scripts in the footer you can change the _precieved_ load times, moving [render-blocking scripts](https://developers.google.com/speed/docs/insights/BlockingJS) below the fold, allowing your content to load first - instead of loading scripts and slowing the visual portions of your site. That's the whole point. Outside of that, this plugin is not intended to decrease page load speed or minify scripts in anyway.
32
+
33
+ ### Donate
34
+
35
+ Like this plugin and feeling generous? Please consdier [donating](http://joshuadnelson.com/donate) to support freelance development.
admin/admin-settings.php ADDED
@@ -0,0 +1,502 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Admin Settings
4
+ *
5
+ * @package Scripts_To_Footer
6
+ * @subpackage Scripts_To_Footer_Settings
7
+ * @author Joshua David Nelson <josh@joshuadnelson.com>
8
+ * @copyright Copyright (c) 2015, Joshua David Nelson
9
+ * @license http://www.opensource.org/licenses/gpl-license.php GPL-2.0+
10
+ * @link http://joshuadnelson.com/scripts-to-footer-plugin
11
+ **/
12
+
13
+ /**
14
+ * Prevent direct access to this file.
15
+ *
16
+ * @since 0.2
17
+ **/
18
+ if( !defined( 'ABSPATH' ) ) {
19
+ exit( 'You are not allowed to access this file directly.' );
20
+ }
21
+
22
+ /**
23
+ * Main Settings Class
24
+ *
25
+ * @since 0.6.0
26
+ */
27
+ if( !class_exists( 'Scripts_To_Footer_Settings' ) ) {
28
+ class Scripts_To_Footer_Settings {
29
+ /**
30
+ * Holds the values to be used in the fields callbacks
31
+ */
32
+ private $options;
33
+
34
+ /**
35
+ * Start up
36
+ *
37
+ * @since 0.6
38
+ */
39
+ public function __construct() {
40
+ add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
41
+ add_action( 'admin_init', array( $this, 'page_init' ) );
42
+ }
43
+
44
+ /**
45
+ * Add options page
46
+ *
47
+ * @since 0.6
48
+ */
49
+ public function add_plugin_page() {
50
+ // This page will be under "Settings"
51
+ add_options_page(
52
+ 'Scripts to Footer Settings',
53
+ 'Scripts to Footer',
54
+ 'manage_options',
55
+ STF_SETTINGS_FIELD,
56
+ array( $this, 'create_admin_page' )
57
+ );
58
+ }
59
+
60
+ /**
61
+ * Options page callback
62
+ *
63
+ * @since 0.6
64
+ */
65
+ public function create_admin_page() {
66
+ // Set class property
67
+ $this->options = get_option( STF_SETTINGS_FIELD );
68
+ ?>
69
+ <div class="wrap">
70
+ <h2>Scripts to Footer Settings</h2>
71
+ <form method="post" action="options.php">
72
+ <?php
73
+ // This prints out all hidden setting fields
74
+ settings_fields( STF_SETTINGS_FIELD );
75
+ do_settings_sections( 'stf-settings' );
76
+ submit_button();
77
+ ?>
78
+ </form>
79
+ </div>
80
+ <?php
81
+ }
82
+
83
+ /**
84
+ * Register and add settings
85
+ *
86
+ * @since 0.6
87
+ */
88
+ public function page_init() {
89
+
90
+ // Metabox on Edit screen, for Page/Post Override
91
+ add_action( 'add_meta_boxes', array( $this, 'metabox_register' ) );
92
+ add_action( 'save_post', array( $this, 'metabox_save' ), 1, 2 );
93
+
94
+ // Admin options page
95
+ register_setting(
96
+ STF_SETTINGS_FIELD, // Option group
97
+ STF_SETTINGS_FIELD, // Option name
98
+ array( $this, 'sanitize' ) // Sanitize
99
+ );
100
+
101
+ // Template Options Section
102
+ add_settings_section(
103
+ 'exclude_options',
104
+ 'Exclude Options',
105
+ array( $this, 'print_exclude_options_section_info' ),
106
+ 'stf-settings'
107
+ );
108
+
109
+ // Home page option
110
+ add_settings_field(
111
+ 'stf_home',
112
+ 'Blog Page',
113
+ array( $this, 'stf_home' ),
114
+ 'stf-settings',
115
+ 'exclude_options'
116
+ );
117
+
118
+ // Search Results option
119
+ add_settings_field(
120
+ 'stf_search',
121
+ 'Search Results',
122
+ array( $this, 'stf_search' ),
123
+ 'stf-settings',
124
+ 'exclude_options'
125
+ );
126
+
127
+ // Post Type Archives options
128
+ add_settings_field(
129
+ 'stf_post_type_archives',
130
+ 'Post Type Archives',
131
+ array( $this, 'stf_post_type_archives' ),
132
+ 'stf-settings',
133
+ 'exclude_options'
134
+ );
135
+
136
+ // Taxonomy Archives options
137
+ add_settings_field(
138
+ 'stf_taxonomy_archives',
139
+ 'Taxonomy Archives',
140
+ array( $this, 'stf_taxonomy_archives' ),
141
+ 'stf-settings',
142
+ 'exclude_options'
143
+ );
144
+
145
+ // Author Archives options
146
+ add_settings_field(
147
+ 'stf_author_archive',
148
+ 'Author Archives',
149
+ array( $this, 'stf_author_archive' ),
150
+ 'stf-settings',
151
+ 'exclude_options'
152
+ );
153
+
154
+ // Archive option
155
+ add_settings_field(
156
+ 'stf_archive',
157
+ 'Other Archive Pages',
158
+ array( $this, 'stf_archive' ),
159
+ 'stf-settings',
160
+ 'exclude_options'
161
+ );
162
+
163
+ // Header Scripts Section
164
+ add_settings_section(
165
+ 'header_script_options',
166
+ 'Header Scripts',
167
+ array( $this, 'print_header_script_section_info' ),
168
+ 'stf-settings'
169
+ );
170
+
171
+ // Archive option
172
+ add_settings_field(
173
+ 'stf_jquery_header',
174
+ 'Keep jQuery in the Header',
175
+ array( $this, 'stf_jquery_header' ),
176
+ 'stf-settings',
177
+ 'header_script_options'
178
+ );
179
+ }
180
+
181
+ /**
182
+ * Sanitize each setting field as needed
183
+ *
184
+ * @since 0.6
185
+ *
186
+ * @param array $input Contains all settings fields as array keys
187
+ */
188
+ public function sanitize( $input ) {
189
+ $new_input = array();
190
+ if( isset( $input['stf_exclude_home'] ) )
191
+ $new_input['stf_exclude_home'] = absint( $input['stf_exclude_home'] );
192
+
193
+ if( isset( $input['stf_exclude_search'] ) )
194
+ $new_input['stf_exclude_search'] = absint( $input['stf_exclude_search'] );
195
+
196
+ if( isset( $input['stf_exclude_archive'] ) )
197
+ $new_input['stf_exclude_archive'] = absint( $input['stf_exclude_archive'] );
198
+ if( isset( $input['stf_exclude_author_archive'] ) )
199
+ $new_input['stf_exclude_author_archive'] = absint( $input['stf_exclude_author_archive'] );
200
+
201
+ // Post Type options
202
+ $post_types = $this->post_type_options();
203
+ if( is_array( $post_types ) ) {
204
+ foreach( $post_types as $option ) {
205
+ if( isset( $input[ $option ] ) )
206
+ $new_input[ $option ] = absint( $input[ $option ] );
207
+ }
208
+ }
209
+
210
+ // Taxonomy options
211
+ $taxes = $this->taxonomy_options();
212
+ if( is_array( $taxes ) ) {
213
+ foreach( $taxes as $option ) {
214
+ if( isset( $input[ $option ] ) )
215
+ $new_input[ $option ] = absint( $input[ $option ] );
216
+ }
217
+ }
218
+
219
+ if( isset( $input['stf_jquery_header'] ) )
220
+ $new_input['stf_jquery_header'] = absint( $input['stf_jquery_header'] );
221
+
222
+ return $new_input;
223
+ }
224
+
225
+ /**
226
+ * Return the post type settings field names.
227
+ *
228
+ * @since 0.6
229
+ *
230
+ * @return array
231
+ */
232
+ function post_type_options() {
233
+ $options = array();
234
+
235
+ global $stf_scripts_to_footer;
236
+ $post_types = $stf_scripts_to_footer->post_types_supported();
237
+ if( is_array( $post_types ) ) {
238
+ foreach( $post_types as $post_type ) {
239
+ $options[] = "stf_exclude_{$post_type}_archive";
240
+ }
241
+ }
242
+
243
+ return $options;
244
+ }
245
+
246
+ /**
247
+ * Return the post type settings field names.
248
+ *
249
+ * @since 0.6
250
+ *
251
+ * @return array
252
+ */
253
+ function taxonomy_options() {
254
+ $options = array();
255
+
256
+ global $stf_scripts_to_footer;
257
+ $taxes = $stf_scripts_to_footer->taxonomies_supported();
258
+ if( is_array( $taxes ) ) {
259
+ foreach( $taxes as $tax ) {
260
+ $options[] = "stf_exclude_{$tax}_archive";
261
+ }
262
+ }
263
+
264
+ return $options;
265
+ }
266
+
267
+ /**
268
+ * Print the Section text.
269
+ *
270
+ * @since 0.6
271
+ */
272
+ public function print_exclude_options_section_info() {
273
+ echo _x( 'Select which templates should <em><strong>not</strong></em> have scripts moved to the footer:', STF_DOMAIN );
274
+ }
275
+
276
+ /**
277
+ * Get the settings option array and print one of its values.
278
+ *
279
+ * @since 0.6
280
+ */
281
+ public function stf_home() {
282
+ if( !isset( $this->options['stf_exclude_home'] ) )
283
+ $this->options['stf_exclude_home'] = 0;
284
+
285
+ echo '<input type="checkbox" name="' . STF_SETTINGS_FIELD . '[stf_exclude_home]" ' . checked( $this->options['stf_exclude_home'], 1, false ) . ' value="1">';
286
+
287
+ }
288
+
289
+ /**
290
+ * Get the settings option array and print one of its values.
291
+ *
292
+ * @since 0.6
293
+ */
294
+ public function stf_search() {
295
+ if( !isset( $this->options['stf_exclude_search'] ) )
296
+ $this->options['stf_exclude_search'] = 0;
297
+
298
+ echo '<input type="checkbox" name="' . STF_SETTINGS_FIELD . '[stf_exclude_search]" ' . checked( $this->options['stf_exclude_search'], 1, false ) . ' value="1">';
299
+
300
+ }
301
+
302
+ /**
303
+ * Get the settings option array and print one of its values.
304
+ *
305
+ * @since 0.6
306
+ */
307
+ public function stf_post_type_archives() {
308
+ global $stf_scripts_to_footer;
309
+ $post_types = $stf_scripts_to_footer->post_types_supported();
310
+ if( is_array( $post_types ) ) {
311
+ echo '<ul>';
312
+ foreach( $post_types as $post_type ) {
313
+ if( !isset( $this->options["stf_exclude_{$post_type}_archive"] ) )
314
+ $this->options["stf_exclude_{$post_type}_archive"] = 0;
315
+
316
+ $obj = get_post_type_object( $post_type );
317
+ $title = $obj->labels->singular_name;
318
+ echo "<li><input type=\"checkbox\" id=\"stf_exclude_{$post_type}_archive\" name=\"" . STF_SETTINGS_FIELD . "[stf_exclude_{$post_type}_archive]\" " . checked( $this->options["stf_exclude_{$post_type}_archive"], 1, false ) . " value=\"1\"><label for=\"stf_exclude_{$post_type}_archive\">" . $title . ' </label></li>';
319
+ }
320
+ echo '</ul>';
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Get the settings option array and print one of its values.
326
+ *
327
+ * @since 0.6
328
+ */
329
+ public function stf_taxonomy_archives() {
330
+ global $stf_scripts_to_footer;
331
+ $taxes = $stf_scripts_to_footer->taxonomies_supported();
332
+ if( is_array( $taxes ) ) {
333
+ echo '<ul>';
334
+ foreach( $taxes as $taxonomy ) {
335
+ if( !isset( $this->options["stf_exclude_{$taxonomy}_archive"] ) )
336
+ $this->options["stf_exclude_{$taxonomy}_archive"] = 0;
337
+
338
+ $obj = get_taxonomy( $taxonomy );
339
+ $title = $obj->labels->singular_name;
340
+ echo "<li><input type=\"checkbox\" id=\"stf_exclude_{$taxonomy}_archive\" name=\"" . STF_SETTINGS_FIELD . "[stf_exclude_{$taxonomy}_archive]\" " . checked( $this->options["stf_exclude_{$taxonomy}_archive"], 1, false ) . " value=\"1\"><label for=\"stf_exclude_{$taxonomy}_archive\">" . $title . ' </label></li>';
341
+ }
342
+ echo '</ul>';
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Get the settings option array and print one of its values.
348
+ *
349
+ * @since 0.6
350
+ */
351
+ public function stf_author_archive() {
352
+ if( !isset( $this->options['stf_exclude_author_archive'] ) )
353
+ $this->options['stf_exclude_author_archive'] = 0;
354
+
355
+ echo '<input type="checkbox" name="' . STF_SETTINGS_FIELD . '[stf_exclude_author_archive]" ' . checked( $this->options['stf_exclude_author_archive'], 1, false ) . ' value="1">';
356
+
357
+ }
358
+
359
+ /**
360
+ * Get the settings option array and print one of its values.
361
+ *
362
+ * @since 0.6
363
+ */
364
+ public function stf_archive() {
365
+ if( !isset( $this->options['stf_exclude_archive'] ) )
366
+ $this->options['stf_exclude_archive'] = 0;
367
+
368
+ echo '<input type="checkbox" name="' . STF_SETTINGS_FIELD . '[stf_exclude_archive]" ' . checked( $this->options['stf_exclude_archive'], 1, false ) . ' value="1">';
369
+
370
+ }
371
+
372
+ /**
373
+ * Print the Section text.
374
+ *
375
+ * @since 0.6
376
+ */
377
+ public function print_header_script_section_info() {
378
+ echo sprintf( __( 'Options for keeping specific scripts in the header, if they occur. Want to exclude a different script? Check out the <a href="%s" title="On Github">documentation</a> for more information.', STF_DOMAIN ), 'https://github.com/joshuadavidnelson/scripts-to-footer/wiki' );
379
+ }
380
+
381
+ /**
382
+ * Get the settings option array and print one of its values.
383
+ *
384
+ * @since 0.6
385
+ */
386
+ public function stf_jquery_header() {
387
+ if( !isset( $this->options['stf_jquery_header'] ) )
388
+ $this->options['stf_jquery_header'] = 0;
389
+
390
+ echo '<input type="checkbox" name="' . STF_SETTINGS_FIELD . '[stf_jquery_header]" ' . checked( $this->options['stf_jquery_header'], 1, false ) . ' value="1">';
391
+
392
+ }
393
+
394
+ ///////////// Post Metabox /////////////
395
+
396
+ /**
397
+ * Initialize the single post metabox.
398
+ *
399
+ * @since 0.6
400
+ */
401
+ function metabox_register() {
402
+ global $stf_scripts_to_footer;
403
+
404
+ // Check for post type support
405
+ $post_type = get_post_type();
406
+ if( !$post_type || !$stf_scripts_to_footer->post_type_supported( $post_type ) )
407
+ return;
408
+
409
+ add_meta_box( 'scripts-to-footer', 'Scripts to Footer Settings', array( $this, 'metabox_render' ), $post_type, 'normal', 'high' );
410
+ }
411
+
412
+ /**
413
+ * Output the single post metabox.
414
+ *
415
+ * @since 0.6
416
+ */
417
+ function metabox_render() {
418
+
419
+ // Grab current value
420
+ $exclude = get_post_meta( get_the_ID(), 'stf_exclude', true );
421
+ if( $exclude == 'on' ) {
422
+ update_post_meta( get_the_ID(), 'stf_exclude', 1, 'on' );
423
+ $exclude = 1;
424
+ }
425
+
426
+ // Security nonce
427
+ wp_nonce_field( 'scripts_to_footer', 'stf_nonce' );
428
+
429
+ echo '<p style="padding-top:10px;">';
430
+
431
+ // Exclude
432
+ printf( '<label for="stf_exclude">%s</label>', __( 'Turn Plugin Off', STF_DOMAIN ) );
433
+
434
+ echo '<input type="checkbox" id="stf_exclude" name="stf_exclude" ' . checked( true , $exclude, false ) . ' style="margin:0 20px 0 10px;">';
435
+
436
+ printf( '<span style="color:#999;">%s</span>', __( 'By default, this plugin will run on this post type. This checkbox lets you turn it off for this specific page/post.', STF_DOMAIN ) );
437
+
438
+ echo '</p>';
439
+ }
440
+
441
+ /**
442
+ * Handle metabox saves
443
+ *
444
+ * @since 0.6
445
+ */
446
+ function metabox_save( $post_id, $post ) {
447
+
448
+ // Security check
449
+ if ( ! isset( $_POST['stf_nonce'] ) || ! wp_verify_nonce( $_POST['stf_nonce'], 'scripts_to_footer' ) ) {
450
+ return;
451
+ }
452
+
453
+ // Bail out if running an autosave, ajax, cron.
454
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
455
+ return;
456
+ }
457
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
458
+ return;
459
+ }
460
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
461
+ return;
462
+ }
463
+
464
+ // Bail out if the user doesn't have the correct permissions to update the slider.
465
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
466
+ return;
467
+ }
468
+
469
+ // Either save or delete they post meta
470
+ if ( isset( $_POST[ 'stf_exclude' ] ) ) {
471
+ $value = (int) (bool) $_POST[ 'stf_exclude' ];
472
+ update_post_meta( $post_id, 'stf_exclude', $value );
473
+ } else {
474
+ delete_post_meta( $post_id, 'stf_exclude' );
475
+ }
476
+ }
477
+ }
478
+
479
+ if( is_admin() )
480
+ $stf_settings = new Scripts_To_Footer_Settings();
481
+ }
482
+
483
+ /**
484
+ * Get custom settings.
485
+ *
486
+ * @since 0.6
487
+ *
488
+ * @param string $key The key
489
+ * @param string $setting The settings field
490
+ */
491
+ if( !function_exists( 'stf_get_option' ) ) {
492
+ function stf_get_option( $key, $setting = null ) {
493
+ // Get settings field options
494
+ $setting = $setting ? $setting : STF_SETTINGS_FIELD;
495
+ $options = get_option( $setting );
496
+
497
+ if ( ! is_array( $options ) || ! array_key_exists( $key, $options ) )
498
+ return '';
499
+
500
+ return is_array( $options[$key] ) ? stripslashes_deep( $options[$key] ) : stripslashes( wp_kses_decode_entities( $options[$key] ) );
501
+ }
502
+ }
lib/metabox/example-functions.php DELETED
@@ -1,222 +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[] = array(
24
- 'id' => 'test_metabox',
25
- 'title' => 'Test Metabox',
26
- 'pages' => array( 'page', ), // Post type
27
- 'context' => 'normal',
28
- 'priority' => 'high',
29
- 'show_names' => true, // Show field names on the left
30
- 'fields' => array(
31
- array(
32
- 'name' => 'Test Text',
33
- 'desc' => 'field description (optional)',
34
- 'id' => $prefix . 'test_text',
35
- 'type' => 'text',
36
- ),
37
- array(
38
- 'name' => 'Test Text Small',
39
- 'desc' => 'field description (optional)',
40
- 'id' => $prefix . 'test_textsmall',
41
- 'type' => 'text_small',
42
- ),
43
- array(
44
- 'name' => 'Test Text Medium',
45
- 'desc' => 'field description (optional)',
46
- 'id' => $prefix . 'test_textmedium',
47
- 'type' => 'text_medium',
48
- ),
49
- array(
50
- 'name' => 'Test Date Picker',
51
- 'desc' => 'field description (optional)',
52
- 'id' => $prefix . 'test_textdate',
53
- 'type' => 'text_date',
54
- ),
55
- array(
56
- 'name' => 'Test Date Picker (UNIX timestamp)',
57
- 'desc' => 'field description (optional)',
58
- 'id' => $prefix . 'test_textdate_timestamp',
59
- 'type' => 'text_date_timestamp',
60
- ),
61
- array(
62
- 'name' => 'Test Date/Time Picker Combo (UNIX timestamp)',
63
- 'desc' => 'field description (optional)',
64
- 'id' => $prefix . 'test_datetime_timestamp',
65
- 'type' => 'text_datetime_timestamp',
66
- ),
67
- array(
68
- 'name' => 'Test Time',
69
- 'desc' => 'field description (optional)',
70
- 'id' => $prefix . 'test_time',
71
- 'type' => 'text_time',
72
- ),
73
- array(
74
- 'name' => 'Test Money',
75
- 'desc' => 'field description (optional)',
76
- 'id' => $prefix . 'test_textmoney',
77
- 'type' => 'text_money',
78
- ),
79
- array(
80
- 'name' => 'Test Color Picker',
81
- 'desc' => 'field description (optional)',
82
- 'id' => $prefix . 'test_colorpicker',
83
- 'type' => 'colorpicker',
84
- 'std' => '#ffffff'
85
- ),
86
- array(
87
- 'name' => 'Test Text Area',
88
- 'desc' => 'field description (optional)',
89
- 'id' => $prefix . 'test_textarea',
90
- 'type' => 'textarea',
91
- ),
92
- array(
93
- 'name' => 'Test Text Area Small',
94
- 'desc' => 'field description (optional)',
95
- 'id' => $prefix . 'test_textareasmall',
96
- 'type' => 'textarea_small',
97
- ),
98
- array(
99
- 'name' => 'Test Text Area Code',
100
- 'desc' => 'field description (optional)',
101
- 'id' => $prefix . 'test_textarea_code',
102
- 'type' => 'textarea_code',
103
- ),
104
- array(
105
- 'name' => 'Test Title Weeeee',
106
- 'desc' => 'This is a title description',
107
- 'id' => $prefix . 'test_title',
108
- 'type' => 'title',
109
- ),
110
- array(
111
- 'name' => 'Test Select',
112
- 'desc' => 'field description (optional)',
113
- 'id' => $prefix . 'test_select',
114
- 'type' => 'select',
115
- 'options' => array(
116
- array( 'name' => 'Option One', 'value' => 'standard', ),
117
- array( 'name' => 'Option Two', 'value' => 'custom', ),
118
- array( 'name' => 'Option Three', 'value' => 'none', ),
119
- ),
120
- ),
121
- array(
122
- 'name' => 'Test Radio inline',
123
- 'desc' => 'field description (optional)',
124
- 'id' => $prefix . 'test_radio_inline',
125
- 'type' => 'radio_inline',
126
- 'options' => array(
127
- array( 'name' => 'Option One', 'value' => 'standard', ),
128
- array( 'name' => 'Option Two', 'value' => 'custom', ),
129
- array( 'name' => 'Option Three', 'value' => 'none', ),
130
- ),
131
- ),
132
- array(
133
- 'name' => 'Test Radio',
134
- 'desc' => 'field description (optional)',
135
- 'id' => $prefix . 'test_radio',
136
- 'type' => 'radio',
137
- 'options' => array(
138
- array( 'name' => 'Option One', 'value' => 'standard', ),
139
- array( 'name' => 'Option Two', 'value' => 'custom', ),
140
- array( 'name' => 'Option Three', 'value' => 'none', ),
141
- ),
142
- ),
143
- array(
144
- 'name' => 'Test Taxonomy Radio',
145
- 'desc' => 'Description Goes Here',
146
- 'id' => $prefix . 'text_taxonomy_radio',
147
- 'type' => 'taxonomy_radio',
148
- 'taxonomy' => '', // Taxonomy Slug
149
- ),
150
- array(
151
- 'name' => 'Test Taxonomy Select',
152
- 'desc' => 'Description Goes Here',
153
- 'id' => $prefix . 'text_taxonomy_select',
154
- 'type' => 'taxonomy_select',
155
- 'taxonomy' => '', // Taxonomy Slug
156
- ),
157
- array(
158
- 'name' => 'Test Checkbox',
159
- 'desc' => 'field description (optional)',
160
- 'id' => $prefix . 'test_checkbox',
161
- 'type' => 'checkbox',
162
- ),
163
- array(
164
- 'name' => 'Test Multi Checkbox',
165
- 'desc' => 'field description (optional)',
166
- 'id' => $prefix . 'test_multicheckbox',
167
- 'type' => 'multicheck',
168
- 'options' => array(
169
- 'check1' => 'Check One',
170
- 'check2' => 'Check Two',
171
- 'check3' => 'Check Three',
172
- ),
173
- ),
174
- array(
175
- 'name' => 'Test wysiwyg',
176
- 'desc' => 'field description (optional)',
177
- 'id' => $prefix . 'test_wysiwyg',
178
- 'type' => 'wysiwyg',
179
- 'options' => array( 'textarea_rows' => 5, ),
180
- ),
181
- array(
182
- 'name' => 'Test Image',
183
- 'desc' => 'Upload an image or enter an URL.',
184
- 'id' => $prefix . 'test_image',
185
- 'type' => 'file',
186
- ),
187
- ),
188
- );
189
-
190
- $meta_boxes[] = array(
191
- 'id' => 'about_page_metabox',
192
- 'title' => 'About Page Metabox',
193
- 'pages' => array( 'page', ), // Post type
194
- 'context' => 'normal',
195
- 'priority' => 'high',
196
- 'show_names' => true, // Show field names on the left
197
- 'show_on' => array( 'key' => 'id', 'value' => array( 2, ), ), // Specific post IDs to display this metabox
198
- 'fields' => array(
199
- array(
200
- 'name' => 'Test Text',
201
- 'desc' => 'field description (optional)',
202
- 'id' => $prefix . 'test_text',
203
- 'type' => 'text',
204
- ),
205
- )
206
- );
207
-
208
- // Add other metaboxes as needed
209
-
210
- return $meta_boxes;
211
- }
212
-
213
- add_action( 'init', 'cmb_initialize_cmb_meta_boxes', 9999 );
214
- /**
215
- * Initialize the metabox class.
216
- */
217
- function cmb_initialize_cmb_meta_boxes() {
218
-
219
- if ( ! class_exists( 'cmb_Meta_Box' ) )
220
- require_once 'init.php';
221
-
222
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/images/ico-delete.png DELETED
Binary file
lib/metabox/images/ui-bg_flat_0_aaaaaa_40x100.png DELETED
Binary file
lib/metabox/images/ui-bg_flat_75_ffffff_40x100.png DELETED
Binary file
lib/metabox/images/ui-bg_glass_55_fbf9ee_1x400.png DELETED
Binary file
lib/metabox/images/ui-bg_glass_65_ffffff_1x400.png DELETED
Binary file
lib/metabox/images/ui-bg_glass_75_dadada_1x400.png DELETED
Binary file
lib/metabox/images/ui-bg_glass_75_e6e6e6_1x400.png DELETED
Binary file
lib/metabox/images/ui-bg_glass_95_fef1ec_1x400.png DELETED
Binary file
lib/metabox/images/ui-bg_highlight-soft_75_cccccc_1x100.png DELETED
Binary file
lib/metabox/images/ui-icons_222222_256x240.png DELETED
Binary file
lib/metabox/images/ui-icons_2e83ff_256x240.png DELETED
Binary file
lib/metabox/images/ui-icons_454545_256x240.png DELETED
Binary file
lib/metabox/images/ui-icons_888888_256x240.png DELETED
Binary file
lib/metabox/images/ui-icons_cd0a0a_256x240.png DELETED
Binary file
lib/metabox/init.php DELETED
@@ -1,569 +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
- Description: This will create metaboxes with custom fields that will blow your mind.
8
- Version: 0.9
9
- */
10
-
11
- /**
12
- * Released under the GPL license
13
- * http://www.opensource.org/licenses/gpl-license.php
14
- *
15
- * This is an add-on for WordPress
16
- * http://wordpress.org/
17
- *
18
- * **********************************************************************
19
- * This program is free software; you can redistribute it and/or modify
20
- * it under the terms of the GNU General Public License as published by
21
- * the Free Software Foundation; either version 2 of the License, or
22
- * (at your option) any later version.
23
- *
24
- * This program is distributed in the hope that it will be useful,
25
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
- * GNU General Public License for more details.
28
- * **********************************************************************
29
- */
30
-
31
- /************************************************************************
32
- You should not edit the code below or things might explode!
33
- *************************************************************************/
34
-
35
- $meta_boxes = array();
36
- $meta_boxes = apply_filters ( 'cmb_meta_boxes' , $meta_boxes );
37
- foreach ( $meta_boxes as $meta_box ) {
38
- $my_box = new cmb_Meta_Box( $meta_box );
39
- }
40
-
41
- /**
42
- * Validate value of meta fields
43
- * Define ALL validation methods inside this class and use the names of these
44
- * methods in the definition of meta boxes (key 'validate_func' of each field)
45
- */
46
- class cmb_Meta_Box_Validate {
47
- function check_text( $text ) {
48
- if ($text != 'hello') {
49
- return false;
50
- }
51
- return true;
52
- }
53
- }
54
-
55
- /**
56
- * Defines the url to which is used to load local resources.
57
- * This may need to be filtered for local Window installations.
58
- * If resources do not load, please check the wiki for details.
59
- */
60
- define( 'CMB_META_BOX_URL', apply_filters( 'cmb_meta_box_url', trailingslashit( str_replace( WP_CONTENT_DIR, WP_CONTENT_URL, dirname( __FILE__ ) ) ) ) );
61
-
62
- /**
63
- * Create meta boxes
64
- */
65
- class cmb_Meta_Box {
66
- protected $_meta_box;
67
-
68
- function __construct( $meta_box ) {
69
- if ( !is_admin() ) return;
70
-
71
- $this->_meta_box = $meta_box;
72
-
73
- $upload = false;
74
- foreach ( $meta_box['fields'] as $field ) {
75
- if ( $field['type'] == 'file' || $field['type'] == 'file_list' ) {
76
- $upload = true;
77
- break;
78
- }
79
- }
80
-
81
- global $pagenow;
82
- if ( $upload && in_array( $pagenow, array( 'page.php', 'page-new.php', 'post.php', 'post-new.php' ) ) ) {
83
- add_action( 'admin_head', array( &$this, 'add_post_enctype' ) );
84
- }
85
-
86
- add_action( 'admin_menu', array( &$this, 'add' ) );
87
- add_action( 'save_post', array( &$this, 'save' ) );
88
-
89
- add_filter( 'cmb_show_on', array( &$this, 'add_for_id' ), 10, 2 );
90
- add_filter( 'cmb_show_on', array( &$this, 'add_for_page_template' ), 10, 2 );
91
- }
92
-
93
- function add_post_enctype() {
94
- echo '
95
- <script type="text/javascript">
96
- jQuery(document).ready(function(){
97
- jQuery("#post").attr("enctype", "multipart/form-data");
98
- jQuery("#post").attr("encoding", "multipart/form-data");
99
- });
100
- </script>';
101
- }
102
-
103
- // Add metaboxes
104
- function add() {
105
- $this->_meta_box['context'] = empty($this->_meta_box['context']) ? 'normal' : $this->_meta_box['context'];
106
- $this->_meta_box['priority'] = empty($this->_meta_box['priority']) ? 'high' : $this->_meta_box['priority'];
107
- $this->_meta_box['show_on'] = empty( $this->_meta_box['show_on'] ) ? array('key' => false, 'value' => false) : $this->_meta_box['show_on'];
108
-
109
- foreach ( $this->_meta_box['pages'] as $page ) {
110
- if( apply_filters( 'cmb_show_on', true, $this->_meta_box ) )
111
- add_meta_box( $this->_meta_box['id'], $this->_meta_box['title'], array(&$this, 'show'), $page, $this->_meta_box['context'], $this->_meta_box['priority']) ;
112
- }
113
- }
114
-
115
- /**
116
- * Show On Filters
117
- * Use the 'cmb_show_on' filter to further refine the conditions under which a metabox is displayed.
118
- * Below you can limit it by ID and page template
119
- */
120
-
121
- // Add for ID
122
- function add_for_id( $display, $meta_box ) {
123
- if ( 'id' !== $meta_box['show_on']['key'] )
124
- return $display;
125
-
126
- // If we're showing it based on ID, get the current ID
127
- if( isset( $_GET['post'] ) ) $post_id = $_GET['post'];
128
- elseif( isset( $_POST['post_ID'] ) ) $post_id = $_POST['post_ID'];
129
- if( !isset( $post_id ) )
130
- return false;
131
-
132
- // If value isn't an array, turn it into one
133
- $meta_box['show_on']['value'] = !is_array( $meta_box['show_on']['value'] ) ? array( $meta_box['show_on']['value'] ) : $meta_box['show_on']['value'];
134
-
135
- // If current page id is in the included array, display the metabox
136
-
137
- if ( in_array( $post_id, $meta_box['show_on']['value'] ) )
138
- return true;
139
- else
140
- return false;
141
- }
142
-
143
- // Add for Page Template
144
- function add_for_page_template( $display, $meta_box ) {
145
- if( 'page-template' !== $meta_box['show_on']['key'] )
146
- return $display;
147
-
148
- // Get the current ID
149
- if( isset( $_GET['post'] ) ) $post_id = $_GET['post'];
150
- elseif( isset( $_POST['post_ID'] ) ) $post_id = $_POST['post_ID'];
151
- if( !( isset( $post_id ) || is_page() ) ) return false;
152
-
153
- // Get current template
154
- $current_template = get_post_meta( $post_id, '_wp_page_template', true );
155
-
156
- // If value isn't an array, turn it into one
157
- $meta_box['show_on']['value'] = !is_array( $meta_box['show_on']['value'] ) ? array( $meta_box['show_on']['value'] ) : $meta_box['show_on']['value'];
158
-
159
- // See if there's a match
160
- if( in_array( $current_template, $meta_box['show_on']['value'] ) )
161
- return true;
162
- else
163
- return false;
164
- }
165
-
166
- // Show fields
167
- function show() {
168
-
169
- global $post;
170
-
171
- // Use nonce for verification
172
- echo '<input type="hidden" name="wp_meta_box_nonce" value="', wp_create_nonce( basename(__FILE__) ), '" />';
173
- echo '<table class="form-table cmb_metabox">';
174
-
175
- foreach ( $this->_meta_box['fields'] as $field ) {
176
- // Set up blank or default values for empty ones
177
- if ( !isset( $field['name'] ) ) $field['name'] = '';
178
- if ( !isset( $field['desc'] ) ) $field['desc'] = '';
179
- if ( !isset( $field['std'] ) ) $field['std'] = '';
180
- if ( 'file' == $field['type'] && !isset( $field['allow'] ) ) $field['allow'] = array( 'url', 'attachment' );
181
- if ( 'file' == $field['type'] && !isset( $field['save_id'] ) ) $field['save_id'] = false;
182
- if ( 'multicheck' == $field['type'] ) $field['multiple'] = true;
183
-
184
- $meta = get_post_meta( $post->ID, $field['id'], 'multicheck' != $field['type'] /* If multicheck this can be multiple values */ );
185
-
186
- echo '<tr>';
187
-
188
- if ( $field['type'] == "title" ) {
189
- echo '<td colspan="2">';
190
- } else {
191
- if( $this->_meta_box['show_names'] == true ) {
192
- echo '<th style="width:18%"><label for="', $field['id'], '">', $field['name'], '</label></th>';
193
- }
194
- echo '<td>';
195
- }
196
-
197
- switch ( $field['type'] ) {
198
-
199
- case 'text':
200
- echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />','<p class="cmb_metabox_description">', $field['desc'], '</p>';
201
- break;
202
- case 'text_small':
203
- echo '<input class="cmb_text_small" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" /><span class="cmb_metabox_description">', $field['desc'], '</span>';
204
- break;
205
- case 'text_medium':
206
- echo '<input class="cmb_text_medium" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" /><span class="cmb_metabox_description">', $field['desc'], '</span>';
207
- break;
208
- case 'text_date':
209
- echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" /><span class="cmb_metabox_description">', $field['desc'], '</span>';
210
- break;
211
- case 'text_date_timestamp':
212
- 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'], '" /><span class="cmb_metabox_description">', $field['desc'], '</span>';
213
- break;
214
-
215
- case 'text_datetime_timestamp':
216
- 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'], '" />';
217
- 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'], '" /><span class="cmb_metabox_description" >', $field['desc'], '</span>';
218
- break;
219
- case 'text_time':
220
- echo '<input class="cmb_timepicker text_time" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" /><span class="cmb_metabox_description">', $field['desc'], '</span>';
221
- break;
222
- case 'text_money':
223
- echo '$ <input class="cmb_text_money" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" /><span class="cmb_metabox_description">', $field['desc'], '</span>';
224
- break;
225
- case 'colorpicker':
226
- $meta = '' !== $meta ? $meta : $field['std'];
227
- $hex_color = '(([a-fA-F0-9]){3}){1,2}$';
228
- if ( preg_match( '/^' . $hex_color . '/i', $meta ) ) // Value is just 123abc, so prepend #.
229
- $meta = '#' . $meta;
230
- elseif ( ! preg_match( '/^#' . $hex_color . '/i', $meta ) ) // Value doesn't match #123abc, so sanitize to just #.
231
- $meta = "#";
232
- echo '<input class="cmb_colorpicker cmb_text_small" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta, '" /><span class="cmb_metabox_description">', $field['desc'], '</span>';
233
- break;
234
- case 'textarea':
235
- echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="10">', '' !== $meta ? $meta : $field['std'], '</textarea>','<p class="cmb_metabox_description">', $field['desc'], '</p>';
236
- break;
237
- case 'textarea_small':
238
- echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="4">', '' !== $meta ? $meta : $field['std'], '</textarea>','<p class="cmb_metabox_description">', $field['desc'], '</p>';
239
- break;
240
- case 'textarea_code':
241
- echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="10" class="cmb_textarea_code">', '' !== $meta ? $meta : $field['std'], '</textarea>','<p class="cmb_metabox_description">', $field['desc'], '</p>';
242
- break;
243
- case 'select':
244
- if( empty( $meta ) && !empty( $field['std'] ) ) $meta = $field['std'];
245
- echo '<select name="', $field['id'], '" id="', $field['id'], '">';
246
- foreach ($field['options'] as $option) {
247
- echo '<option value="', $option['value'], '"', $meta == $option['value'] ? ' selected="selected"' : '', '>', $option['name'], '</option>';
248
- }
249
- echo '</select>';
250
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
251
- break;
252
- case 'radio_inline':
253
- if( empty( $meta ) && !empty( $field['std'] ) ) $meta = $field['std'];
254
- echo '<div class="cmb_radio_inline">';
255
- $i = 1;
256
- foreach ($field['options'] as $option) {
257
- echo '<div class="cmb_radio_inline_option"><input type="radio" name="', $field['id'], '" id="', $field['id'], $i, '" value="', $option['value'], '"', $meta == $option['value'] ? ' checked="checked"' : '', ' /><label for="', $field['id'], $i, '">', $option['name'], '</label></div>';
258
- $i++;
259
- }
260
- echo '</div>';
261
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
262
- break;
263
- case 'radio':
264
- if( empty( $meta ) && !empty( $field['std'] ) ) $meta = $field['std'];
265
- echo '<ul>';
266
- $i = 1;
267
- foreach ($field['options'] as $option) {
268
- echo '<li><input type="radio" name="', $field['id'], '" id="', $field['id'], $i,'" value="', $option['value'], '"', $meta == $option['value'] ? ' checked="checked"' : '', ' /><label for="', $field['id'], $i, '">', $option['name'].'</label></li>';
269
- $i++;
270
- }
271
- echo '</ul>';
272
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
273
- break;
274
- case 'checkbox':
275
- echo '<input type="checkbox" name="', $field['id'], '" id="', $field['id'], '"', $meta ? ' checked="checked"' : '', ' />';
276
- echo '<span class="cmb_metabox_description">', $field['desc'], '</span>';
277
- break;
278
- case 'multicheck':
279
- echo '<ul>';
280
- $i = 1;
281
- foreach ( $field['options'] as $value => $name ) {
282
- // Append `[]` to the name to get multiple values
283
- // Use in_array() to check whether the current option should be checked
284
- echo '<li><input type="checkbox" name="', $field['id'], '[]" id="', $field['id'], $i, '" value="', $value, '"', in_array( $value, $meta ) ? ' checked="checked"' : '', ' /><label for="', $field['id'], $i, '">', $name, '</label></li>';
285
- $i++;
286
- }
287
- echo '</ul>';
288
- echo '<span class="cmb_metabox_description">', $field['desc'], '</span>';
289
- break;
290
- case 'title':
291
- echo '<h5 class="cmb_metabox_title">', $field['name'], '</h5>';
292
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
293
- break;
294
- case 'wysiwyg':
295
- wp_editor( $meta ? $meta : $field['std'], $field['id'], isset( $field['options'] ) ? $field['options'] : array() );
296
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
297
- break;
298
- case 'taxonomy_select':
299
- echo '<select name="', $field['id'], '" id="', $field['id'], '">';
300
- $names= wp_get_object_terms( $post->ID, $field['taxonomy'] );
301
- $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
302
- foreach ( $terms as $term ) {
303
- if (!is_wp_error( $names ) && !empty( $names ) && !strcmp( $term->slug, $names[0]->slug ) ) {
304
- echo '<option value="' . $term->slug . '" selected>' . $term->name . '</option>';
305
- } else {
306
- echo '<option value="' . $term->slug . ' ' , $meta == $term->slug ? $meta : ' ' ,' ">' . $term->name . '</option>';
307
- }
308
- }
309
- echo '</select>';
310
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
311
- break;
312
- case 'taxonomy_radio':
313
- $names= wp_get_object_terms( $post->ID, $field['taxonomy'] );
314
- $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
315
- echo '<ul>';
316
- foreach ( $terms as $term ) {
317
- if ( !is_wp_error( $names ) && !empty( $names ) && !strcmp( $term->slug, $names[0]->slug ) ) {
318
- echo '<li><input type="radio" name="', $field['id'], '" value="'. $term->slug . '" checked>' . $term->name . '</li>';
319
- } else {
320
- echo '<li><input type="radio" name="', $field['id'], '" value="' . $term->slug . ' ' , $meta == $term->slug ? $meta : ' ' ,' ">' . $term->name .'</li>';
321
- }
322
- }
323
- echo '</ul>';
324
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
325
- break;
326
- case 'taxonomy_multicheck':
327
- echo '<ul>';
328
- $names = wp_get_object_terms( $post->ID, $field['taxonomy'] );
329
- $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
330
- foreach ($terms as $term) {
331
- echo '<li><input type="checkbox" name="', $field['id'], '[]" id="', $field['id'], '" value="', $term->name , '"';
332
- foreach ($names as $name) {
333
- if ( $term->slug == $name->slug ){ echo ' checked="checked" ';};
334
- }
335
- echo' /><label>', $term->name , '</label></li>';
336
- }
337
- break;
338
- case 'file_list':
339
- echo '<input class="cmb_upload_file" type="text" size="36" name="', $field['id'], '" value="" />';
340
- echo '<input class="cmb_upload_button button" type="button" value="Upload File" />';
341
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
342
- $args = array(
343
- 'post_type' => 'attachment',
344
- 'numberposts' => null,
345
- 'post_status' => null,
346
- 'post_parent' => $post->ID
347
- );
348
- $attachments = get_posts($args);
349
- if ($attachments) {
350
- echo '<ul class="attach_list">';
351
- foreach ($attachments as $attachment) {
352
- echo '<li>'.wp_get_attachment_link($attachment->ID, 'thumbnail', 0, 0, 'Download');
353
- echo '<span>';
354
- echo apply_filters('the_title', '&nbsp;'.$attachment->post_title);
355
- echo '</span></li>';
356
- }
357
- echo '</ul>';
358
- }
359
- break;
360
- case 'file':
361
- $input_type_url = "hidden";
362
- if ( 'url' == $field['allow'] || ( is_array( $field['allow'] ) && in_array( 'url', $field['allow'] ) ) )
363
- $input_type_url="text";
364
- echo '<input class="cmb_upload_file" type="' . $input_type_url . '" size="45" id="', $field['id'], '" name="', $field['id'], '" value="', $meta, '" />';
365
- echo '<input class="cmb_upload_button button" type="button" value="Upload File" />';
366
- echo '<input class="cmb_upload_file_id" type="hidden" id="', $field['id'], '_id" name="', $field['id'], '_id" value="', get_post_meta( $post->ID, $field['id'] . "_id",true), '" />';
367
- echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
368
- echo '<div id="', $field['id'], '_status" class="cmb_upload_status">';
369
- if ( $meta != '' ) {
370
- $check_image = preg_match( '/(^.*\.jpg|jpeg|png|gif|ico*)/i', $meta );
371
- if ( $check_image ) {
372
- echo '<div class="img_status">';
373
- echo '<img src="', $meta, '" alt="" />';
374
- echo '<a href="#" class="cmb_remove_file_button" rel="', $field['id'], '">Remove Image</a>';
375
- echo '</div>';
376
- } else {
377
- $parts = explode( '/', $meta );
378
- for( $i = 0; $i < count( $parts ); ++$i ) {
379
- $title = $parts[$i];
380
- }
381
- echo 'File: <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $meta, '" target="_blank" rel="external">Download</a> / <a href="#" class="cmb_remove_file_button" rel="', $field['id'], '">Remove</a>)';
382
- }
383
- }
384
- echo '</div>';
385
- break;
386
- default:
387
- do_action('cmb_render_' . $field['type'] , $field, $meta);
388
- }
389
-
390
- echo '</td>','</tr>';
391
- }
392
- echo '</table>';
393
- }
394
-
395
- // Save data from metabox
396
- function save( $post_id) {
397
-
398
- // verify nonce
399
- if ( ! isset( $_POST['wp_meta_box_nonce'] ) || !wp_verify_nonce( $_POST['wp_meta_box_nonce'], basename(__FILE__) ) ) {
400
- return $post_id;
401
- }
402
-
403
- // check autosave
404
- if ( defined('DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
405
- return $post_id;
406
- }
407
-
408
- // check permissions
409
- if ( 'page' == $_POST['post_type'] ) {
410
- if ( !current_user_can( 'edit_page', $post_id ) ) {
411
- return $post_id;
412
- }
413
- } elseif ( !current_user_can( 'edit_post', $post_id ) ) {
414
- return $post_id;
415
- }
416
-
417
- foreach ( $this->_meta_box['fields'] as $field ) {
418
- $name = $field['id'];
419
-
420
- if ( ! isset( $field['multiple'] ) )
421
- $field['multiple'] = ( 'multicheck' == $field['type'] ) ? true : false;
422
-
423
- $old = get_post_meta( $post_id, $name, !$field['multiple'] /* If multicheck this can be multiple values */ );
424
- $new = isset( $_POST[$field['id']] ) ? $_POST[$field['id']] : null;
425
-
426
- if ( in_array( $field['type'], array( 'taxonomy_select', 'taxonomy_radio', 'taxonomy_multicheck' ) ) ) {
427
- $new = wp_set_object_terms( $post_id, $new, $field['taxonomy'] );
428
- }
429
-
430
- if ( ($field['type'] == 'textarea') || ($field['type'] == 'textarea_small') ) {
431
- $new = htmlspecialchars( $new );
432
- }
433
-
434
- if ( ($field['type'] == 'textarea_code') ) {
435
- $new = htmlspecialchars_decode( $new );
436
- }
437
-
438
- if ( $field['type'] == 'text_date_timestamp' ) {
439
- $new = strtotime( $new );
440
- }
441
-
442
- if ( $field['type'] == 'text_datetime_timestamp' ) {
443
- $string = $new['date'] . ' ' . $new['time'];
444
- $new = strtotime( $string );
445
- }
446
-
447
- $new = apply_filters('cmb_validate_' . $field['type'], $new, $post_id, $field);
448
-
449
- // validate meta value
450
- if ( isset( $field['validate_func']) ) {
451
- $ok = call_user_func( array( 'cmb_Meta_Box_Validate', $field['validate_func']), $new );
452
- if ( $ok === false ) { // pass away when meta value is invalid
453
- continue;
454
- }
455
- } elseif ( $field['multiple'] ) {
456
- delete_post_meta( $post_id, $name );
457
- if ( !empty( $new ) ) {
458
- foreach ( $new as $add_new ) {
459
- add_post_meta( $post_id, $name, $add_new, false );
460
- }
461
- }
462
- } elseif ( '' !== $new && $new != $old ) {
463
- update_post_meta( $post_id, $name, $new );
464
- } elseif ( '' == $new ) {
465
- delete_post_meta( $post_id, $name );
466
- }
467
-
468
- if ( 'file' == $field['type'] ) {
469
- $name = $field['id'] . "_id";
470
- $old = get_post_meta( $post_id, $name, !$field['multiple'] /* If multicheck this can be multiple values */ );
471
- if ( isset( $field['save_id'] ) && $field['save_id'] ) {
472
- $new = isset( $_POST[$name] ) ? $_POST[$name] : null;
473
- } else {
474
- $new = "";
475
- }
476
-
477
- if ( $new && $new != $old ) {
478
- update_post_meta( $post_id, $name, $new );
479
- } elseif ( '' == $new && $old ) {
480
- delete_post_meta( $post_id, $name, $old );
481
- }
482
- }
483
- }
484
- }
485
- }
486
-
487
- /**
488
- * Adding scripts and styles
489
- */
490
- function cmb_scripts( $hook ) {
491
- if ( $hook == 'post.php' || $hook == 'post-new.php' || $hook == 'page-new.php' || $hook == 'page.php' ) {
492
- wp_register_script( 'cmb-timepicker', CMB_META_BOX_URL . 'js/jquery.timePicker.min.js' );
493
- wp_register_script( 'cmb-scripts', CMB_META_BOX_URL . 'js/cmb.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-datepicker', 'media-upload', 'thickbox', 'farbtastic' ) );
494
- wp_enqueue_script( 'cmb-timepicker' );
495
- wp_enqueue_script( 'cmb-scripts' );
496
- wp_register_style( 'cmb-styles', CMB_META_BOX_URL . 'style.css', array( 'thickbox', 'farbtastic' ) );
497
- wp_enqueue_style( 'cmb-styles' );
498
- }
499
- }
500
- add_action( 'admin_enqueue_scripts', 'cmb_scripts', 10 );
501
-
502
- function cmb_editor_footer_scripts() { ?>
503
- <?php
504
- if ( isset( $_GET['cmb_force_send'] ) && 'true' == $_GET['cmb_force_send'] ) {
505
- $label = $_GET['cmb_send_label'];
506
- if ( empty( $label ) ) $label="Select File";
507
- ?>
508
- <script type="text/javascript">
509
- jQuery(function($) {
510
- $('td.savesend input').val('<?php echo $label; ?>');
511
- });
512
- </script>
513
- <?php
514
- }
515
- }
516
- add_action( 'admin_print_footer_scripts', 'cmb_editor_footer_scripts', 99 );
517
-
518
- // Force 'Insert into Post' button from Media Library
519
- add_filter( 'get_media_item_args', 'cmb_force_send' );
520
- function cmb_force_send( $args ) {
521
-
522
- // if the Gallery tab is opened from a custom meta box field, add Insert Into Post button
523
- if ( isset( $_GET['cmb_force_send'] ) && 'true' == $_GET['cmb_force_send'] )
524
- $args['send'] = true;
525
-
526
- // if the From Computer tab is opened AT ALL, add Insert Into Post button after an image is uploaded
527
- if ( isset( $_POST['attachment_id'] ) && '' != $_POST["attachment_id"] ) {
528
-
529
- $args['send'] = true;
530
-
531
- // TO DO: Are there any conditions in which we don't want the Insert Into Post
532
- // button added? For example, if a post type supports thumbnails, does not support
533
- // the editor, and does not have any cmb file inputs? If so, here's the first
534
- // bits of code needed to check all that.
535
- // $attachment_ancestors = get_post_ancestors( $_POST["attachment_id"] );
536
- // $attachment_parent_post_type = get_post_type( $attachment_ancestors[0] );
537
- // $post_type_object = get_post_type_object( $attachment_parent_post_type );
538
- }
539
-
540
- // change the label of the button on the From Computer tab
541
- if ( isset( $_POST['attachment_id'] ) && '' != $_POST["attachment_id"] ) {
542
-
543
- echo '
544
- <script type="text/javascript">
545
- function cmbGetParameterByNameInline(name) {
546
- name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
547
- var regexS = "[\\?&]" + name + "=([^&#]*)";
548
- var regex = new RegExp(regexS);
549
- var results = regex.exec(window.location.href);
550
- if(results == null)
551
- return "";
552
- else
553
- return decodeURIComponent(results[1].replace(/\+/g, " "));
554
- }
555
-
556
- jQuery(function($) {
557
- if (cmbGetParameterByNameInline("cmb_force_send")=="true") {
558
- var cmb_send_label = cmbGetParameterByNameInline("cmb_send_label");
559
- $("td.savesend input").val(cmb_send_label);
560
- }
561
- });
562
- </script>
563
- ';
564
- }
565
-
566
- return $args;
567
-
568
- }
569
- // End. That's it, folks! //
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/js/cmb.js DELETED
@@ -1,128 +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
- * @see https://github.com/jaredatch/Custom-Metaboxes-and-Fields-for-WordPress
8
- */
9
-
10
- /*jslint browser: true, devel: true, indent: 4, maxerr: 50, sub: true */
11
- /*global jQuery, tb_show, tb_remove */
12
-
13
- /**
14
- * Custom jQuery for Custom Metaboxes and Fields
15
- */
16
- jQuery(document).ready(function ($) {
17
- 'use strict';
18
-
19
- var formfield;
20
-
21
- /**
22
- * Initialize timepicker (this will be moved inline in a future release)
23
- */
24
- $('.cmb_timepicker').each(function () {
25
- $('#' + jQuery(this).attr('id')).timePicker({
26
- startTime: "07:00",
27
- endTime: "22:00",
28
- show24Hours: false,
29
- separator: ':',
30
- step: 30
31
- });
32
- });
33
-
34
- /**
35
- * Initialize jQuery UI datepicker (this will be moved inline in a future release)
36
- */
37
- $('.cmb_datepicker').each(function () {
38
- $('#' + jQuery(this).attr('id')).datepicker();
39
- // $('#' + jQuery(this).attr('id')).datepicker({ dateFormat: 'yy-mm-dd' });
40
- // For more options see http://jqueryui.com/demos/datepicker/#option-dateFormat
41
- });
42
- // Wrap date picker in class to narrow the scope of jQuery UI CSS and prevent conflicts
43
- $("#ui-datepicker-div").wrap('<div class="cmb_element" />');
44
-
45
- /**
46
- * Initialize color picker
47
- */
48
- $('input:text.cmb_colorpicker').each(function (i) {
49
- $(this).after('<div id="picker-' + i + '" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
50
- $('#picker-' + i).hide().farbtastic($(this));
51
- })
52
- .focus(function() {
53
- $(this).next().show();
54
- })
55
- .blur(function() {
56
- $(this).next().hide();
57
- });
58
-
59
- /**
60
- * File and image upload handling
61
- */
62
- $('.cmb_upload_file').change(function () {
63
- formfield = $(this).attr('name');
64
- $('#' + formfield + '_id').val("");
65
- });
66
-
67
- $('.cmb_upload_button').live('click', function () {
68
- var buttonLabel;
69
- formfield = $(this).prev('input').attr('name');
70
- buttonLabel = 'Use as ' + $('label[for=' + formfield + ']').text();
71
- tb_show('', 'media-upload.php?post_id=' + $('#post_ID').val() + '&type=file&cmb_force_send=true&cmb_send_label=' + buttonLabel + '&TB_iframe=true');
72
- return false;
73
- });
74
-
75
- $('.cmb_remove_file_button').live('click', function () {
76
- formfield = $(this).attr('rel');
77
- $('input#' + formfield).val('');
78
- $('input#' + formfield + '_id').val('');
79
- $(this).parent().remove();
80
- return false;
81
- });
82
-
83
- window.original_send_to_editor = window.send_to_editor;
84
- window.send_to_editor = function (html) {
85
- var itemurl, itemclass, itemClassBits, itemid, htmlBits, itemtitle,
86
- image, uploadStatus = true;
87
-
88
- if (formfield) {
89
-
90
- if ($(html).html(html).find('img').length > 0) {
91
- itemurl = $(html).html(html).find('img').attr('src'); // Use the URL to the size selected.
92
- itemclass = $(html).html(html).find('img').attr('class'); // Extract the ID from the returned class name.
93
- itemClassBits = itemclass.split(" ");
94
- itemid = itemClassBits[itemClassBits.length - 1];
95
- itemid = itemid.replace('wp-image-', '');
96
- } else {
97
- // It's not an image. Get the URL to the file instead.
98
- htmlBits = html.split("'"); // jQuery seems to strip out XHTML when assigning the string to an object. Use alternate method.
99
- itemurl = htmlBits[1]; // Use the URL to the file.
100
- itemtitle = htmlBits[2];
101
- itemtitle = itemtitle.replace('>', '');
102
- itemtitle = itemtitle.replace('</a>', '');
103
- itemid = ""; // TO DO: Get ID for non-image attachments.
104
- }
105
-
106
- image = /(jpe?g|png|gif|ico)$/gi;
107
-
108
- if (itemurl.match(image)) {
109
- uploadStatus = '<div class="img_status"><img src="' + itemurl + '" alt="" /><a href="#" class="cmb_remove_file_button" rel="' + formfield + '">Remove Image</a></div>';
110
- } else {
111
- // No output preview if it's not an image
112
- // Standard generic output if it's not an image.
113
- html = '<a href="' + itemurl + '" target="_blank" rel="external">View File</a>';
114
- uploadStatus = '<div class="no_image"><span class="file_link">' + html + '</span>&nbsp;&nbsp;&nbsp;<a href="#" class="cmb_remove_file_button" rel="' + formfield + '">Remove</a></div>';
115
- }
116
-
117
- $('#' + formfield).val(itemurl);
118
- $('#' + formfield + '_id').val(itemid);
119
- $('#' + formfield).siblings('.cmb_upload_status').slideDown().html(uploadStatus);
120
- tb_remove();
121
-
122
- } else {
123
- window.original_send_to_editor(html);
124
- }
125
-
126
- formfield = '';
127
- };
128
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/js/jquery.timePicker.min.js DELETED
@@ -1,13 +0,0 @@
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/metabox/readme.md DELETED
@@ -1,121 +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
-
9
- **Version**: 0.9
10
- **Requires at least**: 3.3
11
- **Tested up to**: 3.3
12
- **License**: GPLv2
13
-
14
- ## Description
15
-
16
- Custom Metaboxes and Fields (CMB for short) will create metaboxes with custom fields that will blow your mind.
17
-
18
- ##### Links
19
- * [Github project page](http://github.com/jaredatch/Custom-Metaboxes-and-Fields-for-WordPress)
20
- * [Documentation (GitHub wiki)](http://github.com/jaredatch/Custom-Metaboxes-and-Fields-for-WordPress/wiki)
21
-
22
- ##### Field Types:
23
- * text
24
- * text small
25
- * text medium
26
- * text money
27
- * date picker
28
- * date picker (unix timestamp)
29
- * date time picker combo (unix timestamp)
30
- * time picker
31
- * color picker
32
- * textarea
33
- * textarea small
34
- * textarea code
35
- * select
36
- * radio
37
- * radio inline
38
- * taxonomy radio
39
- * taxonomy select
40
- * checkbox
41
- * multicheck
42
- * WYSIWYG/TinyMCE
43
- * Image/file upload
44
-
45
- [More on field types (GitHub wiki)](github.com/jaredatch/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types)
46
-
47
- ## Installation
48
-
49
- This script is easy to install. If you can't figure it out you probably shouldn't be using it.
50
-
51
- 1. Place `metabox` directory inside of your (activated) theme. E.g. inside `/themes/twentyten/lib/metabox/`.
52
- 2. Include `init.php`.
53
- 3. See `example-functions.php` for further guidance.
54
- 4. Profit.
55
-
56
- ## Known Issues
57
-
58
- * Problem inserting file url inside field for image with caption (issue #50)
59
- * `CMB_META_BOX_URL` does not define properly in WAMP/XAMP (Windows) (issue #31)
60
- * Metabox containing WYSIWYG editor cannot be moved (this is a TinyMCE issue)
61
-
62
- ## To-do
63
- * Fix known issues (above)
64
- * clean up code
65
- * improve inline documentation
66
- * move timepicker and datepicker jQuery inline
67
- * support for multiple configurable timepickers/datepickers
68
- * add ability to save fields in a single custom field
69
- * add ability to mark fields as required
70
- * add ability to define `placeholder` text
71
- * repeatable fields
72
- * look at possiblity of tabs
73
- * look at preserving taxonomy hierarchies
74
-
75
- ## Changelog
76
-
77
- ### 0.9
78
- * __Note: This release requires WordPress 3.3+__
79
- * Cleaned up scripts being queued, props @jaredatch
80
- * Cleaned up and reorganized jQuery, props @GaryJones
81
- * Use $pagenow instead of custom $current_page, props @jaredatch
82
- * Fixed CSS, removed inline styles, now all in style.css, props @jaredatch
83
- * Fixed multicheck issues (issue #48), props @jaredatch
84
- * Fixed jQuery UI datepicker CSS conflicting with WordPress UI elements, props @jaredatch
85
- * Fixed zeros not saving in fields, props @GaryJones
86
- * Fixed improper labels on radio and multicheck fields, props @jaredatch
87
- * Fixed fields not rendering properly when in sidebar, props @jaredatch
88
- * Fixed bug where datepicker triggers extra space after footer in Firefox (issue #14), props @jaredatch
89
- * Added jQuery UI datepicker packaged with 3.3 core, props @jaredatch
90
- * Added date time combo picker, props @jaredatch
91
- * Added color picker, props @jaredatch
92
- * Added readme.md markdown file, props @jaredatch
93
-
94
- ### 0.8
95
- * Added jQuery timepicker, props @norcross
96
- * Added 'raw' textarea to convert special HTML entities back to characters, props @norcross
97
- * Added missing examples on example-functions.php, props @norcross
98
-
99
- ### 0.7
100
- * Added the new wp_editor() function for the WYSIWYG dialog box, props @jcpry
101
- * Created 'cmb_show_on' filter to define your own Show On Filters, props @billerickson
102
- * Added page template show_on filter, props @billerickson
103
- * Improvements to the 'file' field type, props @randyhoyt
104
- * Allow for default values on 'radio' and 'radio_inline' field types, props @billerickson
105
-
106
- ### 0.6.1
107
- * Enabled the ability to define your own custom field types (issue #28). props @randyhoyt
108
-
109
- ### 0.6
110
- * Added the ability to limit metaboxes to certain posts by id. props @billerickson
111
-
112
- ### 0.5
113
- * Fixed define to prevent notices. props @destos
114
- * Added text_date_timestap option. props @andrewyno
115
- * Fixed WYSIWYG paragraph breaking/spacing bug. props @wpsmith
116
- * Added taxonomy_radio and taxonomies_select options. props @c3mdigital
117
- * Fixed script causing the dashboard widgets to not be collapsible.
118
- * Fixed various spacing and whitespace inconsistencies
119
-
120
- ### 0.4
121
- * Think we have a release that is mostly working. We'll say the initial release :)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/style.css DELETED
@@ -1,329 +0,0 @@
1
- /**
2
- * CMB Styling
3
- */
4
- table.cmb_metabox td, table.cmb_metabox th { border-bottom: 1px solid #E9E9E9; }
5
- table.cmb_metabox th { text-align: right; font-weight:bold;}
6
- table.cmb_metabox th label { margin-top:5px; display:block;}
7
- p.cmb_metabox_description { color: #AAA; font-style: italic; margin: 2px 0 !important;}
8
- span.cmb_metabox_description { color: #AAA; font-style: italic;}
9
- table.cmb_metabox input, table.cmb_metabox textarea { font-size:12px; padding: 5px; }
10
- table.cmb_metabox input[type=text], table.cmb_metabox textarea { width: 97%; }
11
- table.cmb_metabox textarea.cmb_textarea_code { font-family: Consolas,Monaco,monospace; line-height: 16px; }
12
- table.cmb_metabox input.cmb_text_small { width: 100px; margin-right: 15px;}
13
- table.cmb_metabox input.cmb_timepicker { width: 100px; margin-right: 15px;}
14
- table.cmb_metabox input.cmb_text_money { width: 90px; margin-right: 15px;}
15
- table.cmb_metabox input.cmb_text_medium { width: 230px; margin-right: 15px;}
16
- table.cmb_metabox input.cmb_upload_file { width: 65%; }
17
- table.cmb_metabox li { font-size:12px; margin: 1px 0 5px 0; line-height: 16px; }
18
- table.cmb_metabox ul { padding-top:5px; margin: 0; }
19
- table.cmb_metabox select { font-size:12px; margin-top: 3px;}
20
- table.cmb_metabox input:focus, table.cmb_metabox textarea:focus { background: #fffff8;}
21
- .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;}
22
- .cmb_radio_inline { padding: 4px 0 0 0;}
23
- .cmb_radio_inline_option {display: inline; padding-right: 18px;}
24
- table.cmb_metabox input[type="radio"] { margin: 0 5px 0 0; padding: 0;}
25
- table.cmb_metabox input[type="checkbox"] { margin: 0 5px 0 0; padding: 0;}
26
- table.cmb_metabox .mceLayout {border:1px solid #DFDFDF !important;}
27
- table.cmb_metabox .mceIframeContainer {background:#FFF;}
28
- table.cmb_metabox .meta_mce {width:97%;}
29
- table.cmb_metabox .meta_mce textarea {width:100%;}
30
- table.cmb_metabox .cmb_upload_status { margin: 10px 0 0 0;}
31
- table.cmb_metabox .cmb_upload_status .img_status { position: relative; }
32
- table.cmb_metabox .cmb_upload_status .img_status img { border:1px solid #DFDFDF; background: #FAFAFA; max-width:350px; padding: 5px; -moz-border-radius: 2px; border-radius: 2px;}
33
- table.cmb_metabox .cmb_upload_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;}
34
- /* Sidebar placement adjustments */
35
- .inner-sidebar table.cmb_metabox input[type=text], table.cmb_metabox textarea { width: 95%; }
36
- .inner-sidebar table.cmb_metabox .cmb_upload_status .img_status img { width: 90%; }
37
-
38
- /**
39
- * Timepicker
40
- */
41
- 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;}
42
- div.time-picker-12hours { width:8em; /* needed for IE */}
43
- div.time-picker ul { list-style-type: none; margin: 0; padding: 0; }
44
- div.time-picker li { cursor: pointer; height: 10px; font: 12px/1 Helvetica, Arial, sans-serif; padding: 4px 3px; }
45
- div.time-picker li.selected { background: #0063CE; color: #fff; }
46
-
47
- /**
48
- * jQuery UI CSS Framework 1.8.16
49
- *
50
- * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
51
- * Dual licensed under the MIT or GPL Version 2 licenses.
52
- * http://jquery.org/license
53
- *
54
- * http://docs.jquery.com/UI/Theming/API
55
- */
56
- .cmb_element .ui-helper-hidden { display: none; }
57
- .cmb_element .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
58
- .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; }
59
- .cmb_element .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
60
- .cmb_element .ui-helper-clearfix { display: inline-block; }
61
- * html .ui-helper-clearfix { height:1%; }
62
- .cmb_element .ui-helper-clearfix { display:block; }
63
- .cmb_element .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
64
- .cmb_element .ui-state-disabled { cursor: default !important; }
65
- .cmb_element .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
66
- .cmb_element .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
67
- .cmb_element .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
68
- .cmb_element .ui-widget .ui-widget { font-size: 1em; }
69
- .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; }
70
- .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; }
71
- .cmb_element .ui-widget-content a { color: #222222; }
72
- .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; }
73
- .cmb_element .ui-widget-header a { color: #222222; }
74
- .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; }
75
- .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; }
76
- .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; }
77
- .cmb_element .ui-state-hover a, .cmb_element .ui-state-hover a:hover { color: #212121; text-decoration: none; }
78
- .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; }
79
- .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; }
80
- .cmb_element .ui-widget :active { outline: none; }
81
- .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; }
82
- .cmb_element .ui-state-highlight a, .cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
83
- .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; }
84
- .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; }
85
- .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; }
86
- .cmb_element .ui-priority-primary, .cmb_element .ui-widget-content .ui-priority-primary, .cmb_element .ui-widget-header .ui-priority-primary { font-weight: bold; }
87
- .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; }
88
- .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; }
89
- .cmb_element .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
90
- .cmb_element .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
91
- .cmb_element .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
92
- .cmb_element .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
93
- .cmb_element .ui-state-hover .ui-icon, .cmb_element .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
94
- .cmb_element .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
95
- .cmb_element .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
96
- .cmb_element .ui-state-error .ui-icon, .cmb_element .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
97
- .cmb_element .ui-icon-carat-1-n { background-position: 0 0; }
98
- .cmb_element .ui-icon-carat-1-ne { background-position: -16px 0; }
99
- .cmb_element .ui-icon-carat-1-e { background-position: -32px 0; }
100
- .cmb_element .ui-icon-carat-1-se { background-position: -48px 0; }
101
- .cmb_element .ui-icon-carat-1-s { background-position: -64px 0; }
102
- .cmb_element .ui-icon-carat-1-sw { background-position: -80px 0; }
103
- .cmb_element .ui-icon-carat-1-w { background-position: -96px 0; }
104
- .cmb_element .ui-icon-carat-1-nw { background-position: -112px 0; }
105
- .cmb_element .ui-icon-carat-2-n-s { background-position: -128px 0; }
106
- .cmb_element .ui-icon-carat-2-e-w { background-position: -144px 0; }
107
- .cmb_element .ui-icon-triangle-1-n { background-position: 0 -16px; }
108
- .cmb_element .ui-icon-triangle-1-ne { background-position: -16px -16px; }
109
- .cmb_element .ui-icon-triangle-1-e { background-position: -32px -16px; }
110
- .cmb_element .ui-icon-triangle-1-se { background-position: -48px -16px; }
111
- .cmb_element .ui-icon-triangle-1-s { background-position: -64px -16px; }
112
- .cmb_element .ui-icon-triangle-1-sw { background-position: -80px -16px; }
113
- .cmb_element .ui-icon-triangle-1-w { background-position: -96px -16px; }
114
- .cmb_element .ui-icon-triangle-1-nw { background-position: -112px -16px; }
115
- .cmb_element .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
116
- .cmb_element .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
117
- .cmb_element .ui-icon-arrow-1-n { background-position: 0 -32px; }
118
- .cmb_element .ui-icon-arrow-1-ne { background-position: -16px -32px; }
119
- .cmb_element .ui-icon-arrow-1-e { background-position: -32px -32px; }
120
- .cmb_element .ui-icon-arrow-1-se { background-position: -48px -32px; }
121
- .cmb_element .ui-icon-arrow-1-s { background-position: -64px -32px; }
122
- .cmb_element .ui-icon-arrow-1-sw { background-position: -80px -32px; }
123
- .cmb_element .ui-icon-arrow-1-w { background-position: -96px -32px; }
124
- .cmb_element .ui-icon-arrow-1-nw { background-position: -112px -32px; }
125
- .cmb_element .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
126
- .cmb_element .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
127
- .cmb_element .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
128
- .cmb_element .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
129
- .cmb_element .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
130
- .cmb_element .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
131
- .cmb_element .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
132
- .cmb_element .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
133
- .cmb_element .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
134
- .cmb_element .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
135
- .cmb_element .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
136
- .cmb_element .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
137
- .cmb_element .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
138
- .cmb_element .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
139
- .cmb_element .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
140
- .cmb_element .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
141
- .cmb_element .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
142
- .cmb_element .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
143
- .cmb_element .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
144
- .cmb_element .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
145
- .cmb_element .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
146
- .cmb_element .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
147
- .cmb_element .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
148
- .cmb_element .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
149
- .cmb_element .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
150
- .cmb_element .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
151
- .cmb_element .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
152
- .cmb_element .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
153
- .cmb_element .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
154
- .cmb_element .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
155
- .cmb_element .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
156
- .cmb_element .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
157
- .cmb_element .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
158
- .cmb_element .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
159
- .cmb_element .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
160
- .cmb_element .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
161
- .cmb_element .ui-icon-arrow-4 { background-position: 0 -80px; }
162
- .cmb_element .ui-icon-arrow-4-diag { background-position: -16px -80px; }
163
- .cmb_element .ui-icon-extlink { background-position: -32px -80px; }
164
- .cmb_element .ui-icon-newwin { background-position: -48px -80px; }
165
- .cmb_element .ui-icon-refresh { background-position: -64px -80px; }
166
- .cmb_element .ui-icon-shuffle { background-position: -80px -80px; }
167
- .cmb_element .ui-icon-transfer-e-w { background-position: -96px -80px; }
168
- .cmb_element .ui-icon-transferthick-e-w { background-position: -112px -80px; }
169
- .cmb_element .ui-icon-folder-collapsed { background-position: 0 -96px; }
170
- .cmb_element .ui-icon-folder-open { background-position: -16px -96px; }
171
- .cmb_element .ui-icon-document { background-position: -32px -96px; }
172
- .cmb_element .ui-icon-document-b { background-position: -48px -96px; }
173
- .cmb_element .ui-icon-note { background-position: -64px -96px; }
174
- .cmb_element .ui-icon-mail-closed { background-position: -80px -96px; }
175
- .cmb_element .ui-icon-mail-open { background-position: -96px -96px; }
176
- .cmb_element .ui-icon-suitcase { background-position: -112px -96px; }
177
- .cmb_element .ui-icon-comment { background-position: -128px -96px; }
178
- .cmb_element .ui-icon-person { background-position: -144px -96px; }
179
- .cmb_element .ui-icon-print { background-position: -160px -96px; }
180
- .cmb_element .ui-icon-trash { background-position: -176px -96px; }
181
- .cmb_element .ui-icon-locked { background-position: -192px -96px; }
182
- .cmb_element .ui-icon-unlocked { background-position: -208px -96px; }
183
- .cmb_element .ui-icon-bookmark { background-position: -224px -96px; }
184
- .cmb_element .ui-icon-tag { background-position: -240px -96px; }
185
- .cmb_element .ui-icon-home { background-position: 0 -112px; }
186
- .cmb_element .ui-icon-flag { background-position: -16px -112px; }
187
- .cmb_element .ui-icon-calendar { background-position: -32px -112px; }
188
- .cmb_element .ui-icon-cart { background-position: -48px -112px; }
189
- .cmb_element .ui-icon-pencil { background-position: -64px -112px; }
190
- .cmb_element .ui-icon-clock { background-position: -80px -112px; }
191
- .cmb_element .ui-icon-disk { background-position: -96px -112px; }
192
- .cmb_element .ui-icon-calculator { background-position: -112px -112px; }
193
- .cmb_element .ui-icon-zoomin { background-position: -128px -112px; }
194
- .cmb_element .ui-icon-zoomout { background-position: -144px -112px; }
195
- .cmb_element .ui-icon-search { background-position: -160px -112px; }
196
- .cmb_element .ui-icon-wrench { background-position: -176px -112px; }
197
- .cmb_element .ui-icon-gear { background-position: -192px -112px; }
198
- .cmb_element .ui-icon-heart { background-position: -208px -112px; }
199
- .cmb_element .ui-icon-star { background-position: -224px -112px; }
200
- .cmb_element .ui-icon-link { background-position: -240px -112px; }
201
- .cmb_element .ui-icon-cancel { background-position: 0 -128px; }
202
- .cmb_element .ui-icon-plus { background-position: -16px -128px; }
203
- .cmb_element .ui-icon-plusthick { background-position: -32px -128px; }
204
- .cmb_element .ui-icon-minus { background-position: -48px -128px; }
205
- .cmb_element .ui-icon-minusthick { background-position: -64px -128px; }
206
- .cmb_element .ui-icon-close { background-position: -80px -128px; }
207
- .cmb_element .ui-icon-closethick { background-position: -96px -128px; }
208
- .cmb_element .ui-icon-key { background-position: -112px -128px; }
209
- .cmb_element .ui-icon-lightbulb { background-position: -128px -128px; }
210
- .cmb_element .ui-icon-scissors { background-position: -144px -128px; }
211
- .cmb_element .ui-icon-clipboard { background-position: -160px -128px; }
212
- .cmb_element .ui-icon-copy { background-position: -176px -128px; }
213
- .cmb_element .ui-icon-contact { background-position: -192px -128px; }
214
- .cmb_element .ui-icon-image { background-position: -208px -128px; }
215
- .cmb_element .ui-icon-video { background-position: -224px -128px; }
216
- .cmb_element .ui-icon-script { background-position: -240px -128px; }
217
- .cmb_element .ui-icon-alert { background-position: 0 -144px; }
218
- .cmb_element .ui-icon-info { background-position: -16px -144px; }
219
- .cmb_element .ui-icon-notice { background-position: -32px -144px; }
220
- .cmb_element .ui-icon-help { background-position: -48px -144px; }
221
- .cmb_element .ui-icon-check { background-position: -64px -144px; }
222
- .cmb_element .ui-icon-bullet { background-position: -80px -144px; }
223
- .cmb_element .ui-icon-radio-off { background-position: -96px -144px; }
224
- .cmb_element .ui-icon-radio-on { background-position: -112px -144px; }
225
- .cmb_element .ui-icon-pin-w { background-position: -128px -144px; }
226
- .cmb_element .ui-icon-pin-s { background-position: -144px -144px; }
227
- .cmb_element .ui-icon-play { background-position: 0 -160px; }
228
- .cmb_element .ui-icon-pause { background-position: -16px -160px; }
229
- .cmb_element .ui-icon-seek-next { background-position: -32px -160px; }
230
- .cmb_element .ui-icon-seek-prev { background-position: -48px -160px; }
231
- .cmb_element .ui-icon-seek-end { background-position: -64px -160px; }
232
- .cmb_element .ui-icon-seek-start { background-position: -80px -160px; }
233
- .cmb_element .ui-icon-seek-first { background-position: -80px -160px; }
234
- .cmb_element .ui-icon-stop { background-position: -96px -160px; }
235
- .cmb_element .ui-icon-eject { background-position: -112px -160px; }
236
- .cmb_element .ui-icon-volume-off { background-position: -128px -160px; }
237
- .cmb_element .ui-icon-volume-on { background-position: -144px -160px; }
238
- .cmb_element .ui-icon-power { background-position: 0 -176px; }
239
- .cmb_element .ui-icon-signal-diag { background-position: -16px -176px; }
240
- .cmb_element .ui-icon-signal { background-position: -32px -176px; }
241
- .cmb_element .ui-icon-battery-0 { background-position: -48px -176px; }
242
- .cmb_element .ui-icon-battery-1 { background-position: -64px -176px; }
243
- .cmb_element .ui-icon-battery-2 { background-position: -80px -176px; }
244
- .cmb_element .ui-icon-battery-3 { background-position: -96px -176px; }
245
- .cmb_element .ui-icon-circle-plus { background-position: 0 -192px; }
246
- .cmb_element .ui-icon-circle-minus { background-position: -16px -192px; }
247
- .cmb_element .ui-icon-circle-close { background-position: -32px -192px; }
248
- .cmb_element .ui-icon-circle-triangle-e { background-position: -48px -192px; }
249
- .cmb_element .ui-icon-circle-triangle-s { background-position: -64px -192px; }
250
- .cmb_element .ui-icon-circle-triangle-w { background-position: -80px -192px; }
251
- .cmb_element .ui-icon-circle-triangle-n { background-position: -96px -192px; }
252
- .cmb_element .ui-icon-circle-arrow-e { background-position: -112px -192px; }
253
- .cmb_element .ui-icon-circle-arrow-s { background-position: -128px -192px; }
254
- .cmb_element .ui-icon-circle-arrow-w { background-position: -144px -192px; }
255
- .cmb_element .ui-icon-circle-arrow-n { background-position: -160px -192px; }
256
- .cmb_element .ui-icon-circle-zoomin { background-position: -176px -192px; }
257
- .cmb_element .ui-icon-circle-zoomout { background-position: -192px -192px; }
258
- .cmb_element .ui-icon-circle-check { background-position: -208px -192px; }
259
- .cmb_element .ui-icon-circlesmall-plus { background-position: 0 -208px; }
260
- .cmb_element .ui-icon-circlesmall-minus { background-position: -16px -208px; }
261
- .cmb_element .ui-icon-circlesmall-close { background-position: -32px -208px; }
262
- .cmb_element .ui-icon-squaresmall-plus { background-position: -48px -208px; }
263
- .cmb_element .ui-icon-squaresmall-minus { background-position: -64px -208px; }
264
- .cmb_element .ui-icon-squaresmall-close { background-position: -80px -208px; }
265
- .cmb_element .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
266
- .cmb_element .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
267
- .cmb_element .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
268
- .cmb_element .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
269
- .cmb_element .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
270
- .cmb_element .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
271
- .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; }
272
- .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; }
273
- .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; }
274
- .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; }
275
- .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); }
276
- .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; }
277
- .cmb_element .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
278
- .cmb_element .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
279
- .cmb_element .ui-datepicker .ui-datepicker-prev, .cmb_element .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
280
- .cmb_element .ui-datepicker .ui-datepicker-prev-hover, .cmb_element .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
281
- .cmb_element .ui-datepicker .ui-datepicker-prev { left:2px; }
282
- .cmb_element .ui-datepicker .ui-datepicker-next { right:2px; }
283
- .cmb_element .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
284
- .cmb_element .ui-datepicker .ui-datepicker-next-hover { right:1px; }
285
- .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; }
286
- .cmb_element .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
287
- .cmb_element .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
288
- .cmb_element .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
289
- .cmb_element .ui-datepicker select.ui-datepicker-month,
290
- .cmb_element .ui-datepicker select.ui-datepicker-year { width: 49%;}
291
- .cmb_element .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
292
- .cmb_element .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
293
- .cmb_element .ui-datepicker td { border: 0; padding: 1px; }
294
- .cmb_element .ui-datepicker td span, .cmb_element .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
295
- .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; }
296
- .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; }
297
- .cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
298
- .cmb_element .ui-datepicker.ui-datepicker-multi { width:auto; }
299
- .cmb_element .ui-datepicker-multi .ui-datepicker-group { float:left; }
300
- .cmb_element .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
301
- .cmb_element .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
302
- .cmb_element .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
303
- .cmb_element .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
304
- .cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
305
- .cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
306
- .cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
307
- .cmb_element .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
308
- .cmb_element .ui-datepicker-rtl { direction: rtl; }
309
- .cmb_element .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
310
- .cmb_element .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
311
- .cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
312
- .cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
313
- .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
314
- .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
315
- .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
316
- .cmb_element .ui-datepicker-rtl .ui-datepicker-group { float:right; }
317
- .cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
318
- .cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
319
- .cmb_element .ui-datepicker-cover {
320
- display: none; /*sorry for IE5*/
321
- display/**/: block; /*sorry for IE5*/
322
- position: absolute; /*must have*/
323
- z-index: -1; /*must have*/
324
- filter: mask(); /*must have*/
325
- top: -4px; /*must have*/
326
- left: -4px; /*must have*/
327
- width: 200px; /*must have*/
328
- height: 200px; /*must have*/
329
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,20 +1,42 @@
1
  === Scripts To Footer ===
2
  Contributors: joshuadnelson
3
- Tags: javascript, footer, speed, head, performance
4
  Donate link: http://jdn.im/donate
5
- Requires at least: 3.6
6
- Tested up to: 4.0
7
- Stable tag: 0.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- This small plugin moves scripts to the footer to help speed up page load times, while keeping stylesheets in the header.
12
 
13
  == Description ==
14
 
15
- This small plugin moves scripts to the footer to help speed up page load times, while keeping stylesheets in the header. Note that this only works if you have plugins and a theme that utilizes `wp_enqueue_scripts` correctly.
16
 
17
- Now includes an option to disable the plugin on a specific page or post.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  = Custom Post Type Support =
20
  If you're comfortable with code you can use the `scripts_to_footer_post_types` filter to change the post types this applies to (it only applies to pages and posts by default). For example, if you have a custom post type called "project" you could add support for this metabox via the post type filter like this:
@@ -28,9 +50,10 @@ function stf_add_cpt_support( $post_types ) {
28
  add_filter( 'scripts_to_footer_post_types', 'stf_add_cpt_support' );
29
  `
30
 
31
- = Excluding Pages/Posts Via Filter =
32
- As of version 0.5 you can either use the checkbox option to disable the plugin's action on a specific page/post, or you can utilize a filter. The filter also passes the post/page id, which might be useful for more advanced development. For example:
33
 
 
34
  `
35
  function stf_exclude_my_page( $exclude_page, $post_id ) {
36
  if( is_front_page() ) {
@@ -38,11 +61,17 @@ function stf_exclude_my_page( $exclude_page, $post_id ) {
38
  }
39
  return $exclude_page;
40
  }
41
- add_filter( 'scripts_to_footer_exclude_page', 'stf_exclude_my_page' );
42
  `
43
 
 
 
 
 
 
44
  = View on GitHub =
45
- [View this plugin on GitHub](https://github.com/joshuadavidnelson/scripts-to-footer)
 
46
 
47
  == Installation ==
48
 
@@ -57,9 +86,43 @@ e.g.
57
  == Screenshots ==
58
 
59
  1. The metabox that shows up on the Edit screen.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  == Changelog ==
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  = 0.5 =
64
  Reverted metabox version to previous - invalid error was sneaking through.
65
 
@@ -77,6 +140,9 @@ Initial release
77
 
78
  == Upgrade Notice ==
79
 
 
 
 
80
  = 0.5 =
81
  Please update to avoid an error on 0.4 version. If you're updating from version 0.3 or earlier, you'll get a new filter.
82
 
1
  === Scripts To Footer ===
2
  Contributors: joshuadnelson
3
+ Tags: javascript, footer, speed, head, performance, jquery, seo
4
  Donate link: http://jdn.im/donate
5
+ Requires at least: 3.1.0
6
+ Tested up to: 4.3.0
7
+ Stable tag: 0.6.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Move your scripts to the footer to help speed up perceived page load times and improve user experience.
12
 
13
  == Description ==
14
 
15
+ This small plugin moves scripts to the footer. Note that this only works if you have plugins and a theme that utilizes `wp_enqueue_scripts` correctly.
16
 
17
+ You can disable the plugin on specific pages and posts directly via the post/page edit screen metabox.
18
+
19
+ You can disable the plugin on specific archive pages (blog page, search page, post type and taxonomy archives) via the settings page.
20
+
21
+ **Everything Broken?** Try placing jQuery back into the header via Settings > Scripts to Footer, "Keep jQuery in the Header" checkbox. If that doesn't work, refer to the walkthrough below for using the `stf_exclude_scripts` filter for the script that is causing the issue.
22
+
23
+ Check out the [documentation](https://github.com/joshuadavidnelson/scripts-to-footer/wiki) on [GitHub](https://github.com/joshuadavidnelson/scripts-to-footer) or some quick walkthroughs below.
24
+
25
+ = Keeping specific Scripts in the Header =
26
+ As of version 0.6 you can now keep specific scripts in the header. Note: this will print any scripts they depend on as well (if you want to keep `jquery-effects-core` in the header, you'll also get `jQuery` in the header, so no need to add both).
27
+
28
+ Specifically for jQuery, see the settings page option, as it is a common request we've built it into the settings.
29
+
30
+ For any other scripts, use this filter:
31
+ `
32
+ add_filter( 'stf_exclude_scripts', 'jdn_header_scripts', 10, 1 );
33
+ function jdn_header_scripts( $scripts ) {
34
+ $scripts[] = 'backbone'; // Replace 'backbone' with the script slug
35
+ return $scripts;
36
+ }
37
+ `
38
+
39
+ You will need the correct script slug, which is used when the script is registered, and the script will only be printed into the header *if it's enqueued*. Check out the scripts that come registered [out-of-the-box with WordPress](http://codex.wordpress.org/Function_Reference/wp_enqueue_script#Default_Scripts_Included_and_Registered_by_WordPress).
40
 
41
  = Custom Post Type Support =
42
  If you're comfortable with code you can use the `scripts_to_footer_post_types` filter to change the post types this applies to (it only applies to pages and posts by default). For example, if you have a custom post type called "project" you could add support for this metabox via the post type filter like this:
50
  add_filter( 'scripts_to_footer_post_types', 'stf_add_cpt_support' );
51
  `
52
 
53
+ = Excluding Pages/Posts/Templates Via Filter =
54
+ As of version 0.5 you can either use the checkbox option to disable the plugin's action on a specific page/post, or you can utilize a filter (updated with version 0.6). The filter also passes the post/page id, if there is one (archive templates don't have ids!).
55
 
56
+ For example, for the "page" post type:
57
  `
58
  function stf_exclude_my_page( $exclude_page, $post_id ) {
59
  if( is_front_page() ) {
61
  }
62
  return $exclude_page;
63
  }
64
+ add_filter( 'stf_page', 'stf_exclude_my_page' );
65
  `
66
 
67
+ Replace `stf_page` with `stf_post` for posts, or the slug of your custom post type. For instance, a post type called "project" can be filtered with `stf_project`.
68
+
69
+ = More Documentation =
70
+ [View this plugin on GitHub](https://github.com/joshuadavidnelson/scripts-to-footer/wiki).
71
+
72
  = View on GitHub =
73
+ [View this plugin on GitHub](https://github.com/joshuadavidnelson/scripts-to-footer).
74
+
75
 
76
  == Installation ==
77
 
86
  == Screenshots ==
87
 
88
  1. The metabox that shows up on the Edit screen.
89
+ 2. The settings page.
90
+
91
+ == Frequently Asked Questions ==
92
+
93
+ 1. My scripts are not moving to the footer. This is likely due to one of three things:
94
+ - The theme you're using is not enqueuing scripts per [WordPress standards](https://codex.wordpress.org/Function_Reference/wp_enqueue_script#Using_a_Hook).
95
+ - You have a plugin that is not enqueing scripts [per standards](https://codex.wordpress.org/Function_Reference/wp_enqueue_script#Using_a_Hook).
96
+ - (Less common) There is a conflict with this plugin and another one. Deactivate all plugins and revert to a built-in theme (like TwentyTwelve or TwentyFifteen). Then activate Scripts-to-Footer. Check your HTML source to confirm it's working.
97
+ - If so, proceed to activate each of your other plugins one at a time, checking your HTML source each time to see if the scripts behavior changes. Eventually you'll find a conflict, if not with the plugins then activate your theme and check.
98
+
99
+ 2. Everything Breaks!!
100
+ - There are lots of scripts that require things like jQuery in the header. Try checking the "Keep jQuery in the header" option in Settings > Scripts to Footer or using the `stf_exclude_scripts` filter noted in the [documnetation](https://github.com/joshuadavidnelson/scripts-to-footer/wiki) (Note: only for version 0.6 and higher).
101
+
102
+ 3. My Slider stopped working.
103
+ - See number 2.
104
+
105
+ 4. My Page Speed hasn't improved (or it's worse)
106
+ - Actually, this plugin should not change your actual page speed - the same scripts are being loaded, that takes the same amount of time. However, by placing scripts in the footer you can change the _precieved_ load times, moving [render-blocking scripts](https://developers.google.com/speed/docs/insights/BlockingJS) below the fold, allowing your content to load first - instead of loading scripts and slowing the visual portions of your site. That's the whole point. Outside of that, this plugin is not intended to increase page load speed or minify scripts in anyway.
107
+
108
+ Please feel free to open a [Github Issue](https://github.com/joshuadavidnelson/scripts-to-footer/issues) to report conflicts or goto [the WP.org support forum](https://wordpress.org/support/plugin/scripts-to-footerphp). If there is something wrong with Scripts-to-Footer, we'll update it. However, if it's a another plugin or theme we can only contact the developer with the issue to attempt to resolve it.
109
 
110
  == Changelog ==
111
 
112
+ = 0.6.0 =
113
+ Large number of improvements:
114
+ - Add settings page with global disable options for home page, search pages, post type archives, taxonomy archives, and other archives.
115
+ - Update uninstall.php to remove things correctly.
116
+ - Add FAQ to readme.txt and readme.md.
117
+ - Add a changelog as a separate file.
118
+ - Change the custom post type filter. Refer to updated [FAQ](https://github.com/joshuadavidnelson/scripts-to-footer/#faq) and [documentation](https://github.com/joshuadavidnelson/scripts-to-footer/wiki).
119
+ - Add support for custom taxonomy archives.
120
+ - Change the exclude filter, to be more relevant to the new options. Older filter is depreciated, but still supported (for now).
121
+ - Update the post meta for disabling the plugin on specific posts/pages.
122
+ - Add Github Updater support.
123
+ - Removed CMB and built metaboxes the old fashion way.
124
+ - Added debug logging to better track any potential errors moving forward.
125
+
126
  = 0.5 =
127
  Reverted metabox version to previous - invalid error was sneaking through.
128
 
140
 
141
  == Upgrade Notice ==
142
 
143
+ = 0.6 =
144
+ Large improvements, including: a settings page to resolve issues on archives and blog roll pages, setting to keep jQuery in the header, and updated filters. Refer to the documentation if you are using a filter currently, as they have changed, prior to updating.
145
+
146
  = 0.5 =
147
  Please update to avoid an error on 0.4 version. If you're updating from version 0.3 or earlier, you'll get a new filter.
148
 
scripts-to-footer.php CHANGED
@@ -3,7 +3,6 @@
3
  * Main Plugin File
4
  *
5
  * @package Scripts_To_Footer
6
- * @subpackage Admin
7
  * @author Joshua David Nelson <josh@joshuadnelson.com>
8
  * @copyright Copyright (c) 2014, Joshua David Nelson
9
  * @license http://www.opensource.org/licenses/gpl-license.php GPL-2.0+
@@ -12,10 +11,12 @@
12
  * Plugin Name: Scripts-To-Footer
13
  * Plugin URI: http://wordpress.org/plugins/scripts-to-footerphp/
14
  * Description: Moves scripts to the footer to decrease page load times, while keeping stylesheets in the header. Requires that plugins and theme correctly utilizes wp_enqueue_scripts hook. Can be disabled via a checkbox on specific pages and posts.
15
- * Version: 0.5
16
  * Author: Joshua David Nelson
17
  * Author URI: http://joshuadnelson.com
18
  * License: GPL2
 
 
19
  *
20
  **/
21
 
@@ -43,7 +44,19 @@ if( !defined( 'STF_DOMAIN' ) )
43
 
44
  // Plugin Verison
45
  if( !defined( 'STF_VERSION' ) )
46
- define( 'STF_VERSION', '0.5' );
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  /**
49
  * Scripts to Footer Class.
@@ -52,8 +65,19 @@ if( !defined( 'STF_VERSION' ) )
52
  *
53
  * @since 0.2
54
  */
 
 
55
 
56
- class JDN_Scripts_To_Footer {
 
 
 
 
 
 
 
 
 
57
 
58
  /**
59
  * Construct.
@@ -61,11 +85,98 @@ class JDN_Scripts_To_Footer {
61
  * Registers our activation hook and init hook.
62
  *
63
  * @since 0.2
64
- * @author Joshua David Nelson
65
  */
66
  function __construct() {
 
 
 
 
 
 
 
 
 
 
 
67
  add_action( 'init', array( $this, 'init' ) );
68
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  /**
71
  * Plugin Init.
@@ -74,91 +185,326 @@ class JDN_Scripts_To_Footer {
74
  * and plugin links.
75
  *
76
  * @since 0.2
77
- * @author Joshua David Nelson
78
  */
79
  function init() {
 
80
  // Run the plugin
81
  add_action( 'wp_enqueue_scripts', array( $this, 'clean_head' ) );
 
 
 
 
82
 
83
- // Metabox on Edit screen, for Page Override
84
- add_filter( 'cmb_meta_boxes', array( $this, 'create_metaboxes' ) );
85
- add_action( 'init', array( $this, 'initialize_cmb_meta_boxes' ), 50 );
86
 
87
  // Add Links to Plugin Bar
88
  if( function_exists( 'stf_plugin_links' ) )
89
  add_filter( 'plugin_row_meta', 'stf_plugin_links', 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  }
91
 
92
  /**
93
  * Remove scripts from header, forces them to the footer.
94
  *
95
- * First checks to see if the current post type is excluded via the custom meta box, if so then it doesn't run.
 
96
  *
97
  * @since 0.1
98
  **/
99
  function clean_head() {
100
- if( get_queried_object_id() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  $queried_object_id = get_queried_object_id();
102
- $exclude_page = get_post_meta( $queried_object_id, 'stf_exclude', true );
103
- $exclude_page = apply_filters( 'scripts_to_footer_exclude_page', $exclude_page, $queried_object_id );
104
 
105
- if( 'on' !== $exclude_page && !is_admin() ) {
106
- remove_action( 'wp_head', 'wp_print_scripts' );
107
- remove_action( 'wp_head', 'wp_print_head_scripts', 9 );
108
- remove_action( 'wp_head', 'wp_enqueue_scripts', 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
  }
112
 
113
  /**
114
- * Create Page-Specific Metaboxes.
115
- * @link http://www.billerickson.net/wordpress-metaboxes/
116
  *
117
- * @param array $meta_boxes, current metaboxes
118
- * @return array $meta_boxes, current + new metaboxes
119
  *
120
- * @since 0.2
121
  */
122
- function create_metaboxes( $meta_boxes ) {
123
  $post_types = apply_filters( 'scripts_to_footer_post_types', array( 'page', 'post' ) );
124
- if( !empty( $post_types ) ) {
125
- $meta_boxes[] = array(
126
- 'id' => 'scripts-to-footer',
127
- 'title' => __( 'Scripts to Footer Plugin Settings', STF_DOMAIN ),
128
- 'pages' => $post_types,
129
- 'context' => 'normal',
130
- 'priority' => 'high',
131
- 'show_names' => true,
132
- 'fields' => array(
133
- array(
134
- 'name' => __( 'Disable Plugin', STF_DOMAIN ),
135
- 'desc' => __( 'By default, the scripts to footer plugin is set to run. This checkbox disables the plugin on this page', STF_DOMAIN ),
136
- 'id' => 'stf_exclude',
137
- 'type' => 'checkbox'
138
- )
139
- )
140
- );
141
- }
142
-
143
- return $meta_boxes;
144
- }
145
-
146
- /**
147
- * Initializing Custom Metaboxes
148
- *
149
- * @author Bill Erickson, billerickson.net
150
- * @since 0.2
151
- **/
152
- function initialize_cmb_meta_boxes() {
153
- $post_types = apply_filters( 'scripts_to_footer_post_types', array( 'page', 'post' ) );
154
- if( !class_exists( 'cmb_Meta_Box' ) && !empty( $post_types ) ) {
155
- require_once( dirname( __FILE__) . '/lib/metabox/init.php' );
156
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
158
-
159
  }
160
- global $stf_scripts_to_footer;
161
- $stf_scripts_to_footer = new JDN_Scripts_To_Footer();
162
 
163
  /**
164
  * Add various links to plugin page
@@ -184,6 +530,8 @@ if( !function_exists( 'stf_plugin_links' ) ) {
184
 
185
  if( $file == $this_plugin ) {
186
  $links[] = '<a href="http://wordpress.org/support/plugin/scripts-to-footerphp" title="' . __( 'Support', STF_DOMAIN ) . '">' . __( 'Support', STF_DOMAIN ) . '</a>';
 
 
187
 
188
  $links[] = '<a href="http://jdn.im/donate" title="' . __( 'Donate', STF_DOMAIN ) . '">' . __( 'Donate', STF_DOMAIN ) . '</a>';
189
  }
@@ -191,3 +539,19 @@ if( !function_exists( 'stf_plugin_links' ) ) {
191
  return $links;
192
  }
193
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  * Main Plugin File
4
  *
5
  * @package Scripts_To_Footer
 
6
  * @author Joshua David Nelson <josh@joshuadnelson.com>
7
  * @copyright Copyright (c) 2014, Joshua David Nelson
8
  * @license http://www.opensource.org/licenses/gpl-license.php GPL-2.0+
11
  * Plugin Name: Scripts-To-Footer
12
  * Plugin URI: http://wordpress.org/plugins/scripts-to-footerphp/
13
  * Description: Moves scripts to the footer to decrease page load times, while keeping stylesheets in the header. Requires that plugins and theme correctly utilizes wp_enqueue_scripts hook. Can be disabled via a checkbox on specific pages and posts.
14
+ * Version: 0.6
15
  * Author: Joshua David Nelson
16
  * Author URI: http://joshuadnelson.com
17
  * License: GPL2
18
+ * GitHub Plugin URI: https://github.com/joshuadavidnelson/scripts-to-footer
19
+ * GitHub Branch: master
20
  *
21
  **/
22
 
44
 
45
  // Plugin Verison
46
  if( !defined( 'STF_VERSION' ) )
47
+ define( 'STF_VERSION', '0.6' );
48
+
49
+ // Plugin name
50
+ if( !defined( 'STF_NAME' ) )
51
+ define( 'STF_NAME', trim( dirname( plugin_basename( __FILE__ ) ), '/' ) );
52
+
53
+ // Plugin Directory
54
+ if( !defined( 'STF_DIR' ) )
55
+ define( 'STF_DIR', WP_PLUGIN_DIR . '/' . STF_NAME );
56
+
57
+ // Plugin URL
58
+ if( !defined( 'STF_URL' ) )
59
+ define( 'STF_URL', WP_PLUGIN_URL . '/' . STF_NAME );
60
 
61
  /**
62
  * Scripts to Footer Class.
65
  *
66
  * @since 0.2
67
  */
68
+ global $stf_scripts_to_footer;
69
+ $stf_scripts_to_footer = new Scripts_To_Footer();
70
 
71
+ class Scripts_To_Footer {
72
+
73
+ /**
74
+ * An array of script slugs that should remain in the header.
75
+ *
76
+ * @since 0.6
77
+ *
78
+ * @var array
79
+ */
80
+ protected $header_scripts;
81
 
82
  /**
83
  * Construct.
85
  * Registers our activation hook and init hook.
86
  *
87
  * @since 0.2
 
88
  */
89
  function __construct() {
90
+ add_action( 'admin_init', array( $this, 'check_version' ) );
91
+
92
+ // Don't run anything else in the plugin, if we're on an incompatible
93
+ if ( ! self::compatible_version() ) {
94
+ return;
95
+ }
96
+
97
+ // Admin settings
98
+ include_once( STF_DIR . '/admin/admin-settings.php' );
99
+
100
+ // Make it so
101
  add_action( 'init', array( $this, 'init' ) );
102
  }
103
+
104
+ /**
105
+ * Activation hook.
106
+ *
107
+ * The primary sanity check, automatically disable the plugin on activation
108
+ * if it doesn't meet minimum requirements. If it does, then it does some version
109
+ * checks and updates the site version option.
110
+ *
111
+ * @since 0.6
112
+ */
113
+ static function activation_check() {
114
+ if ( ! self::compatible_version() ) {
115
+ deactivate_plugins( plugin_basename( __FILE__ ) );
116
+ wp_die( __( 'Scripts-to-Footer requires WordPress 3.1.0 or higher', 'stf' ) );
117
+ } else {
118
+ // Save the previous version we're upgrading from
119
+ $current_version = get_option( 'stf_version', false );
120
+ if ( $current_version )
121
+ update_option( 'stf_previous_version', $current_version );
122
+
123
+ // See if it's a previous version, which may not have set the version option
124
+ if ( false === $current_version || $current_version != STF_VERSION ) {
125
+ // do things on update
126
+ }
127
+
128
+ // Save current version
129
+ update_option( 'stf_version', STF_VERSION );
130
+ }
131
+ }
132
+
133
+ /**
134
+ * The backup sanity check.
135
+ *
136
+ * This is just in case the plugin is activated in a weird way,
137
+ * or the versions change after activation.
138
+ *
139
+ * @since 0.6
140
+ */
141
+ function check_version() {
142
+ if ( ! self::compatible_version() ) {
143
+ if ( is_plugin_active( plugin_basename( __FILE__ ) ) ) {
144
+ deactivate_plugins( plugin_basename( __FILE__ ) );
145
+ add_action( 'admin_notices', array( $this, 'disabled_notice' ) );
146
+ if ( isset( $_GET['activate'] ) ) {
147
+ unset( $_GET['activate'] );
148
+ }
149
+ }
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Display notice on deactivation.
155
+ *
156
+ * @since 0.6
157
+ *
158
+ * @return void
159
+ */
160
+ function disabled_notice() {
161
+ echo '<strong>' . esc_html__( 'Scripts-to-Footer requires WordPress 3.1.0 or higher.', STF_DOMAIN ) . '</strong>';
162
+ }
163
+
164
+ /**
165
+ * Check everything is compatible.
166
+ *
167
+ * @since 0.6
168
+ *
169
+ * @return boolean
170
+ */
171
+ static function compatible_version() {
172
+ if ( version_compare( $GLOBALS['wp_version'], '3.1.0', '<' ) ) {
173
+ return false;
174
+ }
175
+
176
+ // Add sanity checks for other version requirements here
177
+
178
+ return true;
179
+ }
180
 
181
  /**
182
  * Plugin Init.
185
  * and plugin links.
186
  *
187
  * @since 0.2
 
188
  */
189
  function init() {
190
+
191
  // Run the plugin
192
  add_action( 'wp_enqueue_scripts', array( $this, 'clean_head' ) );
193
+ add_filter( 'stf_include', array( $this, 'stf_includes' ) );
194
+
195
+ // Set the header scripts to be forced into the header
196
+ $this->set_header_scripts();
197
 
198
+ // Add select scripts into the header
199
+ add_action( 'wp_head', array( $this, 'print_head_scripts' ) );
 
200
 
201
  // Add Links to Plugin Bar
202
  if( function_exists( 'stf_plugin_links' ) )
203
  add_filter( 'plugin_row_meta', 'stf_plugin_links', 10, 2 );
204
+
205
+ // Add setting link to plugin bar
206
+ if( function_exists( 'stf_plugin_settings_link' ) ) {
207
+ $plugin = plugin_basename(__FILE__);
208
+ add_filter( "plugin_action_links_$plugin", 'stf_plugin_settings_link' );
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Set the scripts to be printed in the header, based on options and filter.
214
+ *
215
+ * @since 0.6
216
+ */
217
+ public function set_header_scripts() {
218
+ if( $exclude = stf_get_option( 'stf_jquery_header', false ) ) {
219
+ $head_scripts = array( 'jquery' );
220
+ } else {
221
+ $head_scripts = array();
222
+ }
223
+
224
+ $this->header_scripts = apply_filters( 'stf_exclude_scripts', $head_scripts );
225
+ }
226
+
227
+ /**
228
+ * The holy grail: print select scripts in the header!
229
+ *
230
+ * @since 0.6
231
+ *
232
+ * @return void
233
+ */
234
+ function print_head_scripts() {
235
+ if( !isset( $this->header_scripts ) || empty( $this->header_scripts ) || !is_array( $this->header_scripts ) )
236
+ return;
237
+
238
+ // The main filter, true inacts the plugin, false does not (excludes the page)
239
+ $include = $this->is_included();
240
+ if( $this->is_included() ) {
241
+ foreach( $this->header_scripts as $script ) {
242
+ if( !is_string( $script ) )
243
+ continue;
244
+
245
+ // If the script is enqueued for the page, print it
246
+ if( wp_script_is( $script ) )
247
+ wp_print_scripts( $script );
248
+ }
249
+ }
250
  }
251
 
252
  /**
253
  * Remove scripts from header, forces them to the footer.
254
  *
255
+ * Checks the singular post/page first, then other common pages
256
+ * and compares against any global settings and filters.
257
  *
258
  * @since 0.1
259
  **/
260
  function clean_head() {
261
+
262
+ // Bail if we're in the admin area
263
+ if( is_admin() )
264
+ return;
265
+
266
+ // The main filter, true inacts the plugin, false does not (excludes the page)
267
+ $include = $this->is_included();
268
+
269
+ // If this isn't set, then we're missing something
270
+ if( !isset( $include ) ) {
271
+ $this->log_me( 'Something went wrong with the $include variable' );
272
+ return;
273
+ }
274
+
275
+ // Either it's turned off site wide and included for this post/page, or turned on site wide and not excluded for this post/page - also not admin
276
+ if( true === $include ) {
277
+ remove_action( 'wp_head', 'wp_print_scripts' );
278
+ remove_action( 'wp_head', 'wp_print_head_scripts', 9 );
279
+ remove_action( 'wp_head', 'wp_enqueue_scripts', 1 );
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Determing if the current page is included, via a filter.
285
+ *
286
+ * @since 0.6
287
+ *
288
+ * @return boolean Default is true.
289
+ */
290
+ public function is_included() {
291
+ $include = apply_filters( 'stf_include', true );
292
+
293
+ if( true === $include ) {
294
+ return true;
295
+ } elseif( false === $include ) {
296
+ return false;
297
+ } else {
298
+ $this->log_me( 'Non-boolean value in the stf_include filter' );
299
+ return true;
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Runs the various template checks and returns true/false.
305
+ *
306
+ * @since 0.6
307
+ *
308
+ * @return boolean
309
+ */
310
+ function stf_includes() {
311
+ // Collect the information
312
+ if( is_singular() || is_page() ) {
313
+ // Make sure we can grab the page/post id
314
  $queried_object_id = get_queried_object_id();
 
 
315
 
316
+ // verify we got a good result
317
+ if( absint( $queried_object_id ) && ( $post_type = get_post_type( $queried_object_id ) ) ) {
318
+ // See if post type is supported, if not bail
319
+ if( false === $this->post_type_supported( $post_type ) )
320
+ return false;
321
+
322
+ // Get the exclude post meta value
323
+ $exclude_page = get_post_meta( $queried_object_id, 'stf_exclude', true );
324
+
325
+ // Support for older versions that use 'on' as well as newer versions with boolean
326
+ if( 'on' === $exclude_page || true == $exclude_page )
327
+ return false;
328
+
329
+ // Older override check, depreciated
330
+ $excluded_override = apply_filters( 'scripts_to_footer_exclude_page', null, $queried_object_id );
331
+ if( 'on' == $excluded_override || true == $excluded_override ) {
332
+ $this->log_me( 'The scripts_to_footer_exclude_page is depreciated, please use stf_{$post_type} returning false to exclude');
333
+ return false;
334
+ }
335
+
336
+ // Allow override
337
+ return apply_filters( "stf_{$post_type}", true, $queried_object_id );
338
+
339
+ } else {
340
+ $this->log_me( 'Unable to get a correct object id from get_queried_object_id or unable to get post type' );
341
+ return false;
342
+ }
343
+
344
+ // Home (blog) page
345
+ } elseif( is_home() ) {
346
+ // Grab global setting
347
+ $type = 'home';
348
+
349
+ // Search Result Page
350
+ } elseif( is_search() ) {
351
+ $type = 'search';
352
+
353
+ // Author Archive
354
+ } elseif( is_author() ) {
355
+ $type = 'author_archive';
356
+
357
+ // Category Archive
358
+ } elseif( is_category() ) {
359
+
360
+ if( $this->tax_supported( 'category' ) ) {
361
+ $type = "category_archive";
362
+ } else {
363
+ $this->log_me( 'Error in category check' );
364
+ return false;
365
+ }
366
+
367
+ // Tag Archive
368
+ } elseif( is_tag() ) {
369
+
370
+ if( $this->tax_supported( 'post_tag' ) ) {
371
+ $type = "post_tag_archive";
372
+ } elseif( false === $tax ) {
373
+ $this->log_me( 'Error in tag check' );
374
+ return false;
375
+ }
376
+
377
+ // Taxonomy Archive
378
+ } elseif( is_tax() ) {
379
+
380
+ $tax = get_taxonomy();
381
+ if( isset( $tax->name ) && $this->tax_supported( $tax->name ) ) {
382
+ $type = "{$tax->name}_archive";
383
+ } elseif( false === $tax ) {
384
+ $this->log_me( 'Error in taxonomy check' );
385
+ return false;
386
+ }
387
+
388
+ // Post Type Archive
389
+ } elseif( is_post_type_archive() ) {
390
+
391
+ $post_type = get_post_type();
392
+ if( $this->post_type_supported( $post_type ) ) {
393
+ $type = "{$post_type}_archive";
394
+ } elseif( false === $post_type ) {
395
+ $this->log_me( 'Error in post type check check' );
396
+ return false;
397
  }
398
+
399
+ // Generic archives (date, author, etc)
400
+ } elseif( is_archive() ) {
401
+ $type = 'archive';
402
+
403
+ // if all else fails return false
404
+ } else {
405
+ return false;
406
+ }
407
+
408
+ // Get the option and return the result with a filter to override
409
+ if( isset( $type ) && is_string( $type ) ) {
410
+ // Filter to *exclude* a type of page, return the opposite
411
+ $exclude = stf_get_option( "stf_exclude_{$type}", false );
412
+ if( $exclude ) {
413
+ $include = false;
414
+ } else {
415
+ $include = true;
416
+ }
417
+ return apply_filters( "stf_{$type}", $include );
418
+
419
+ } else {
420
+ $this->log_me( 'invalid $type element' );
421
+ return false;
422
  }
423
  }
424
 
425
  /**
426
+ * Check for post type support, via the filter. Default support for page and post.
 
427
  *
428
+ * @since 0.6
 
429
  *
430
+ * @return array Supported posts
431
  */
432
+ public function post_types_supported() {
433
  $post_types = apply_filters( 'scripts_to_footer_post_types', array( 'page', 'post' ) );
434
+ if( is_array( $post_types ) ) {
435
+ return $post_types;
436
+ } else {
437
+ $this->log_me( 'Invalid post types returned in scripts_to_footer_post_types filter' );
438
+ return false;
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Check if a post type is supported.
444
+ *
445
+ * @since 0.6
446
+ *
447
+ * @return array Supported posts
448
+ */
449
+ public function post_type_supported( $post_type ) {
450
+ $post_types = $this->post_types_supported();
451
+ if( is_array( $post_types ) && is_string( $post_type ) && in_array( $post_type, $post_types ) ) {
452
+ return true;
453
+ } else {
454
+ return false;
455
+ }
456
+ }
457
+
458
+ /**
459
+ * Check for custom taxonomy support, via the filter.
460
+ *
461
+ * @since 0.6
462
+ *
463
+ * @return array Supported posts
464
+ */
465
+ public function taxonomies_supported() {
466
+ $taxes = apply_filters( 'scripts_to_footer_taxonomies', array( 'category', 'post_tag' ) );
467
+ if( is_array( $taxes ) ) {
468
+ return $taxes;
469
+ } else {
470
+ $this->log_me( 'Invalid taxonomies returned in scripts_to_footer_taxonomies filter' );
471
+ return false;
472
+ }
473
+ }
474
+
475
+ /**
476
+ * Check if a post type is supported.
477
+ *
478
+ * @since 0.6
479
+ *
480
+ * @return array Supported posts
481
+ */
482
+ public function tax_supported( $taxonomy ) {
483
+ $taxes = $this->taxonomies_supported();
484
+ if( is_array( $taxes ) && is_string( $taxonomy ) && in_array( $taxonomy, $taxes ) ) {
485
+ return true;
486
+ } else {
487
+ return false;
488
+ }
489
+ }
490
+
491
+ /**
492
+ * Log any errors, if debug mode is on.
493
+ *
494
+ * @since 0.6
495
+ *
496
+ * @param string $message
497
+ */
498
+ public function log_me( $message ) {
499
+ if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
500
+ if ( is_array( $message ) || is_object( $message ) ) {
501
+ error_log( 'Scripts-to-Footer Plugin Error: ' . print_r( $message, true ) );
502
+ } else {
503
+ error_log( 'Scripts-to-Footer Plugin Error: ' . $message );
504
+ }
505
+ }
506
  }
 
507
  }
 
 
508
 
509
  /**
510
  * Add various links to plugin page
530
 
531
  if( $file == $this_plugin ) {
532
  $links[] = '<a href="http://wordpress.org/support/plugin/scripts-to-footerphp" title="' . __( 'Support', STF_DOMAIN ) . '">' . __( 'Support', STF_DOMAIN ) . '</a>';
533
+
534
+ $links[] = '<a href="https://github.com/joshuadavidnelson/scripts-to-footer/wiki" title="' . __( 'Documentation', STF_DOMAIN ) . '" target="_blank">' . __( 'Documentation', STF_DOMAIN ) . '</a>';
535
 
536
  $links[] = '<a href="http://jdn.im/donate" title="' . __( 'Donate', STF_DOMAIN ) . '">' . __( 'Donate', STF_DOMAIN ) . '</a>';
537
  }
539
  return $links;
540
  }
541
  }
542
+
543
+ /**
544
+ * Add link to options page in plguin screen.
545
+ *
546
+ * @since 0.6
547
+ *
548
+ * @param string $links Links.
549
+ * @return $links Amended links.
550
+ */
551
+ if( !function_exists( 'stf_plugin_settings_link' ) ) {
552
+ function stf_plugin_settings_link( $links ) {
553
+ $settings_link = '<a href="options-general.php?page=' . STF_SETTINGS_FIELD . '">Settings</a>';
554
+ array_unshift( $links, $settings_link );
555
+ return $links;
556
+ }
557
+ }
uninstall.php CHANGED
@@ -81,20 +81,24 @@ if ( is_multisite() ) {
81
  $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs}", ARRAY_A );
82
 
83
  if ( $blogs ) {
84
-
85
  foreach ( $blogs as $blog ) {
86
-
87
  // Repeat for every Site ID
88
  switch_to_blog( $blog[ 'blog_id' ] );
 
89
  delete_option( STF_SETTINGS_FIELD );
 
 
 
 
90
  }
91
-
92
  restore_current_blog();
93
-
94
  }
95
 
96
  } else { // Otherwise, delete options from main options table
97
-
98
  delete_option( STF_SETTINGS_FIELD );
99
-
 
 
 
100
  }
81
  $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs}", ARRAY_A );
82
 
83
  if ( $blogs ) {
 
84
  foreach ( $blogs as $blog ) {
 
85
  // Repeat for every Site ID
86
  switch_to_blog( $blog[ 'blog_id' ] );
87
+ // Delete plugin options
88
  delete_option( STF_SETTINGS_FIELD );
89
+ delete_option( 'stf_version' );
90
+
91
+ // Delete all post meta
92
+ delete_post_meta_by_key( 'stf_exclude' );
93
  }
 
94
  restore_current_blog();
 
95
  }
96
 
97
  } else { // Otherwise, delete options from main options table
98
+ // Delete plugin options
99
  delete_option( STF_SETTINGS_FIELD );
100
+ delete_option( 'stf_version' );
101
+
102
+ // Delete all post meta
103
+ delete_post_meta_by_key( 'stf_exclude' );
104
  }