Top

Follow me and receive all the latest free scripts:

By Email:

Categories
Most Popular Posts

jQuery infinite category tree management system

jQuery infinite category tree management system

Published September 27, 2014 by , category jQuery

jquerycategory treelink directory

Create and manage categories via your back-office

Introduction

Imagine you want to create a link directory. You will need to classify all your websites link in categories, sub-categories, sub-sub-categories and so on...

In this tutorial I will only explain the infinite category system part. In the next tutorial I'll show you how to add websites link inside all these categories.

Technical side

This is a very simple jQuery / Ajax program which allows you to create, first, categories at the root. Then, for each categories created, you can enter inside and create sub-categories. You can repeat this operation as much as you want, until your categories tree is finished. You can, of course, at any moment, edit or delete a category.

Files architecture

Please also add Twitter Bootstrap and the icon design/loader-small.gif. Name it as you want but replace the new name into tuto-links.js. You can find nice loading icon in this website.

Notice that you don't have to use Twitter Bootstrap! If you don't use it, simply replace Bootstrap CSS code by your own.

index.php
db.class.php

ajax

tuto-links-addCat.php
tuto-links-deleteCat.php
tuto-links-displayCats.php
tuto-links-editCat.php

js

tuto-links.js

jquery

jquery-1.10.1.min.js

Live demo

For this live demo, I have created a 3 level geographic / country / travel directory. Please be my guest, play with it and add, edit or deleted categories.

For safety reasons and to prevent misuse, datas are not inserted in the database

Database

Here is the database structure:

CREATE TABLE IF NOT EXISTS `tc_tuto_links_cat` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `inside` int(20) NOT NULL DEFAULT '0',
  `name` varchar(100) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

As you can see the table has 3 colums:

When a category is at the root, it's inside field value is 0

Example: you create your FIRST category named "Europe". Congratulation, "Europe" has the id 1 (first row in the table), and its field inside has the value 0 (at the root).

Now, your create a category "France" INSIDE "Europe". This category "France" has the id 2 (second row in the table), and its field inside has the value 1 ("France" is inside "Europe" which has the id 1)

The index.php page

Name it as you want, this code may be placed on any page of your website (a back-office page)

<?PHP
//index.php
include('db.class.php');
$bdd = new db();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
	<title>Links</title>
	<meta name="description" content="" />
	<meta name="keywords" content="" />
	
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">

	<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" type="text/css">
	
	<script type="text/javascript" src="jquery/jquery-1.10.1.min.js"></script>
    
</head>

<body>

<div class="container">
	<div class="row">
		<div class="col-md-3">
		</div>
		<div class="col-md-9">
		<div id="messagesAlert"></div>
		<?php
		echo '<ul>';
		$mainCat = $bdd->getAll('SELECT id, inside, name FROM tc_tuto_links_cat WHERE inside=0 ORDER BY name ASC');
		if (is_array($mainCat) && count($mainCat) != 0) {
			
			foreach($mainCat as $mainCat) {
				echo '<li id="delete'.$mainCat['id'].'"><span id="name'.$mainCat['id'].'">'.$mainCat['name'].'</span>';
				echo ' <small>';
				?>
				(<a href="#" onclick="editCat(<?php echo $mainCat['id']; ?>, '<?php echo $mainCat['name']; ?>'); return false;" class="glyphicon glyphicon-edit" title="Edit"></a>, <a href="#" onclick="deleteCat(<?php echo $mainCat['id']; ?>); return false;" class="glyphicon glyphicon-trash" title="Delete"></a>)
				<?php
				echo ' (<a href="#" onclick="displaySubCat('.$mainCat['id'].', '.$mainCat['inside'].'); return false;" id="showHide'.$mainCat['id'].'" class="statueShow'.$mainCat['id'].'">+ show categories</a>)';
				echo '</small>';
				echo '<div id="returnCats'.$mainCat['id'].'"></div>';
				echo '</li>';
			}
		}
		echo '<div id="newCat0"></div>';
		echo '<li id="idAddCat0"><a href="#" onclick="addCat(0); return false;" style="color: green">+ Add category</a></li>';
		echo '</ul>';
		?>
		<script type="text/javascript" src="js/tuto-links.js"></script>
		
		
		</div>
	
		</div>
	</div>
</div>
	
</body>
</html>

Database connection

Page db.class.php. More information about the database connection I use here

The jQuery code

//tuto-links.js
function addCat(inside) {
	var originalContent = $('li#idAddCat' + inside).html();
	$('#idAddCat' + inside).append('<li><input type="text" id="field' + inside + '" value="" /></li>');
	$('#field' + inside).focus();
	$('#field' + inside).keypress(function (e) {
		if (e.which == 13) {
			newContent = $('#field' + inside).val();
			$('li#idAddCat' + inside).html('<img src="design/loader-small.gif" />');
			var data = {'inside': inside, 'name': newContent};
			
			$.ajax({
				type: 'POST',
				url: 'ajax/tuto-links-addCat.php',
				data: data,
				timeout: 3000,
				success: function(data) {
					$(data).insertBefore($('#idAddCat' + inside)); },
				error: function() {
					$('#newCat' + inside).text('Problem'); }
			});
			
			$('li#idAddCat' + inside).html(originalContent);
		}
	});
	$('#field' + inside).blur(function() {
		$('li#idAddCat' + inside).html(originalContent);
	});
}

function displaySubCat(id, inside) {
	$('#returnCats' + id).html('<img src="design/loader-small.gif" /> Processing...');
	var data = {'id': id, 'inside': inside};
	$.ajax({
		type: "POST",
		url: "ajax/tuto-links-displayCats.php",
		data: data,
		timeout: 3000,
		success: function(dataBack){
			$('#returnCats' + id).html(dataBack);
			},
		error: function() {
			$('#returnCats' + id).text('Problem!');
		}
	});
	
	var statue = $('#showHide' + id).attr('class');
	if (statue == "statueHide" + id) {
		$('#showHide' + id).text('+ show categories').attr('class', 'statueShow' + id);
		$('#returnCats' + id).hide();
	}
	if (statue == "statueShow" + id) {
		$('#showHide' + id).text('- hide categories').attr('class', 'statueHide' + id);
		$('#returnCats' + id).show();
	}
	return false;
}

function deleteCat(id) {
	if (confirm("Are you sure?")) {
		var data = {'id': id};
		$.ajax({
			type: 'POST',
			url: 'ajax/tuto-links-deleteCat.php',
			data: data,
			timeout: 3000,
			success: function(dataBack) {
				if (dataBack == 'catNotDeleted') {
					$('#messagesAlert').html('<div class="alert alert-danger" id="alertFadeOut">This category is not empty and so can\'t be deleted!</div>');
					$('#alertFadeOut').fadeOut(2000, function () {
						$('#alertFadeOut').text('');
					});
				}
				if (dataBack == 'catDeleted') {
					$('#delete' + id).html('<font color="green">Category deleted successfully</font>');
					$('#delete' + id).fadeOut('slow', function() {
						$('#delete' + id).replaceWith('');
						$(this).clear();
					});
				}
				},
			error: function() {
				$('#messagesAlert').text('Problem'); }
		});
		
	}
}

function editCat(id, name) {
	var originalContent = name;
	$('#name' + id).html('<input type="text" id="field' + id + '" value="' + originalContent + '" />');
	$('#field' + id).focus();
	$('#field' + id).keypress(function (e) {
		if (e.which == 13) {
			newContent = $('#field' + id).val();
			$('#name' + id).html('<img src="design/loader-small.gif" />');
			var data = {'id': id, 'name': newContent};
			
			$.ajax({
				type: 'POST',
				url: 'ajax/tuto-links-editCat.php',
				data: data,
				timeout: 3000,
				success: function(dataBack) {
					$('#messagesAlert').html(dataBack);
					$('#alertFadeOut').fadeOut(2000, function () {
						$('#alertFadeOut').text('');
					});
				},
				error: function() {
					$('#messagesAlert').text('Problem'); }
			});
			
			$('#name' + id).html(newContent);
		}
	});
	$('#field' + id).blur(function() {
		$('#name' + id).html(originalContent);
	});
}

The PHP code

tuto-links-addCat.php

AJAX PHP file called by JS addCat() function

<?php
include('../db.class.php');
$bdd = new db();

if($_POST) {
	$inside = $_POST['inside'];
	$name = $_POST['name'];
	
	if (!empty($name)) {
		$addCat = $bdd->execute('INSERT INTO tc_tuto_links_cat (inside, name) VALUES ('.$inside.', "'.$name.'")');
		$newCatId=mysql_insert_id();
		echo '<li id="delete'.$newCatId.'">';
		echo '<span id="name'.$newCatId.'">'.$name.'</span>';
		echo ' <small>';
		?>
		(<a href="#" onclick="editCat(<?php echo $newCatId; ?>, '<?php echo $name; ?>'); return false;" class="glyphicon glyphicon-edit" title="Edit"></a>, <a href="#" onclick="deleteCat(<?php echo $newCatId; ?>); return false;" class="glyphicon glyphicon-trash" title="Delete"></a>)
		<?php
		echo ' (<a href="#" onclick="displaySubCat('.$newCatId.', '.$inside.'); return false;" id="showHide'.$newCatId.'" class="statueShow'.$newCatId.'">+ show categories</a>)';
		echo '</small>';
		echo '<div id="returnCats'.$newCatId.'"></div>';
		echo '</li>';
	} else {
		echo '<li>';
		echo '<font color="red">Empty field! Category not added.</font>';
		echo '</li>';
	}
}
?>

tuto-links-deleteCat.php

AJAX PHP file called by JS deleteCat() function

<?php
include('../db.class.php');
$bdd = new db();

if($_POST) {
	$id = $_POST['id'];
	
	$testEmptyCat = $bdd->getOne('SELECT id FROM tc_tuto_links_cat WHERE inside='.$id.'');
	if (is_array($testEmptyCat) && !empty($testEmptyCat)) {
		echo 'catNotDeleted';
	} else {
		$deleteCat = $bdd->execute('DELETE FROM tc_tuto_links_cat WHERE id='.$id.'');
		echo 'catDeleted';
	}
}
?>

tuto-links-displayCats.php

AJAX PHP file called by JS displaySubCat() function

<?php
include('../db.class.php');
$bdd = new db();

if($_POST) {
	$id = $_POST['id'];
	$inside = $_POST['inside'];
	
	echo '<ul>';
	$cats = $bdd->getAll('SELECT id, inside, name FROM tc_tuto_links_cat WHERE inside='.$id.' ORDER BY name ASC');
	if (is_array($cats) && count($cats) != 0) {
		foreach($cats as $cat) {
			echo '<li id="delete'.$cat['id'].'"><span id="name'.$cat['id'].'">'.$cat['name'].'</span>';
			echo ' <small>';
			?>
			(<a href="#" onclick="editCat(<?php echo $cat['id']; ?>, '<?php echo $cat['name']; ?>'); return false;" class="glyphicon glyphicon-edit" title="Edit"></a>, <a href="#" onclick="deleteCat(<?php echo $cat['id']; ?>); return false;" class="glyphicon glyphicon-trash" title="Delete"></a>)
			<?php
			echo ' (<a href="#" onclick="displaySubCat('.$cat['id'].', '.$cat['inside'].'); return false;" id="showHide'.$cat['id'].'" class="statueShow'.$cat['id'].'">+ show categories</a>)';
			echo '</small>';
			echo '<div id="returnCats'.$cat['id'].'"></div>';
			echo '</li>';
		}
	}
	echo '<div id="newCat'.$id.'"></div>';
	echo '<li id="idAddCat'.$id.'"><a href="#" onclick="addCat('.$id.'); return false;" style="color: green">+ Add category</a></li>';
	echo '</ul>';
}
?>

tuto-links-editCat.php

AJAX PHP file called by JS editCat() function

<?php
include('../db.class.php');
$bdd = new db();

if($_POST) {
	$id = $_POST['id'];
	$name = $_POST['name'];
	
	$addCat = $bdd->execute('UPDATE tc_tuto_links_cat SET name="'.$name.'" WHERE id='.$id.'');
	
}
echo '<div class="alert alert-success" id="alertFadeOut">Category edited successfully</div>';
?>

Conclusion

I'll soon add more tutorials about:

About Simon Laroche
Simon Laroche on Google+
Simon Laroche on Twitter
Simon Laroche on Facebook
Simon Laroche on Pinterest
Simon Laroche on LinkedIn
: I am a Coder, Designer, Webmaster and Expert SEO Consulting, I'm also a wise traveller and an avid amateur photographer. I created the website TipoCode and many others such as Landolia: a World of Photos...

If you need help about this script, please leave a comment below. I reply as much as I can depending of my time, you may also get help from others.
I also offer a paid support, if you are in the need to adapt or create a script...

Leave a comment

Comments (7 comments)

Simon Laroche
Simon Laroche Posted on December 03, 2016
@shiva: looks fine to me...
SHiva Posted on December 03, 2016
HI When Iam adding subcategory for second it is not working, Please check once this link
http://mg.couponsnebula.net/cat-list/#
Simon Laroche
Simon Laroche Posted on December 03, 2016
@shiva: all files are here on the page. Just copy/paste into your code.
shiva Posted on December 03, 2016
Hi How can I download this script?
Thanks
Shiva
Anthony Posted on November 01, 2016
Is there a way to get the script to stop giving the option of adding a subcategory after the 3rd level?

Eg. Let's say you only want to allow categories to go as deep as Africa > Algeria > Arts & Culture..
Simon Laroche
Simon Laroche Posted on October 31, 2014
@ Murulimadhav
Do you have an error, PHP error or JavaScript error so I can target where is the problem...
Murulimadhav Posted on October 31, 2014
Respected Sir,
I am trying your script, i am able to add and delete the main category names only. when i try to add sub categories its showing error. Am i missing anything ? I wish you wil guide me
yours faithfully
Murulimadhav