Add a preview to a WordPress Control Panel

I’m trying to create a new wordpress template and inside it I added a Control Panel, inside this control panel there is an option that allows user to choose where he want’s to place a on a map, I try to explain: user can set div’s left and top attributes via control panel.
Now I know how to add an iframe that can show a preview of the changes but it doesn’t work as I would like (how to add the preview? read here: Modify CSS via Theme Control Panel) What I would like to add is a real time preview. As soon as the user modify TOP or LEFT attribute preview has to show what it is happening without showing it to “live” blog.

Here is my function.php:

Read More
array( "name" => "Before we start",
    "type" => "section"),
array( "type" => "open"),
array( "name" => "Where is the map?",
    "desc" => "Insert map page url",
    "id" => $shortname."_pama",
    "type" => "text",
    "std" => "http://examplepage.com"),
array( "type" => "close"),
array( "name" => "Zona 1",
    "type" => "section"),
array( "type" => "open"),
array(  "name" => "Activate zona 1?",
    "desc" => "Choose yes or no",
    "id" => $shortname."_zona1c",
    "type" => "checkbox",
    "std" => "false"),
array( "name" => "Zona 1 X-Axis",
    "desc" => "Where do you want it on x-axis?",
    "id" => $shortname."_zona1x",
    "type" => "text",
    "std" => "Left:???"),
array( "name" => "Zona 1 Y-Axis",
    "desc" => "Where do you want it on y-axis?",
    "id" => $shortname."_zona1y",
    "type" => "text",
    "std" => "Top:???"),
array( "type" => "close"),
array( "name" => "Zona 1",
    "type" => "section"),
array( "type" => "open"),
array(  "name" => "Activate zona 2?",
    "desc" => "Choose yes or no",
    "id" => $shortname."_zona1c",
    "type" => "checkbox",
    "std" => "false"),
array( "name" => "Zona 2 X-Axis",
    "desc" => "Choose where you want it on X-Axis",
    "id" => $shortname."_zona2x",
    "type" => "text",
    "std" => "Left:???"),
array( "name" => "Zona 2 Y-Axis",
    "desc" => "Choose where you want it on Y-Axis",
    "id" => $shortname."_zona2y",
    "type" => "text",
    "std" => "Top:???"),
array( "type" => "close"),
array( "type" => "close"),
);

This is the iframe that I use to show the preview inside Control Panel:

<iframe src="<?php echo clean_url(apply_filters('preview_post_link', add_query_arg('preview', 'true', get_option('appacqua_pama')))); ?>" width="100%" height="600" ></iframe>

Ok, now the big question is there a STEP TO STEP way to add a preview on real time (I don’t know how to explain it better, I’m really sorry…), what do you think will it be possible to use ajax? (I heard about it but I’m not a programmer so please write in a Dummy Proof way!!!) Will I need to add also a PREVIEW button instead of only SAVE button? How to add it? Do you know Mystique theme by digitalnature? something like this will be GREAT! If you can’t write it here why don’t you write a very good, and step to step, tutorial on your website? There is a lack of good articles about how to create a very good Theme-Option panel with a lot of functionalities for wordpress 3.x maybe you’ll be the next and you’ll also help us…poor noobs 🙂
Thank you very much for your time and patience!

Related posts

Leave a Reply

2 comments

  1. If you look at Mystique theme (a great example of option panel with preview BTW) you can see that the main idea is to lavrage the form fields OnChange or change() events to load the theme’s preview with Jquery and a bit of ajax.

    So you have one function to load by ajax the preview

    function mystique_get_site_preview() {
      check_ajax_referer("site_preview"); ?>
      <iframe id="themepreview" name="themepreview" src="<?php echo get_option('home'); ?>/?preview=1"></iframe>
      <?php die();
    }
    

    and to create the auto preview effect you use some JQuery with PHP:

    $nonce = wp_create_nonce('site_preview');
    ?>
    <script type="text/javascript">
        jQuery(document).ready(function () {
            jQuery("#$zona1y").change(function() {// if a user changed the y-Axis
                check_preview_refresh();
                }
            );
            jQuery("#$zona1x").change(function() {// if a user changed the x-Axis
                check_preview_refresh();
                }
            );
        });
    
        function check_preview_refresh(){
            if (jQuery("#zona1y").val() != '' && jQuery("#zona1x").val() != '' ){
                jQuery.ajax({
                    type: "post",url: "admin-ajax.php",data: { action: 'site_preview', _ajax_nonce: '<?php echo $nonce; ?>' },
                    success: function(html){
                        jQuery("#themepreview").html(html);
                        jQuery("#themepreview").show();
                    }
                });
            }
        }
    </script>
    

    Now this code assumes that you have two input fields with the id of “zona1y” and “zona1y”
    and a div wrapping your Iframe with the id of “themepreview”.

    and that should get you started.

    Update:

    I forgot you will need to add:

    add_action('wp_ajax_site_preview', 'mystique_get_site_preview');
    

    Now

    the first part + the last line of code go in your functions.php

    and the second part needs to go on your theme option panel page.

  2. Even though it appears the author solved his request, I’ll post a better solution on how to achieve this (I’m also the author of Mystique btw). Maybe it will help others.

    So, first you need the iframe document – your home page. I’m using ajax to get it just like in the function above, but you don’t necessarily need to do this. You can just normally add the iframe above your theme setting fields, just like any HTML.

    Remember to append a query argument to the iframe target URL, like <?php home_url(); ?>/?themepreview (or user add_query_arg or whatever). This is important, you’ll see later.

    Next, you need to find a way to communicate with the iframe. Check out the postMessage and JSON2 scripts. Enqueue them in your settings page.

    Now, simply bind a function on the events you need to the live preview to fire. For example, assuming you have a text input named “page_width”:

    <input name="page_width" />
    

    in your jQuery document.ready function you would have something like this:

    // event can be anything, click/change/input or a custom colorpicker event...
    $("input[name='page_width']").change(function(){
    
      // get the value entered by the user
      var current_page_width = $(this).val();
    
      // send this value trough postMessage to the iframe document
      pm({
        target: window.frames["themepreview"],  // this needs to be the iframe ID
        type: 'page_width',
        data: current_page_width
      });
    });
    

    So the pm function will send the input value to the iframe.

    Now for the iframe to change its contents, you need to include the above scripts on the front-end too. But only do this if the query argument above is present, so you only include them when a theme preview is requested, and not on every page load.

    In the front-end’s document.ready handle the receiving part, with pm.bind():

    // first argument should be the "type" from above
    pm.bind('page_width', function(data){
    
      // data that's being received is the 'current_page_width', so just set the new width to the element you need to
      $('#page').css('width', data + 'px');
    
    });
    

    And that’s it 🙂

    You can also find sample code in version 3 of Mystique…