Blog Post Editor: Categories Selection

Posted Oct 26, 2014

Categories Selection

The user can select a category in 2 ways:

  1. Start typing the category, or
  2. Press the down arrow, which will provide a list of categories

Either way will produce the drop-down of categories as shown below:

Portfolio-BlogAdmin-Step3

 

There is code for the categories selection in:

The PHP Edit View:

<div class="input select" id="select_categories">
Categories<br>
<ul class="item-list categories">
 
<?php
// Loop through each category
foreach ($categories AS $categoryId=>$categoryName)
{
  	// If this category is in the array of categories already associated with this post (in the categories_posts table), then set class=active to show the category. Otherwise the category stays hidden and isn't selected
  	if (in_array($categoryId,$categoriesSelected))
  	{
          	$selected = "class='active'";
  	}
  	else
  	{
          	$selected = "";
  	}
  
  	// Create each category in a list, but only display if class=active is set
  	echo '<li item="' . $categoryId. '" title="' . $categoryName . '"' . $selected . '>' . $categoryName;;
  
  	// Allow removal of an active category
  	echo '<a class="close" title="Remove ' . $categoryName . '">x</a>';
  	echo '</li>';
}
 
 	// This is an autocomplete input form, that displays available categories. You can also cursor down to display a list
?>
 
<li class="input"><input class="item-input" value="" tabindex="2" placeholder="Start typing or press down"></li>
</ul>
</div>

 

The Javascript for the Edit View:

$(function()
{
 	// Enable a multi auto complete drop down box when selecting categories to apply blog post to
 	$(".categories").multiautocomplete({formField: "#categories"});
});
 
 

 

And the Multi Auto Complete Javascript code:

$.widget("ui.verboseautocomplete", $.extend({}, $.ui.autocomplete.prototype, {
 
  _response: function(contents)
{
      $.ui.autocomplete.prototype._response.apply(this, arguments);
      $(this.element).trigger("autocompletesearchcomplete", [contents]);
      //alert("response")
}
 
}));
 
(function($) {
 
 	//multiautocomplete is called upon loading the page from \admin\app\webroot\js\posts\edit.js
 	$.fn.multiautocomplete = function(options) {
 	var options	= options || {};
 	options.formField	= options.formField || "";
 
 	// itemList is binded to <ul class="item-list categories"> and we'll loop through each <li>
 	var itemList = this;
 
 	// Will hold all the categories
 	var names = [];
 
 	// Used to create the indexed array for the HABTM relation between a Post and its Categories
 	var postCategoryCounter = 0;
 
 	// This will hold all the selected categories to pass through the form
 	var outArray = [];
 
 
 	function setOutput(){
 
 	var categoryIdField;
 	var postIdField;
 	var postIdValue = document.getElementById("PostId").value;
 	var x;
 
 	// Find already selected (active) categories, and add to the outArray
 	itemList.find("li.active").each(function(){
 
 	// Check if it already exists
 	if(outArray.indexOf($(this).attr("item")) == -1)
 	{
 
 	outArray.push($(this).attr("item"));
 
 	categoryIdField = '<input type="hidden" class="categories" name="data[Category][' + postCategoryCounter + '][id]" value="' + $(this).attr("item") + '">';
 	$("#select_categories").append(categoryIdField);
 	postCategoryCounter++;
 	}
 	});
 
 	}
 
 	// Add all the categories to the names array
 	itemList.find("li").each(function(){
 	names.push({label:$(this).attr("title"), value:$(this).attr("item")});
 	});
 
 	itemList.find("a.close").click(function(){
 	var parentItem = $(this).parent();
 	var parentItemValue = parentItem.attr("item");
 	var v;
 	var categoryValue;
 	var index = outArray.indexOf(parentItemValue);
 
 	// Remove the selected category from the active list displayed
 	parentItem.slideUp('fast',function(){parentItem.removeClass('active');setOutput();});
 
 	// Remove category from the hidden categories class fields
 	$.each($(".categories"), function(key, value)
 	{
 	// If the category looped over equals the category removed, then remove this categories hidden field
 	categoryValue = $(".categories")[key].value;
 	if (parentItemValue == categoryValue)
 	{
 	// Found hidden field with this categories value and remove
 	$(this).remove();
 
 	// Also remove from the outArray, which allows us to add it back again.
 	if (index > -1) {
 	outArray.splice(index, 1);
 	}
 	}
 	});
 
 	return false;
 	});
 
 	// Just finding the input field within the item list
 	var _InputField = itemList.find("input");
 
 	// Listen to any events on the input field
 	_InputField.verboseautocomplete({
 	minLength: 0,
 	source: names,
 	select: function(event, ui){
 	var selectedItem = itemList.find("li[item="+ui.item.value+"]");
 	selectedItem.slideDown('fast',function(){selectedItem.addClass('active');setOutput();});
 	_InputField.val('');
 
 	return false;
 	},
 	focus: function( event, ui ) {
 	// Only works if the mouse is focusing on it, not the arrow keys
 	$(".item-input").val(ui.item.label);
 	}
 	}).bind("autocompletesearchcomplete", function(event, contents) {
 	if(contents.length == 0){
 	$(this).autocomplete("widget").html('<li><p class="ui-corner-all">No results found.</p></li>');
 	$(this).autocomplete("widget").show();
 	}
 	});
 
 	setOutput();
 	}
})(jQuery);

Where it is all saved in the Posts Controller Code

/* Form is being submitted. Save data */
if ($this->request->is(array('post', 'put')))
{
 
 $this->Post->id = $id;
 $saveStatus = $this->Post->save($this->request->data);
 
 if ($saveStatus )
 {
  // Saving (associating) the categories selected for this post
  $this->loadModel('CategoriesPosts');
  $this->CategoriesPosts->saveCategories($this->request->data["Category"], $this->Post->id);
 
  $this->Session->setFlash(__('Your post has been updated.'));
  return $this->redirect(array('action' => 'index'));
 }
 
 $this->Session->setFlash(__('Unable to update your post.'));
 }

Read more posts in the Blog Post Editor series:

Discussions

New Comment














Latest Discussions

  • Carlos: Thank you!
    May 16, 2014 | Replies (0)
  • Jessica: Great info, thanks!
    May 15, 2014 | Replies (1)
  • Walter: Thanks, you totally saved me a bunch of searching around just now. I was setting up a percona xtradb...
    Feb 25, 2014 | Replies (0)
  • Avi: I've found the reason of the problem in my case. It's a bug as described here :http://bugs.mysql.com/bug.php?id=68892Shortly:...
    Dec 12, 2013 | Replies (0)
  • Avi: I've also met that behavior twice on 5.6.12 slaves. However, i didn't find the root cause of that....
    Dec 12, 2013 | Replies (0)