Chained Selects for ExpressionEngine

Tutorial explaining how to use chained select boxes that link categories to entries and refresh on selection.

Note this article was posted 11 years ago so techniques may not work anymore.

Intro

This tutorial is based on the instruction provided for the Simple chained combobox plugin for jQuery by Ziadin Givan.

While adapting it with ExpressionEngine we also learn about the channel:categories tag, PHP in your templates and the Input Class.

Header

Download both the ChainedSelects plugin and the SelectBoxes plugin and upload both to your server.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
	<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.7.2.min.js"><\/script>')</script>
	<script type="text/javascript" src="/assets/js/jquery.chainedSelects.js"></script>
	<script type="text/javascript" src="/assets/js/jquery.selectboxes.min.js" charset="utf-8"></script> 

	<script type="text/javascript">
		$(function()
		{
		    $('#blogcategory').chainSelect('#entrydrop','/blog/combobox/',
		    { 
		        before:function (target) 
		        { 
		            $("#loading").css("display","block");
		            $(target).css("display","none");    
		        },
		        after:function (target) 
		        { 
		            $("#loading").css("display","none");
		            $(target).css("display","inline");
		             $(".jumpmenu").change(function() {
		                var val = $(this).selectedValues();
		                if (val != '') {
		                    location.href=val;
		                }
		            });
		                if ($(target).val() == null)
		                        {
		                    $(target).css("display","none");
		                    }
		        }
		    });
		});
		</script>

The path reference to _blog/combobox/_ is a template you will have to create. Blog being a template group and combobox is a template. Leave it blank for now but turn PHP on for it and set the parsing to input.

HTML Code

Add this to whatever template you wish your chained select boxes to appear.

<div id="categorypicker">
            <select id="blogcategory" name="blogcategory">
                <option value="">Select a Category</option>
                {exp:channel:categories channel="news" show_empty="no" style="linear"}
                <option value="{category_id}">{category_name}</option>
                {/exp:channel:categories}
            </select>
            <select name="entrydrop" id="entrydrop" style="display:none;" class="jumpmenu" ></select>
        <div id="loading"></div>
     </div>

Server Side Code

Now in that template we created earlier on (_blog/combobox_) we are gonna dump the following. The original tutorial we are adapting used a json_encode but ExpressionEngine has trouble with that so we use a custom function to grab an array in the correct format and throw it back at the select box.

<?php
	$array = array();
	$cat_id =  $this->EE->input->get('_value');
	
	    $query = $this->EE->db->query("SELECT title, url_title  FROM exp_category_posts INNER JOIN exp_channel_data USING(entry_id) INNER JOIN exp_channel_titles USING(entry_id) WHERE cat_id = '".$cat_id."' AND status ='open'"); 
	         
	            $array[] = array(null => 'Choose an article');
	            foreach($query->result_array() as $row)
	        {
	            $entry_title = ($row['title']); 
	            $entry_url_title = ($row['url_title']);
	            $custom_url = '/blog/'.$entry_url_title;
	            $array[] = array($custom_url => $entry_title);
	        
	        }
	
	function php2js($a)
	    {
	        if (is_null($a)) return 'null';
	        if ($a === false) return 'false';
	        if ($a === true) return 'true';
	        if (is_scalar($a)) {
	            $a = addslashes($a);
	            $a = str_replace("\n", '\n', $a);
	            $a = str_replace("\r", '\r', $a);
	            $a = preg_replace('{(</)(script)}i', "$1'+'$2", $a);
	            return "'$a'";
	        }
	        $isList = true;
	        for ($i=0, reset($a); $i<count($a); $i++, next($a))
	            if (key($a) !== $i) { $isList = false; break; }
	        $result = array();
	        if ($isList) {
	            foreach ($a as $v) $result[] = php2js($v);
	            return '[ ' . join(', ', $result) . ' ]';
	        } else {
	            foreach ($a as $k=>$v)
	                $result[] = php2js($k) . ': ' . php2js($v);
	            return '{ ' . join(', ', $result) . ' }';
	        }
	    }
	echo php2js( $array );

	?>