Extended WordPress Settings API Tutorial, Part 2

Download the files (updated June 5, 2011)

This post is based on part 1 of this tutorial, so read it if you haven’t.

We left off with a theme options class, My_Theme_Options, that had all the behind-the-scenes work complete. The next step is the HTML.

4. Display the Options Page and Sections

Up to this point, we’ve had a completely blank options page in our admin. We want to see the fruits of our labor! We use three functions to make this happen: display_page(), display_section(), and display_setting(). Let’s tackle the page and sections first.

Options Page HTML

Add this to the display_page() function:

echo '<div class="wrap">
<div class="icon32" id="icon-options-general"></div>
<h2>' . __( 'Theme Options' ) . '</h2>
<form action="options.php" method="post">
	';
	settings_fields( 'mytheme_options' );
	do_settings_sections( $_GET['page'] );

	echo '<p class="submit"><input name="Submit" type="submit" class="button-primary" value="' . __( 'Save Changes' ) . '" /></p>
</form>';

Look at the theme options page now. There is a big “Theme Options” heading, a subheading for each section, and a whole lot of errors. That’s because there’s no display_section() function written yet, and we’ll get to that next.

The “icon32″ div at the top of the above code is what creates the nice-looking settings icon next to our heading. You can change the id to use a different WordPress icon (onextrapixel has a great cheat sheet).

The settings_fields() function inserts a few hidden form fields, including a nonce for security.

The do_settings_sections() function is looking for sections assigned to the current page slug. Remember the code we used to register the sections in part 1:

add_settings_section( $slug, $title, array( &$this, 'display_section' ), 'mytheme-options' );

The page slug was referenced there, along with the display_section() function.

Sections HTML

The purpose of the display_section() function is only to add descriptive text (or other HTML) to that specific settings section. Whatever is output by this function will be displayed below the section subheading. If you register the sections individually instead of in a loop, you can use a different callback function for each section and insert custom content here.

For now, just put an empty function inside the class:

/* Description for section */
public function display_section() {
	// code
}

5. Display the Form Fields

The reason we wrote a helper function to add our settings to the database is so we could pass certain arguments along to the callback function (which is responsible for outputting the HTML to display the field). This allows us to use the same callback function for every single field, and still get unique displays for each type. Let’s walk through the callback function, display_setting().

/* HTML output for individual settings */
public function display_setting( $args = array() ) {

	extract( $args );

	$options = get_option( 'mytheme_options' );

	if ( ! isset( $options[$id] ) && $type != 'checkbox' )
		$options[$id] = $std;
	elseif ( ! isset( $options[$id] ) )
		$options[$id] = 0;

	$field_class = '';
	if ( $class != '' )
		$field_class = ' class="' . $class . '"';

The arguments for this function, which are the same arguments as our create_setting() function, get passed in an array and then turned into variables by extract(). Then, we create an array of all the existing options in the database with get_option(). The argument for that, ‘mytheme_options’, is the name of our master options array.

If the current setting, $id, doesn’t exist in the database, then it assigns that setting its default value. You should also exclude checkboxes in this if statement, because checkboxes don’t have user-created values (they’re either on or off).

Then we check for a custom class to use for this field. If it’s equal to anything other than an empty string, it will output ‘class=”$class”‘ in the HTML form field.

There is a fairly massive swtich statement coming up next. I’ll just give you the text field code for now, and the rest after I explain it:

	switch ( $type ) {

		case 'text':
		default:
			echo '<input class="regular-text' . $field_class . '" type="text" id="' . $id . '" name="mytheme_options[' . $id . ']" placeholder="' . $std . '" value="' . esc_attr( $options[$id] ) . '" />';

	 		if ( $desc != '' )
	 			echo '<br /><span class="description">' . $desc . '</span>';

	 		break;
	}
}

This is pretty straightforward. It’s printing an HTML input field, with a custom class if the setting has one, and setting its name, id, and value. It prints the description, if it exists, on a line below the field in small text. It’s also setting a “placeholder” attribute. This is an HTML5 attribute, and we’ll be using it to find the default value for that field in some jQuery later on.

Note that I’m using the text field as the default in this switch statement. You can use whichever type you want as the default, just make sure it comes last in the switch statement and has “default:” under the “case” line.

Where are the form labels and the table structure?

The Settings API prints the HTML for these settings inside a table cell that’s already created. WordPress automatically creates the table, creates a row for each field with a table header containing the field label, and opens and closes the table cell around the form field.

This is both good and bad. It saves us a lot of code doing that manually, and it formats it like other settings pages in WordPress so it has the same look and feel. However, it is less flexible for those who want their options page to look a little different. This is where the jQuery comes in (back to that in a bit).

Below is the rest of the switch statement. This code should all go after switch ( $type ) { and before case 'text': for it to work properly.

case 'heading':
	echo '</td></tr><tr valign="top"><td colspan="2"><h4>' . $desc . '</h4>';
	break;

case 'checkbox':

	echo '<input class="checkbox' . $field_class . '" type="checkbox" id="' . $id . '" name="mytheme_options[' . $id . ']" value="1" ' . checked( $options[$id], 1, false ) . ' /> <label for="' . $id . '">' . $desc . '</label>';

	break;

case 'select':
	echo '<select class="select' . $field_class . '" name="mytheme_options[' . $id . ']">';

	foreach ( $choices as $value => $label )
		echo '<option value="' . esc_attr( $value ) . '"' . selected( $options[$id], $value, false ) . '>' . $label . '</option>';

	echo '</select>';

	if ( $desc != '' )
		echo '<br /><span class="description">' . $desc . '</span>';

	break;

case 'radio':
	$i = 0;
	foreach ( $choices as $value => $label ) {
		echo '<input class="radio' . $field_class . '" type="radio" name="mytheme_options[' . $id . ']" id="' . $id . $i . '" value="' . esc_attr( $value ) . '" ' . checked( $options[$id], $value, false ) . '> <label for="' . $id . $i . '">' . $label . '</label>';
		if ( $i < count( $options ) - 1 )
			echo '<br />';
		$i++;
	}

	if ( $desc != '' )
		echo '<br /><span class="description">' . $desc . '</span>';

	break;

case 'textarea':
	echo '<textarea class="' . $field_class . '" id="' . $id . '" name="mytheme_options[' . $id . ']" placeholder="' . $std . '" rows="5" cols="30">' . wp_htmledit_pre( $options[$id] ) . '</textarea>';

	if ( $desc != '' )
		echo '<br /><span class="description">' . $desc . '</span>';

	break;

case 'password':
	echo '<input class="regular-text' . $field_class . '" type="password" id="' . $id . '" name="mytheme_options[' . $id . ']" value="' . esc_attr( $options[$id] ) . '" />';

	if ( $desc != '' )
		echo '<br /><span class="description">' . $desc . '</span>';

	break;

Subheadings Within a Section

In the switch statement, I added a “heading” type as an option. This is useful for dividing up long sections. Since a setting is displayed within a table cell on the right-hand side, I had to cheat the system a bit here. I close the table cell and the table row, and then open a new row with a cell spanning two columns. Then I put an h4 inside to give it a consistent appearance and (somewhat) proper semantics. To avoid displaying a label on the left, the title is left blank, and the text for the heading is put in the description.

6. Custom Javascript and Styling

At this point, the settings page is 100% functional and is visually consistent with the rest of the WordPress admin. You could stop right here and have a solid theme options page. If you want something with a little more pizzazz, then we have more coding to do.

jQuery Tabs

Go back to the add_pages() function and add this line of code under what’s already there:

add_action( 'admin_print_scripts-' . $admin_page, array( &$this, 'scripts' ) );

This calls a function in our class so we can insert our own Javascript, and it only applies it to our theme options page in the admin. Here’s that function:

/* jQuery Tabs */
public function scripts() {
	wp_print_scripts( 'jquery-ui-tabs' );
}

Now we need to add some jQuery code to our admin page. We will do that in the display_page() function. Replace everything inside that function with the following:

echo '<div class="wrap">
<div class="icon32" id="icon-options-general"></div>
<h2>Theme Options</h2>
<form action="options.php" method="post">';

	settings_fields( 'mytheme_options' );
	echo '<div class="ui-tabs">
		<ul class="ui-tabs-nav">';

	foreach ( $this->sections as $section )
		echo '<li><a href="#' . strtolower( str_replace( ' ', '_', $section ) ) . '">' . $section . '</a></li>';

	echo '</ul>';
	do_settings_sections( $_GET['page'] );

	echo '</div>
	<p class="submit"><input name="Submit" type="submit" class="button-primary" value="' . __( 'Save Changes' ) . '" /></p>

</form>
<script type="text/javascript">
	jQuery(document).ready(function($) {

	});
</script>
</div>';

Before we get to the jQuery, I’ve added a couple of things. The entire settings output is now wrapped in a div with class=”ui-tabs”. Then there’s an unordered list with class=”ui-tabs-nav” that loops through our sections to output a link for each one.

Now the jQuery magic. First, we need to make some modification to the code structure. Each section needs to be wrapped in a div with class=”ui-tabs-panel”, but we can’t access any of the code between the sections with just PHP. So we’ll search for the <h3> tags and use those as a marker for beginning a new section.

var wrapped = $(".wrap h3").wrap("<div class=\"ui-tabs-panel\">");
wrapped.each(function() {
	$(this).parent().append($(this).parent().nextUntil("div.ui-tabs-panel"));
});

Thanks, Nathan, for the tip on using nextUntil() instead of next()!

This wraps the section headings inside of the div, and then takes what was directly after the headings—the table with all the form fields in it—and puts it inside that div. The next step is to add id attributes to the headings, and apply a class to all but the first panel to hide it from view:

$(".ui-tabs-panel").each(function(index) {
	var str = $(this).children("h3").text().replace(/\s/g, "_");
	$(this).attr("id", str.toLowerCase());
	if (index > 0)
		$(this).addClass("ui-tabs-hide");
});

The .each() function loops through the panels. By adding the “index” attribute to the function, it generates an arbitrary counter that we can use to determine whether we’re on the first panel.

Finally, apply the actual tabs functionality to our modified HTML:

$(".ui-tabs").tabs({ fx: { opacity: "toggle", duration: "fast" } });

The parameters inside the .tabs() function can be altered to change the animation and speed of the transition between tabs. Check out the jQuery UI documentation to see what’s possible.

Placeholder Text

The default values of our text and textarea fields are currently just showing up as values that the user has to manually erase to enter their own information. This isn’t a horrible thing, but we can make it more user-friendly by adding some jQuery and styling to the mix. Add this to the jQuery block in display_page():

$("input[type=text], textarea").each(function() {
	if ($(this).val() == $(this).attr("placeholder"))
		$(this).css("color", "#999");
});

$("input[type=text], textarea").focus(function() {
	if ($(this).val() == $(this).attr("placeholder")) {
		$(this).val("");
		$(this).css("color", "#000");
	}
}).blur(function() {
	if ($(this).val() == "" || $(this).val() == $(this).attr("placeholder")) {
		$(this).val($(this).attr("placeholder"));
		$(this).css("color", "#999");
	}
});

This takes any field with a default value in it and makes the text grey. The value then disappears when the user clicks on the field (only if the value was the default). When a user clicks out of a field, if the field is still empty, it re-inserts the value and makes it grey again.

Because we’re creating some HTML dynamically and it’s going to be styled after the fact, we use CSS to hide the elements on the page to avoid the “flash” of unstyled content when the page loads. We need to put in one line of jQuery to show that content again when the loading is complete.

$(".wrap h3, .wrap table").show();

There are some strange issues that show up in Firefox because of its autocomplete functionality. To fix that, add this to the jQuery block:

if ($.browser.mozilla) 
         $("form").attr("autocomplete", "off");

Thank you, Billyben, for pointing this out to me!

Custom Styling

All the hard work is done! Everything from here on out is just gravy. To add custom CSS, we need to call our own stylesheet on our admin page.

First, create a new CSS file in your theme folder, and name it what you like (I’ll use mytheme-options.css). Add this to the add_pages() function:

add_action( 'admin_print_styles-' . $admin_page, array( &$this, 'styles' ) );

Now add the styles() function to the theme options class:

/* Insert custom CSS */
public function styles() {

	wp_register_style( 'mytheme-admin', get_bloginfo( 'stylesheet_directory' ) . '/mytheme-options.css' );
	wp_enqueue_style( 'mytheme-admin' );

}

Any CSS you put in that stylesheet will now be applied to your theme options page. To get the look seen in the screenshot below, put this in the stylesheet:

.ui-tabs-nav {
	border-bottom: 1px solid #ccc;
	height: 27px;
	margin: 20px 0;
	padding: 0;
}

.ui-tabs-nav li {
	display: block;
	float: left;
	margin: 0;
}

.ui-tabs-nav li a {
	padding: 4px 20px 6px;
	font-weight: bold;
}

.ui-tabs-nav li a {
	border-style: solid;
	border-color: #CCC #CCC #F9F9F9;
	border-width: 1px 1px 0;
	color: #C1C1C1;
	text-shadow: rgba(255, 255, 255, 1) 0 1px 0;
	display: inline-block;
	padding: 4px 14px 6px;
	text-decoration: none;
	margin: 0 6px -1px 0;
	-moz-border-radius: 5px 5px 0 0;
	-webkit-border-top-left-radius: 5px;
	-webkit-border-top-right-radius: 5px;
	-khtml-border-top-left-radius: 5px;
	-khtml-border-top-right-radius: 5px;
	border-top-left-radius: 5px;
	border-top-right-radius: 5px;
}

.ui-tabs-nav li.ui-tabs-selected a,
.ui-tabs-nav li.ui-state-active a {
	border-width: 1px;
	color: #464646;
}

.ui-tabs-panel {
	clear: both;
}

.ui-tabs-panel h3 {
	font: italic normal normal 24px/29px Georgia,"Times New Roman","Bitstream Charter",Times,serif;
	margin: 0;
	padding: 0 0 5px;
	line-height: 35px;
	text-shadow: 0 1px 0 #fff;
}

.ui-tabs-panel h4 {
	font-size: 15px;
	font-weight: bold;
	margin: 1em 0;
}

.wrap h3, .wrap table {
	display: none;
}

Voilà! I used some CSS3 to achieve some nice visual effects, so there are no images required.This will make the page look consistent with the rest of the WordPress admin.

Theme Options screenshot

Now you have a functional, beautiful, kickass theme options page!

There are still a couple of small things to cover, so be sure to read the follow-up post to this tutorial.

View this post online: http://alisothegeek.com/2011/01/wordpress-settings-api-tutorial-2/

Leave a Reply

82 thoughts on “Extended WordPress Settings API Tutorial, Part 2

  1. Nathan 'Spanky' Briggs says:

    Nice, thanks Aliso.
    Added a little tweak, so I could include a section description using display_section(). I changed $(this).parent().append($(this).parent().nextUntil(“div.ui-tabs-panel”)); to $(this).parent().append($(this).parent().nextUntil(“div.ui-tabs-panel”));
    Otherwise the section comment is included in the section div, but the actual fields fall outside it and don’t change properly as the tabs do. Luckily, jQuery 1.4.2 is shipping with WP as standard now, so we can use the new-to-1.4 function nextUntil();

    • Alison Barrett says:

      Thanks, Nathan! I admit that I didn’t even know about the nextUntil() function. I changed the code in my post to incorporate your tweak.

  2. Brad Vincent says:

    thanks for a really awesome tutorial on the settings API. This is EXACTLY what i was looking for. Nice work!

  3. Avery says:

    Thanks for this great tutorial, it’s very helpful. However when I use it, I notice that the “validate_options” function seems to be missing…I get an error when I try to save the options…

  4. Avery says:

    A few more things — how do I actually use the options in the theme? It’s different because this options page is a class, so how would I access the values?

    And the select, radio and checkbox options in the sample class do not save — I hit “save” and they just reset back to the default values.

  5. bin says:

    Definitely the best approach to the settings api I have seen so far, thanks for this concise tutorial!
    I just noticed some minor flaws. The appropriate attribute for radio options has to be “checked”, and the current state of radio and select options as well as checkboxes should be added to the actual form output, an easy task since the variables are already defined.

  6. kavin says:

    Thanks for the Great tutorial, Aliso. Awesome! :)

    I’ve added some functional modifications to the your mytheme_options object. With proper credit, i would like to implement this technique into the theme i’m developing. Is that ok with you?

    • Alison Barrett says:

      Definitely! Thanks so much! If you don’t mind me asking, what kind of modifications did you make?

      • kavin says:

        Not much, just some basic ones. :)

        Among the Code :
        * Added an option to change the theme name, or get it automatically using get_theme_data(). Theme name is used as options prefix.
        * Thought this is better with set and get methods for Sections and fields, Now it’s easy to use arrays to implement them.
        * Added some additional input options such as File upload, color picker, descriptive lists etc.

        Design:
        Modified the options to switch between different designs – Tabs, accordion or collapsibles etc.

        Only problem here seems to be the method validate_settings. It is necessary to redefine this method with class extend for security reasons.

        BTW, Would you like to take a look at the code? :)

  7. komah says:

    ( sry my bad english )
    just a notice..

    first, in:


    foreach ( $choices as $value => $label ) {
    $selected = '';
    if ( $options[$id] == $value )
    $selected = ' selected="selected"';
    echo '' . $label . '';
    }

    the option stored as selected, can never be “selected”, because there is not the $selected variable in ..

    There is another little trick that i would say to you…
    Without becoming crazy with a lot of nested if else or and blah blah blah, wordpress allow you to use functions like checked(), selected(), disabled().

    So, for example you can do:

    $is_selected = selected( ( $options[$id] == $value ), true );
    echo '' . $label . '';

    this function allow you to compare the first argument with the second, and, if the expression result true, it return the whole “selected=’selected'” string otherwise it return an empty string.

    However, nice tutorial, worth adding to my bookmarks :)

  8. komah says:

    sorry, the option tag was stripped, hope is however clearly :(

  9. miramez says:

    I have problem with CSS style.
    The class works fine, but when i put the CSS codes, my admin panel get crashed.
    how do i fix that?

  10. miramez says:

    let me to explain,
    i using IE9. when i update any field, the style of admin panel (wordpress) is broken and weird. i tried in firefox and it is OK. Just IE9 it becomes crashed

    • Alison Barrett says:

      I’ll look into the IE9 compatibility this week. Bolts is currently in beta, so there are still a handful of kinks to work out.

  11. miramez says:

    Hi,

    i want to set up different class style for each radio options which i called ‘radiostyle’ like bellow:

    $this->create_setting( array(
    ‘section’ => ‘colors’,
    ‘id’ => ‘idcolor’,
    ‘title’ => __( ‘Menu Colors’, CONSTANT ),
    ‘desc’ => __( ”, CONSTANT ),
    ‘type’ => ‘radio’,
    ‘std’ => ”,
    ‘choices’ => array(
    ‘value1′ => ‘name1′,
    ‘value2′ => ‘name2′
    ),
    ‘class’ => ‘radiostyle’

    however, the output is class=”radio radiostyle” for all options. I’d like to customize different style for each options resulting in something like this:

    How do i do that? Thanks

    • Alison Barrett says:

      There’s nothing I’ve put in the theme options class that would easily allow that, but you could use CSS without needing to give each option a specific class. You can customize the CSS based on the value of each option. Example:

      input[value="one of the values"] {
      	color: #f00;
      }
  12. miramez says:

    i tried to post html code in this form, but it was bloqued. continuing about the question above.

    how do i do to generate different styles for each radio options?

    the stuff:

    i want to post different color images in side of each options. i thinked to get the class style to do that in css file.

  13. miramez says:

    hi, its me again. is it possible to include colorpick type, like there is in options framework by Devin?

  14. miramez says:

    Hi, id like to get categories from my database and put it in array to use ‘select’ type… how do do that?

    • Alison Barrett says:

      You’d need to set up the array before you define that ‘select’ option. Something like this:

      $categories = array();
      
      $terms = get_categories();
      
      foreach ( $terms as $term )
      	$categories[$term->term_id] = $term->name;

      Then, when you define your select box, just use the $categories variable instead of a new array:

      'choices' => $categories

      That should do the trick! The above code would make the category ID the value of each option in the select element (<option value="4">Category with ID 4</option>).

  15. Billyben says:

    Really great Job! I’ve adapted it for my widget options pages and it’s really great, except the loss of flexibility… It’s quite hard to get into that api, but you’ve make it quite clear!

  16. Anthony says:

    Great tutorials! I was wondering if you could help me with one thing that would make this PERFECT!

    Upon saving the theme options, there is no notification that occurs. Usually themes use class=”updated” to display a “Your options have been updated” type of message. Any ideas on how to get that working here?

    Thanks!

    Anthony

  17. mira says:

    hi, Do you know when will fix the ‘reset’ button?

  18. Billyben says:

    Hi! I met two issues.First, I tried to include internationalization to your script, and as I’m french (no comment) i’ve got issues with accent for the tab navigation. I solve it by stripping accent from string in php (at the href declaration of list) and in jquery wrapping (for div container id .ui-tabs-panel).Secondly, there is an issue with firefox, radiobutton, some javascript, form and page reload (F5) with the autocomplete function of FF, explain here. this : if($.browser.mozilla)
    $(“form”).attr(“autocomplete”, “off”); solve the problem.

  19. mira says:

    Billyben, is the reset option (radio) working for you?
    it doesnt work for me.

    • Alison Barrett says:

      The reset radio option still isn’t programmed (I forgot to remove it from this code). In the next few days I’m re-posting the code, and I’ll either have that option programmed or removed.

  20. Dominic says:

    I’ve been trying to wrap my head around the settings API to add options to a theme framework I’ve been working on for quite a while now. It wasn’t making much sense until I read this tutorial, thank you so much for taking the time to spell it out for us!

    I just wanted to drop in my two cents.

    You could remove all the jQuery you’re using to handle the placeholder text by altering the ‘text:’ portion of your switch statement from:

    placeholder="' . $std . '" value="' . $options[$id] . '"

    to:

    value placeholder="' . $std . '" value="' . $options[$id] . '"

    By simply adding ‘value’ to ‘placeholder’ the form should handle on it’s own what the jQuery is doing.

    Just a thought to shorten the code.

    Thank you again for writing this!

    Dom
    NYC

    • Thanks for the tip!

      Will that work across all browsers? (Not including IE6!)

      • Dominic says:

        Well after some digging around I realize that I am incorrect. I’ve been writing my input boxes wrong for quite some time now!  :-)

        The proper attribute is just “placeholder”. It is an HTML5 feature so it does not work in any version of IE.

        Looks like jQuery (as always) is the way to go so that it works across browsers.

        Sorry about posting incorrect info.

  21. Genevieve says:

    Thanks so much for this tutorial! I found it easy to understand, implement and adapt. I did have a question, though: I’m wanting to arrange some of my theme options into field sets within a section. How would I do that?

    • Thanks for your comment!

      I built in a “heading” field type that will let you do exactly that. It’s in part 2 (this post). Here’s a link straight to that part: http://alisothegeek.com/2011/01/wordpress-settings-api-tutorial-2/#subheadings-within-a-section

      • Genevieve says:

        Ah ha! I had to go back over that part–went over my head the first time ’round. Thanks so much!

  22. Ray says:

    Just when I’ve almost finished my own settings API field rendering, when I came across your post! ;)

    Looks good! Will give it a test drive!

  23. Norbert says:

    Hi, awesome tutorial! I noticed you said that the table elements are automatically generated. But is there a way to move certain elements around?

    Let’s say I want to move  a setting description from the to the closest so that it’s under the title (on the left). I managed to do it with jQuery, but I just wanted to make sure that there isn’t another way to do it before moving forward.

    Thanks again for this tut!

  24. Roland Barker says:

    Excellent tutorial, gets down to details and doesn’t rely on over-simplified examples that avoid all the hard parts. I like that.

    I have a question: I’m in the throes of writing my own settings page for a plugin and I want to handle all the notifications myself. I have successfully grabbed the errors array ( using get_settings_errors() ) and got my own error messages displaying but I can’t figure out how to get the built-in error messages from displaying also!

    I know the hook is “admin_notices”, and I’m using it, but so it the core.

    Any insights on this? Thanks!!

  25. Javaadh says:

    Brilliant tutorial. I was looking for a way to wrap theme options in a class and found this tutorial. It was very helpful. Keep up the good work. Man you rock :)

  26. Habli Muhammad Rizal A says:

    Thanks for this tutorial.. it’s very helpfull :D

  27. Alex Krumm says:

    First off, great tut.  My options page looks FABULOUS.

    I’m trying to implement the settings API, but I’m having some difficulty saving data to an assigned array within my setting.

    My options page has dynamically created fields that the user can add or remove using JQuery (i.e., ‘add another field’ and ‘remove this field’.)  I want to save the values from those fields to an array so that I call them back with a ‘foreach’ statement.

    What it’s saving now:

    Array ( [example_text] => Default value [example_textarea] => Default value [example_jquery] => test1 [example_jquery2] => test2 [example_jquery3] => test3 [example_select] => choice1 [recrm_lead_sources] => Website Lead Circle Of Influence Past Referral [header_logo] => [favicon] => [custom_css] => )

    What I’d like it to save:

    Array ( [example_text] => Default value [example_textarea] => Default value [example_jquery] => Array ( [example_jquery1] => test1 [example_jquery2] => test2 )[example_select] => choice1 [recrm_lead_sources] => Website Lead Circle Of Influence Past Referral [header_logo] => [favicon] => [custom_css] => )

  28. Josepena says:

    Great work!, thank you so much, i only miss a few things: validation, colorpicker and upload button.

    Is there any plan for explain how to include this, like a part 3 tutorial :P?

  29. Anonymous says:

    Hello, and thanks for the GREAT admin options theme class!

    I just had something i could add regarding this line:

    // Browser compatibility
    if ($.browser.mozilla)
    $(“form”).attr(“autocomplete”, “off”);

    The jQuery API recommends against using the $.browser
    method.. (see DOCS in API: http://api.jquery.com/jQuery.browser/)
    jQuery API recocommends to use jQuery.support.
    (http://api.jquery.com/jQuery.support/)
    The reason being is that jQuery.browser uses the user agent which can be
    spoofed and it is actually deprecated in later versions of jQuery. It’s
    better to use feature detection instead of browser detection.

    Its best to use the below when checking if the browser is Mozilla Firefox.. which basically detects the Gecko rendering engine:

    // Browser compatibility
    var FF = !(window.mozInnerScreenX == null);
    if (FF)
             $(“form”).attr(“autocomplete”, “off”);

    Thanks again for your GREAT Class!!!

    jonathan

  30. Eddie Moya says:

    Not sure if there’s something I tinkered with by mistake, but I think ‘if( $i < count( $options) -1)' should be 'if( $i < count( $choices) -1)'

    That aside, amazing job with this, very clean and extremely easy to read, and handles most anything you could need from an options page. Only additions I might need to make is to allow the user to upload an image (like you can in a custom header), and perhaps a color picker.

    Again, great job with this.

  31. Donin Nick says:

    Hi. I found your settings api, and want use on my feature theme. But i not understand how right use.
    When I create a class object, I have the ability to create their own settings. How to create them properly?
    My ex.
    $theme_options = new My_Theme_Options();$args = array(    ‘section’ => ‘color’,    ‘id’ => ‘idcolor’,    ‘title’ => __(‘Menu Colors’, ‘twentyten’),    ‘desc’ => __(”, ‘twentyten’),    ‘type’ => ‘radio’,    ‘std’ => ”,    ‘choices’ => array(        ‘value1′ => ‘name1′,        ‘value2′ => ‘name2′    ),    ‘class’ => ‘radiostyle’);$theme_options->create_setting($args);
    Answer me this question:
    1. How to create section?
    2. How to add fields in create new section?
    Thanks

  32. Miramezjr says:

    I wonder if it will be updated using media upload… Just it to get perfect!

  33. Newb says:

    Please! How do I insert a submenu_page under add_pages.
    Instead show the main menu in “Appearance” worpress menu, i’d like ro create a New Menu with Submenu sections.

    I have this one to create a new menu with icon – working fine:

    $admin_page     = add_menu_page(__( MY_THEME.’ Configuracoes’, MY_THEME ), __( MY_THEME, MY_THEME ), ‘manage_options’, ‘pp-options’, array( &$this, ‘display_page’ ), get_bloginfo(‘stylesheet_directory’).’/images/favicon.ico’ );

    How do i insert add_submenu_page() ?

    I tried this one:

    add_submenu_page( ‘tools.php’, __( MY_THEME.’ Configuracoes’, MY_THEME ), __( MY_THEME, MY_THEME ), ‘manage_options’, ‘pp-options’, array( &$this, ‘display_page’ ) );

    But didn’t work, i think because the “$admin_pag” variable.

    Does anybody can help me?

  34. Sathesh says:

    Thank you.. Your script is really helpful.. 

  35. Sangsaka says:

    is it possible to change “reset” checkbox into a reset button?

  36. Cristi says:

    Hello. Great tutorial. I have a question: If i write a text in the “Example Text Input” field and i want the text to be displayed as a paragraph what code do i need? I am a beginner and i haven’t quite figured that out…Thank you!

  37. srcliveRtransat says:

    Thanks :). How to add multiple checkbox field ? :)

    • Shiba says:

      Im struggling with the same…

    • ahnkeelee says:

      Her code doesn’t natively support multiple checkboxes if I’m understanding it correctly. You’d have to modify the code to extend that functionality. (I’m at work so I’m unable to test it right now but I think something like this should work.

      In the ‘display_setting’ function, you’ll have to modify the switch statement.

      The original code is:
      echo ‘ ‘ . $desc . ”;

      You probably want to do something like this to mirror her code for radio inputs:
      case ‘checkbox':

      foreach ($choices as $value => $label) {
      echo ‘ ‘ . $label . ”;
      if ( $i < count( $choices ) – 1 )
      echo '';
      $i++;
      }

      break;

      Then in your get_settings function, you can modify your usage of the checkboxes.
      $this->settings[‘example_checkbox’] = array(
      ‘section’ => ‘general’,
      ‘title’ => __( ‘Example Checkbox’ ),
      ‘desc’ => __( ‘This is a description for the checkbox.’ ),
      ‘type’ => ‘checkbox’,
      ‘std’ => ”,
      ‘choices’ => array(
      ‘choice1′ => ‘Choice 1′,
      ‘choice2′ => ‘Choice 2′,
      ‘choice3′ => ‘Choice 3′
      )
      );

      Not sure that code above works 100% but something like that I think should work. Good luck!

  38. Shiba says:

    I am facing a problem in this… When i select any tab it disappears, rather i want it to be visible with its URL changing automatically. Where in the code do I have to make necessary changes? Can somebody help me solve this?

  39. ahnkeelee says:

    Hi. Great, great tutorial. It really helped me get a better understanding of the API and I love the way you set up your helper functions.

    I found a typo that was driving me crazy for a while, and hopefully you can make the edit or it can help someone.

    In Step 5, you have the following code:
    extract( $args );

    $options = get_option( ‘mytheme_options’ );

    if ( ! isset( $options[$id] ) && ‘type’ != ‘checkbox’ )

    In the if statement, you should be checking for variable $type != ‘checkbox’.
    Your code currently checks to see if the two strings are equivalent (which will obviously resolve as false), and this will interfere with properly displaying the checkbox options.

  40. Shiba says:

    I downloaded the .zip.. Can somebody tell me what is the use of function mytheme_option($option). How do i use this function? What exactly should be passed to this function?

  41. Kosher Kenn says:

    Hi, Thanks so much for the code. its very helpful and I was able to extend its function, adding color picker, time picker, and other user friendly stuff. its the best script I’ve seen so far.

    However, I just wanted to know if its possible to stay on the current tab after hitting Save Changes.

    Right now, When you are lets say on the Reset Settings tab, or not in the First Tab. When you click Save Changes, it will refresh the page and will load the the first Tab again.

    It is possible to improve the update option by using ajax submit? so the page wont load and will stay on the current tab?

    I have successfully added an ajax fire request on my php script using

    if (isset($_GET[‘settings-updated’] ) && $_GET[‘settings-updated’] == true)

    that will automatically create minified css file based on the settings option. However, when I try to modify the submit button to use ajax request on submission, I failed.

    I was thinking its not really that hard. its just that I have very poor knowledge with PHP, and Javascript/Jquery.

    I always ask help from google where I was able to understand and modify some of the code I got from people like you where I actually dont understand the whole process and construction :D

    Thanks Again.. I appreciate any response

  42. Sergeo says:

    Hello,
    Sorry for my bad english.
    I have read this tutorial, and I have question.
    for example:
    In admin panel I have – Example Text Input : I write: Hello word!

    How i can paste code in my frontpage:
    Example Text Input

  43. Jeremy Gerster says:

    Thank you so much for your tutorial! I learned so much and it was very descriptive. I’m having problems adding to it though.

    I added a tinymce case and what I put was:

    case ‘tinymce':
    default:
    wp_editor($options[$id],$id);

    break;

    But it doesn’t seem to work. The editor shows up with the Add Media button. Visual and Text tabs and then a line below them. If I click on the Text tab it’ll show a text box with my ‘std’ but it won’t save anything inserted. Is there something else I have to do to enable this? Thank you again for your awesome work!

  44. Jose says:

    Hi, great tutorial, i have used your class for some theme options, but now i am willing to upload a theme to WordPress Repository and have found this link mandatory:

    Can you tell me if this class would be accepted in WordPress theme repository? Or do i have to add it something? Thank you very much. A php class newbie

    • I think you’d need to make some significant changes—ideally writing your own code from scratch using this tutorial as an example—after reading this requirement from the page you linked:

      Themes are required to implement Theme Options and Theme Settings pages deliberately, rather than relying on copy-and-paste scripts from website tutorials.

      If you’re a PHP class newbie, I recommend trying to write your own code and make it work the way you want in your theme, following the guidelines on that page. Writing it from scratch will help you understand it inside and out, and you’ll be able to make sure it meets all the requirements.

      • Jose says:

        Hi, thanks for the answer, of course i agree, i have developed my own custom framework based on this class, i have added new functions, added new fields, customized everything to avoid conflicts…etc

        I have bundled it in a theme and all works properly, i think this should not be a problem. What i mean mainly is the sanitization and validation of data.

  45. hard says:

    Hello

    How i can get this value in the front end like logo or other option please..

  46. Gukni says:

    Hi,
    How can I call this text example value in a page template? Big thanks

    $this->settings[‘example_text’] = array(
    ‘title’ => __( ‘Example Text Input’ ),
    ‘desc’ => __( ‘This is a description for the text input.’ ),
    ‘std’ => ‘Default value’,
    ‘type’ => ‘text’,
    ‘section’ => ‘general’
    );