I have a custom meta button that adds additional custom meta fields inside the custom meta box.

Custom Meta Button

This meta box, in particular, gives me a choice to enter a particular skill and rate my own proficiency of the skill using the input ranger, and also remove or add skill entries.

When clicking the red button to the left, it should add another set of form elements where I can input another skill and its corresponding proficiency, with the same option to remove or add skill entries. Basically, the 'red' button populates the custom meta box 'Skills Set' with similar set of form elements (text input, range input, output, two buttons) assigned with another ID for reference and differentiation.

When clicked, it should show this screen (read the note).

the desired results

PROBLEM: The buttons seem to be acting weird. When clicked, the example image above does not happen but the following image appears at the top of the admin edit page.

what appears when clicking the '+' button instead

Here is my code from functions.php

//J. 'About' Page Custom Meta Boxes
//1. Creates meta boxes
function about_custom_meta(){
    //sets up the 'post_id' variable (see IN '$template_file' variable below )
    //NOTE: $_GET['post'] = used when editing a post/page
    //NOTE: $_POST['post_ID'] = needed when publishing/updating post/page
        $post_id = $_GET['post'] ? $_GET['post'] : $_POST['post_ID'];
    //variable that verifies the existence of a desired page template ( see IN if-else scenario below )
        $template_file = get_post_meta( $post_id, '_wp_page_template', true );
    //only displays the custom meta boxes in a 'About' Page Admin
    if( $template_file == 'page-about.php' ) {
        //a. Meta Box for Skillset
        add_meta_box( 'skillset_meta', 'Skills Set', 'create_skillset', 'page', 'normal', 'high' );
add_action( 'add_meta_boxes', 'about_custom_meta' );

//2. Styling and Scripting Support for 'About' Custom Meta Boxes for UI Usability and Functioning Submission
function about_meta_style( $hook ){
    global $post;
    if( $hook != 'edit.php' && $hook != 'post.php' ) {
    if ( !isset( $post ) || 'page' != $post->post_type ) {
    if ( !isset($post) || 'About' != $post->post_title ) {
    //a. enqueue the needed css stylings!
    wp_enqueue_style( 'about-meta-style' , get_template_directory_uri() . '/admin/css/about-meta-style.css' );
    //b. javascript support for 'create_skillset()' function (see below 'create_skillset()' )
    wp_register_script( 'add-skillset', get_template_directory_uri() . '/admin/js/custom-skillset-meta.js', array( 'jquery' ), '1.0', true );
    wp_enqueue_script( 'add-skillset' );
add_action( 'admin_enqueue_scripts', 'about_meta_style', 10, 2 );

//3. Callback for Skills Custom Meta Box
    //a. callback function
function create_skillset(){
    wp_nonce_field( basename( __FILE__ ), 'skillset_nonce' );
        //custom fields
    $skills = get_post_meta( $post->ID, 'skills', false );
    $apt = get_post_meta( $post->ID, 'apt', false );

    echo '
    <table id=\'skill-table\'>
        <tbody id=\'skill-table-cont\'>
            <tr class=\'skillset\'>
                    <input type=\'text\' name=\'skills\' id=\'skillaab\' value=\'\'>
                    <input type=\'range\' name=\'apt\' id=\'aptaab\' min=\'1\' max=\'100\' value=\'1\' oninput=\'percaab.value = parseInt( aptaab.value ) + "%";\'>
                    <output name=\'percaab\' for=\'aptaab\'>1%</output>
                    <button class=\'new-skill-btn\' disabled>
                        <span class=\'dashicons dashicons-plus-alt\'></span>
                    <label for=\'skills\'>Skill Set</label>
                <th colspan=\'2\'>
                    <label for=\'apt\'>Aptitude</label>

The code for the enqueued javascript file 'custom-skillset-meta.js' is here:

jQuery(document).ready( function($){
//generates unique ID (3 alphabetical characters)
function genID(){
    //1. gets all current input elements with 'type' value 'range' inside #skill-table table element
    var ranges = $('input[type="range"]');
    //2. gets each input's 'id' value and 'slice()' it to get the value's distinct string configuration.
    //3. stores each distinct configuration in an array variable.
    var ids = [];
    for (var i = 0; i < ranges.length; i++) {
        var id = ranges.eq(i).attr('id').slice(3, 6);
    //4. generate random string containing 3 characters with possible values from a-z per character.
    function makeID() {
        var genid = '';
        var possible = 'ab';
        for( var i = 0; i < 3; i++ ){
            genid += possible.charAt( Math.floor( Math.random() * possible.length ) );
        return genid;
    var newid = makeID();
    //5. compare the generated random string to each value inside the array variable.
    function isuniqueID( putid ) {
        for (var i = 0; i < ids.length; i++) {
            if ( putid === ids[i] ) {
                return false;
        return true;
    // //6.a. if generated string is equal to at least one value inside the array variable, repeat 4.
    // //6.b. else, store the generated string inside a new variable and return the variable when called.
    if ( !isuniqueID( newid ) ) {
        while( !isuniqueID( newid ) ) {
            var changeid = makeID();
            newid = changeid;
            if ( isuniqueID( newid ) ) {
    return newid;

//generates new skillset (callback function)
function newSkill( uniqueID ){
    //1. html content to be appended
    var htmlcont = '
        <tr class=\'skillset\'>
                <input type=\'text\' name=\'skills\' id=\'skill'+uniqueID+'\' value=\'\'>
                <input type=\'range\' name=\'apt\' id=\'apt'+uniqueID+'\' min=\'1\' max=\'100\' value=\'1\' oninput=\'perc'+uniqueID+'.value = parseInt( apt'+uniqueID+'.value ) + "%";\'>
                <output name=\'perc'+uniqueID+'\' for=\'apt'+uniqueID+'\'>1%</output>
                <button class=\'remove-skill-btn\' disabled>
                    <span class=\'dashicons dashicons-dismiss\'></span>
                <button class=\'new-skill-btn\'>
                    <span class=\'dashicons dashicons-plus-alt\'></span>

    //2. appends html content into the container
    $('#skill-table-cont').append( htmlcont );

//when 'plus' button is clicked
$('button.new-skill-btn').on('click', genID(), function( event ){
    newSkill( genID() );
  • image for desired results. – Migs M. Jul 22 '16 at 6:55
  • Great to read such a well written question. My PHP is better than my JS/jQuery but nothing leaps out as wrong. Better heads might take a look and see something. My first thought though is to take a look at whether any other JS on the page is also binding to your buttons. It looks like you're inadvertently triggering a click on the update button or something similar. Do you have other plugins installed that might be conflicting? – Andy Macaulay-Brook Jul 22 '16 at 8:44
  • @AndyMacaulay-Brook I have no other plugins installed. Every customized features in my wordpress localhost are all in my 'functions.php'. I only showed relevant code from the file into the question. If something is triggering the update button, how do I find out? There are just too many JS files embedded in the admin page for the particular post (which is 'About' Page). I guess I'll try to do it. – Migs M. Jul 22 '16 at 9:38
  • In your click handler, should genID be called twice like that, or should you assign its return value to a variable? – Andy Macaulay-Brook Jul 22 '16 at 10:05
  • I'd turn off everything in functions.php apart from the code for this metabox, just to rule that out. Then with my browser's code inspector I'd check that all the HTML elements are properly closed, just to make sure that the new code hasn't upset the structure of the form. It's pretty unlikely, but you could check that elements aren't inadvertently layered so that you're accidentally clicking Submit. Then I'm afraid I'd have to learn about the JavaScript console - I'm more PHP than JS and haven't extensively debugged JS problems. – Andy Macaulay-Brook Jul 22 '16 at 10:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.