Multiple Custom_Background, is it possible?

Is it possible to create multiple “custom background” administration pages? A site I’m doing now needs 2 different background in 2 different areas, I would really love giving my client the same experience for both backgrounds in terms of colour/image/select-repeat etc.
Any Ideas?

Related posts

Leave a Reply

2 comments

  1. Hi @Amit:

    The answer is “Yes, it is possible.” The follow up question is “Do you really want to?”

    I thought it would be fun to see if I could build a plugin to do what you are asking for so I decided to see if it was possible. Of course I was able to make it work but I fear that the plugin code I wrote needs to be so tightly coupled with the existing code in WordPress that it might easily break on a core update.

    This code handles all the admin console side of things by creating a new menu item in the Appearance section called “Special Background.” What it does not do is provide any way to actually use the background; that’s phase two of the plugin and will require hooking many of the functions in /wp-includes/themes.php and frankly I don’t know if I’ll get a chance to write that code.

    The reason I stopped without doing it is I didn’t know the requirements for where the special background should show and where the regular one would show. I assume maybe for selected pages and/or URL paths?

    Nonetheless, here if the code for the plugin (which you can also download from gist):

    <?php
    /*
    Plugin Name: Special Background
    Plugin URI: http://wordpress.stackexchange.com/questions/972/
    Description: Example to show how to add a special background using exiting background admin page in core.
    Version: 0.1
    Author: Mike Schinkel
    Author URI: http://mikeschinkel.com/custom-wordpress-plugins/
    */
    add_filter('admin_menu','add_special_background_menu_item');
    function add_special_background_menu_item() {
        add_theme_page(__('Special Background'), __('Special Background'),'edit_theme_options','special-background','special_background_admin_page');
    }
    add_filter('admin_init','add_js_for_special_background');
    function add_js_for_special_background() {
        global $custom_background;
        if (is_special_background_page()) {
            wp_enqueue_script('custom-background');
            wp_enqueue_style('farbtastic');
        }
        $hook = 'load-appearance_page_special-background';
        add_action($hook, array(&$custom_background, 'admin_load'));
        add_action($hook, array(&$custom_background, 'take_action'), 49);
        add_action($hook, array(&$custom_background, 'handle_upload'), 49);    
    }
    add_filter('theme_mod_background_image',      'theme_mod_special_background_image');
    add_filter('theme_mod_background_image_thumb','theme_mod_special_background_image_thumb');
    add_filter('theme_mod_background_repeat',     'theme_mod_special_background_repeat');
    add_filter('theme_mod_background_position_x', 'theme_mod_special_background_position_x');
    add_filter('theme_mod_background_attachment', 'theme_mod_special_background_attachment');
    add_filter('theme_mod_background_color',      'theme_mod_special_background_color');
    function theme_mod_special_background_image($defaults) {
        return theme_mod_special_background_image_attrs('image',$defaults);
    }
    function theme_mod_special_background_image_thumb($defaults) {
        return theme_mod_special_background_image_attrs('image_thumb',$defaults);
    }
    function theme_mod_special_background_repeat($defaults) {
        return theme_mod_special_background_image_attrs('repeat',$defaults);
    }
    function theme_mod_special_background_position_x($defaults) {
        return theme_mod_special_background_image_attrs('position_x',$defaults);
    }
    function theme_mod_special_background_attachment($defaults) {
        return theme_mod_special_background_image_attrs('attachment',$defaults);
    }
    function theme_mod_special_background_color($defaults) {
        return theme_mod_special_background_image_attrs('color',$defaults);
    }
    function theme_mod_special_background_image_attrs($attr,$defaults) {
        if (is_special_background_page()) {
            $mods = get_option( 'mods_' . get_current_theme() );
            $defaults = (!empty($mods["special_background_{$attr}"]) ? $mods["special_background_{$attr}"] : '');
        }
        return $defaults;
    }
    add_filter('pre_update_option_mods_' . get_current_theme(),'pre_update_option_special_background_image',10,2);
    function pre_update_option_special_background_image($newvalue, $oldvalue) {
        static $times_called = 0;
        if (!empty($_POST) && is_special_background_page()) {
            if ((isset($_POST['action']) && $_POST['action']=='save') || isset($_POST['reset-background']) || isset($_POST['remove-background'])) {
                switch ($times_called) {
                    case 0:
                        $newvalue = special_background_image_value_swap('image',$newvalue,$oldvalue);
                        break;
                    case 1:
                        $newvalue = special_background_image_value_swap('image_thumb',$newvalue,$oldvalue);
                        break;
                }
            } else {
                if ($times_called==0 && isset($_POST['background-repeat'])) {
                    $newvalue = special_background_image_value_swap('repeat',$newvalue,$oldvalue);
                }
                if ($times_called==1 && isset($_POST['background-position-x'])) {
                    $newvalue = special_background_image_value_swap('position_x',$newvalue,$oldvalue);
                }
                if ($times_called==2 && isset($_POST['background-attachment'])) {
                    $newvalue = special_background_image_value_swap('attachment',$newvalue,$oldvalue);
                }
                if ($times_called==3 && isset($_POST['background-color'])) {
                $newvalue = special_background_image_value_swap('color',$newvalue,$oldvalue);
          }
        }
        $times_called++;
      }
      return $newvalue;
    }
    function special_background_image_value_swap($swap_what,$newvalue,$oldvalue) {
      $newvalue["special_background_{$swap_what}"] = $newvalue["background_{$swap_what}"];
      $newvalue["background_{$swap_what}"] = $oldvalue["background_{$swap_what}"];
      return $newvalue;
    }
    function special_background_admin_page() {
      global $custom_background;
      if (is_special_background_page()) {
        global $parent_file,$submenu_file,$title;
        $parent_file = 'themes.php';
        $submenu_file = 'themes.php?page=special-background';
        $title = 'Special Background';
        require_once(ABSPATH . 'wp-admin/admin-header.php');
        ob_start();
        $custom_background->admin_page();
        $html = ob_get_clean();
        $html = preg_replace('#<h2>([^<]+)</h2>#','<h2>Special Background</h2>',$html);
        echo $html;
        include(ABSPATH . 'wp-admin/admin-footer.php');
        exit;
      }
    }
    function is_special_background_page() {
      global $pagenow;
      return ($pagenow=='themes.php' &&
             isset($_GET['page']) && $_GET['page']== 'special-background');
    }
    

    Frankly it is too much code to explain proactively but I’ll be happy to answer specific questions.

  2. Technically it’s possible (so to extend the wordpress source), but not by default. So I would give the answer to no. The build-in background theme feature is for a single graphics only be default.

    But if you describe a little bit more about the “2 different areas” you’re writing about, there might be something nice to suggest next to this.

    Edit: Highlight for MikeSchinkel. Plugins are extending the wordpress source.