Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Case:

I got a set of classes that build form fields based on data from an input array. The class can build the following types of form fields:

  • input (basic, hidden, password)
  • textarea
  • radio
  • checkbox
  • select
  • colorpicker
  • datepicker
  • file upload

EDIT: The class uses wp_register_script/_style & wp_enqueue_script/_style to load the scripts & styles. The functions containing the actions are hooked inside the class like this: add_action( 'admin_enqueue_scripts', array( &$this, 'enqueue' ) );.

Example:

(Inside functions.php)

// meta box callback function
function test_meta_box_cb()
{   
    $input_args = array(
         'type'         => 'color'
        ,'id'           => 'color-id'
        ,'label'        => 'Input Colorpicker Label'
        ,'opt_name'     => 'abc_xyz'
        ,'value'        => '009ee0'
     );
    new FormClass( $input_args, true );
}
// add the meta box
function add_test_meta_box()
{
    add_meta_box( 'test_box', __('TestBox'), 'test_meta_box_cb', 'post', 'advanced', 'high' );
}
add_action( 'add_meta_boxes', 'add_test_meta_box' );

Problem:

This way, my call for wp_enqueue_script & wp_enqueue_style doesn't work. I get the form fields rendered, but no scripts or styles.

Situation & Backtracing of the problem:

So far I could track down the problem to the wordpress core architecture:

  • WP doesn't question what happens inside the callback function until do_action('add_meta_boxes', $post_type, $post) get's called (inside edit-form-advanced.php).
  • That call happens long after admin-header.php was called (which contains do_action('admin_enqueue_scripts', $hook_suffix);).
  • Therefore the script & style can't get loaded (if I'm not wrong).

Question:

  1. How could i load styles before the meta box form fields get called?
  2. How could i avoid repeating the same stylesheet over and over again - i want to use wp_enqueue_style & wp_register_style?

I'm open to any answers including those who force me to rewrite my class architecture.

Note: I need to use this class in a lot of different szenarios, so bundling it to close together with the add_meta_box function is not good. I'm close to making an abstraction layer that divides the call for the meta box and the style/script part, but why would I want to add another layer above a core function?

share|improve this question

3 Answers 3

up vote 2 down vote accepted

Your problem is adding the scripts, styles inside the class, and because the class instance is created when the hook add_meta_box is fired, at that time the wp_enqueue_script/style are already finished.

A solution for you is adding the scripts, styles outside the function and the class. And because meta boxes are used only at editing pages, you can do as the following:

// the editing pages are actually post.php and post-new.php
add_action('admin_print_styles-post.php', 'custom_js_css');
add_action('admin_print_styles-post-new.php', 'custom_js_css');

function custom_js_css() {
    wp_enqueue_style('your-meta-box', $base_url . '/meta-box.css');
    wp_enqueue_script('your-meta-box', $base_url . '/meta-box.js', array('jquery'), null, true);
}

Actually, I wrote a meta box class for WP, that uses another approach. Instead of writing form class for form fields like you did, my class is a wrapper for meta boxes. If you interested in, it's worth to take a look.

share|improve this answer
    
@Rilwis Glad you dropped by. I know your class (and it's great), but have been completely forgotten to take a look for "inspiration". Needless to say that your article/tutorial/manual is amazing. :) –  kaiser Jun 10 '11 at 14:28
    
@kaiser: Thanks. I hope to listen your opinion about the code, though. Btw, can you share your form class? Does it look similar to scribu's framework? scribu's framework is good, but it lacks documentation and seems a bit complicated. –  Rilwis Jun 10 '11 at 15:36
    
@rilwis Sorry to say, but currently I'm not sharing for an easy reason: I'm writing it for our company and sharing code for fields that interfer with the database are a possible security hole (so I'm simply not allowed). Furthermore it takes it data from xml files, so it won't be of much use for most of the people. But i share other stuff on my github page (check my profile). You can find breadcrumb classes, pagination (currently the old version) and other stuff. Just make shure you check the gists too. –  kaiser Jun 10 '11 at 16:05
1  
@kaiser Thank you very much :) –  Rilwis Jun 17 '11 at 1:15
1  
@knutole just fixed the link –  Rilwis Feb 5 at 3:02

You should really hook you scripts to the wp_enqueue_scripts action and your styles to the wp_print_styles action. Inside your functions, do a check to make sure you're on the page using your meta boxes before actually using wp_enqueue_script() or wp_enqueue_style().

For example, in one of my plugins I have:

public static function enqueue_scripts_and_styles() {
    if( is_admin() ) {
        wp_enqueue_script( 'media-upload' );
        wp_enqueue_script( 'thickbox' );
        wp_enqueue_style( 'thickbox' );
    } else {
        wp_enqueue_style( 'wp-publication-archive-frontend', WP_PUB_ARCH_INC_URL . '/front-end.css', '', '2.0', 'all' );
    }
}

And I hook that to init (which fires just before all the other scripts and styles are enqueued).

share|improve this answer
    
@EAMann Point is that I'm doing exactly the same inside my class. Point also is that these won't get fired and added to the appropriate hooks until the meta box get's printed - which is much too late (right in the middle of the admin screen). See Edit under Case. –  kaiser Jun 9 '11 at 18:04
    
My argument was to not use the meta box callback for this. Hook things up separately, then add some logic inside your filter to make sure the page will be using your meta boxes. –  EAMann Jun 9 '11 at 18:48
    
@EAMann In this case i missunderstood you. The problem still is that I don't want to separate the calls, so I'm searching for a solution that works with add_meta_box as well. The class is extremly generic and I don't want to add a layer above add_meta_box just to make it work. –  kaiser Jun 9 '11 at 19:19
    
The problem you're going to run into is that there isn't a solution that works with add_meta_box directly. You either have to add a layer on top of it, or queue up your scripts and styles separately. –  EAMann Jun 9 '11 at 19:54
    
Well, there's no way to do it with hooks ... you could just output the scripts and styles directly within your markup. But that's a bad idea for a whole slew of other reasons. Just remember, the add_meta_boxes action is fired to directly add markup to the page, not to queue up additional code for the <head>. –  EAMann Jun 9 '11 at 19:56

In current form your code dumbs down object to kind of function call (get created, do something, die). Such usage won't do if you want object to do something long before that object is created and destroyed.

Instead of creating object inside of metabox content I'd do following:

  1. Create object some time early.
  2. Use object's method to deal with scripts.
  3. Use another object's method as meta box callback.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.