0

I am trying to populate a dropdown with JSON. It works in every other browser except IE. If I add

alert(response.html);

after the success response, it shows the data correctly. But IE won't populate the dropdown with that data. Any help will REALLY be appreciated!!!

<script type="text/javascript">
jQuery(document).ready(function() {
(function($) {
    $('select[name="post_type"]').change(function(event) {
        $.post( <? php echo json_encode(admin_url('admin-ajax.php')); ?> , {
            action: 'wpse158929_get_terms_for_cpt',
            post_type: $(this).val(),
            taxonomy: <? php echo json_encode($taxonomy); ?> ,
            current_selected: $('select[name="location"]').val(),
                nonce: <? php echo json_encode(wp_create_nonce('wpse158929_get_terms_for_cpt_submit_')); ?>
        }, function(response) {
            if (response && !response.error) {
                $('select[name="location"]').html(response.html);
            }
        }, 'json');
    });
    // Remove if you don't want to call change immediately.
    $('select[name="post_type"]').change();
})(jQuery);
});
</script>

This is the function for the 2 dropdowns:

function my_dropdown_categories( $taxonomy, $current_selected = '', $include = null ) {
// Get all terms of the chosen taxonomy
$terms = get_terms($taxonomy, array('orderby' => 'name'));

// our content variable
$list_of_terms = '<select  id="location-dropdown" class="fade-in five selectboxSingle" name="location">';

            // the current selected taxonomy slug ( would come from a QUERY VAR)
            //$current_selected = "asfasdf";

if ( ! is_wp_error( $terms ) ) foreach($terms as $term){

    // If include array set, exclude unless in array.
    if ( is_array( $include ) && ! in_array( $term->slug, $include ) ) continue;

    $select = ($current_selected == $term->slug) ? "selected" : ""; // Note: ==

    if ($term->parent == 0 ) {

        // get children of current parent.
        $tchildren = get_term_children($term->term_id, $taxonomy);

        $children = array();
        foreach ($tchildren as $child) {
            $cterm = get_term_by( 'id', $child, $taxonomy );
            // If include array set, exclude unless in array.
            if ( is_array( $include ) && ! in_array( $cterm->slug, $include ) ) continue;
            $children[$cterm->name] = $cterm;
        }
        ksort($children);

        // OPTGROUP FOR PARENTS
        if (count($children) > 0 ) {
           //  $list_of_terms .= '<optgroup label="'. $term->name .'">';
             if ($term->count > 0)
                 $list_of_terms .= '<option class="option-parent" value="'.$term->slug.'" '.$select.'>'. $term->name .'</option>';
        } else
            $list_of_terms .= '<option value="'.$term->slug.'" '.$select.'>'. $term->name .' </option>';
        //$i++;

        // now the CHILDREN.
        foreach($children as $child) {

             //$select = ($current_selected) ? "selected" : ""; // Note: child, not cterm
             $list_of_terms .= '<option class="option-child" value="'.$child->slug.'" '.$select.'>'. "&nbsp;&nbsp;" . $child->name.' </option>';

        } //end foreach

        if (count($children) > 0 ) {
            $list_of_terms .= "</optgroup>";
        }
    }
}

$list_of_terms .= '</select>';

return $list_of_terms;
}

add_action( 'wp_ajax_wpse158929_get_terms_for_cpt', 'wpse158929_get_terms_for_cpt' );
add_action( 'wp_ajax_nopriv_wpse158929_get_terms_for_cpt',     'wpse158929_get_terms_for_cpt' );

function wpse158929_get_terms_for_cpt() {
$ret = array( 'html' => '', 'error' => false );

if ( ! check_ajax_referer( 'wpse158929_get_terms_for_cpt_submit_', 'nonce', false /*die*/ ) ) {
    $ret['error'] = __( 'Permission error', 'wpfm' );
} else {
    $post_type = isset( $_REQUEST['post_type'] ) ? $_REQUEST['post_type'] : '';
    $taxonomy = isset( $_REQUEST['taxonomy'] ) ? $_REQUEST['taxonomy'] : '';
    $current_selected = isset( $_REQUEST['current_selected'] ) ? $_REQUEST['current_selected'] : '';

    if ( ! $post_type || ! $taxonomy ) {
        $ret['error'] = __( 'Params error', 'wpfm' );
    } else {
        global $wpdb;
        $sql = $wpdb->prepare( 'SELECT t.slug FROM ' . $wpdb->terms . ' t'
            . ' JOIN ' . $wpdb->term_taxonomy . ' AS tt ON tt.term_id = t.term_id'
            . ' JOIN ' . $wpdb->term_relationships . ' AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id'
            . ' JOIN ' . $wpdb->posts . ' AS p ON p.ID = tr.object_id'
            . ' WHERE tt.taxonomy = %s AND p.post_type = %s AND p.post_status = %s'
            . ' GROUP BY t.slug'
            , $taxonomy, $post_type, 'publish' );
        $include = $wpdb->get_col($sql);
        $ret['html'] = my_dropdown_categories( $taxonomy, $current_selected, $include );
    }
}

wp_send_json( $ret );
}
3
  • have you seen stackoverflow.com/questions/412734/…? It has quite some possible solutions... Commented Aug 28, 2014 at 11:39
  • Which version of jQuery are you using? 1.x versions will support IE8, but 2.x versions only support IE9 and higher. See here for details: jquery.com/browser-support Commented Aug 28, 2014 at 11:45
  • I'm using version 1.7.1 Commented Aug 28, 2014 at 12:40

1 Answer 1

0

Internet Explorer had always problems with dynamic HTML and dropdowns, mostly with .html() . You should create the dropdown with a more compatible way:

var json = [{value:"foo",text:"text 1"},{value:"bar",text:"text 2"}];
$("#myid option").remove();
$.each(json,function(k,v) {
   $("#myid").append($("<option></option>",{value:v["value"],text:v["text"]}));
});

The above works for IE11. You can also try this vanilla way for even more compatibility:

var json = [{value:"foo",text:"text 1"},{value:"bar",text:"text 2"}];
var d = document.getElementById("myid");
for(var x in json) {
   d.options[x] = new Option(json[x]["text"],json[x]["value"]);
}

UPDATE 2

Something like this:

PHP

echo json_encode("html_options"=>array(
   array("text"=>"text 1","value"=>"foo"),
   array("text"=>"text 2","value"=>"bar"),
));

JS

$("select[name="location"] option").remove();
$.each(response.html_options,function(k,v) {
   $("select[name="location"]").append($("<option></option>",{value:v["value"],text:v["text"],selected:v["selected"],class:v["class"]}));
});

or

var d = document.getElementById("myid");     <--- you need a select id here
for(var x in response.html_options) {
   d.options[x] = new Option(response.html_options[x]["text"],response.html_options[x]["value"]);
   d.options[x].className = response.html_options[x]["class"];
   if (response.html_options[x]["selected"]) {
      d.selectedIndex = x;
   }
}

this is the modified my_dropdown_categories that returns the options in array (not the HTML).

function my_dropdown_categories( $taxonomy, $current_selected = '', $include = null ) {
   $options = array();
   // Get all terms of the chosen taxonomy
   $terms = get_terms($taxonomy, array('orderby' => 'name'));
   if ( ! is_wp_error( $terms ) ) foreach($terms as $term) {
      // If include array set, exclude unless in array.
      if ( is_array( $include ) && ! in_array( $term->slug, $include ) ) continue;
      $select = ($current_selected == $term->slug); // Note: ==
      if ($term->parent == 0 ) {
         // get children of current parent.
         $tchildren = get_term_children($term->term_id, $taxonomy);
         $children = array();
         foreach ($tchildren as $child) {
            $cterm = get_term_by( 'id', $child, $taxonomy );
            // If include array set, exclude unless in array.
            if ( is_array( $include ) && ! in_array( $cterm->slug, $include ) )     
               continue;
            $children[$cterm->name] = $cterm;
         }
         ksort($children);

         // OPTGROUP FOR PARENTS
         if (count($children) > 0 ) {
            if ($term->count > 0) {
               $options[] = array("value"=>$term->slug,"text"=>$term->name,"class"=>"option-parent","selected"=>FALSE);
            }
         } else {
            $options[] = array("value"=>$term->slug,"text"=>$term->name,"class"=>"option-parent","selected"=>$select);
         }
         // now the CHILDREN.
         foreach($children as $child) {
            $options[] = array("value"=>$child->slug,"text"=>$child->name,"class"=>"option-child","selected"=>$select);
         } // end foreach
      }
   }
   return $options;
}

Then you call your func to populate the 'html_options' (instead the 'html') and return the $ret.

$ret['html_options'] = my_dropdown_categories( $taxonomy, $current_selected, $include);
Sign up to request clarification or add additional context in comments.

19 Comments

Would this work in IE8 and below? How would I implement that?
You need to return values and text for the options rather than complete html etc. <option>..</option> from the AJAX for full compatibility with IE. The vanilla way will surely work since it does not use jquery, though you have to test the first method but both ways are more compatible than a .html call.
I'm really battling to implement that. I've posted my function for the two dropdowns in my original post, will your answer still be suited for that?
Yes, my UPDATE code is suited for your dropdown with name = location (since this is the one you're changing) but you need to also modify your own code so you dont have to return just the html from your my_dropdown_categories. You have to extract the value and text for your options from your PHP somehow and pass them to wp_send_json as my example in PHP. As a side note i just tested my 2 approaches (jquery and vanilla), they both worked down to IE6.
Just took a peek into your function my_dropdown_categories. What you need to extract really are the $term->slug (the value) and $term->name (the text). AH i see you're adding some $childs also... makes that more complex... Allow me to modify your function somehow
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.