I’m new of YII and it’s my first project with a PHP framework, means that if I can do the things better you can write me suggestions and I’ll be so happy
Let’s start…
On my site I want to use in different controllers a CTreeViev that displays different nested elements, and I want to add, delete and rename them, I want also write less code possible and that’s my idea:
for now I want only root>Corporation>Division>Person and I want to add and rename only Corporation and Division, naturally I can nest mor things
View(index.php):
prova.js is the JQuery script and navTree.css is one easy css for creating two div in the same line, now isn’t important
<?php
$cs=Yii::app()->clientScript;
$cs->registerCoreScript('jquery');
$cs->registerScriptFile(Yii::app()->baseUrl.'/js/prova.js');
$cs->registerCssFile(Yii::app()->baseUrl.'/css/navTree.css');
?>
<div id="left">
<?php
$this->widget('CTreeView',array(
'id'=>'tree',
'data'=>$dataTree,
'animated'=>'fast',
'collapsed'=>'false',
'htmlOptions'=>array(
'class'=>'filetree',//there are some classes that ready to use
),
));
?>
</div>
<script>
//here I write classes array sended by actionIndex
<?php echo $classes; ?>
setParams("prova",classes);
</script>
Controller (ProvaController.php):
see the attribute $classes with the list of classes that I’ll nest in order and how I want to manage the operations of add, rename, delete using the id sended by the elements (classname_id -> corporation_10)
there is also the creation the initial tree, the #adders can be avery kind of element, the important that the class is "adder" and the id is right.
<?php
class ProvaController extends Controller
{
protected $classes = array('tree','corporation','division','person'); //list of classes in order, the first is the name of the tree
public function actionIndex() {
//$datatree is the array of the tree, $classes contains the string for the istance of the array in javascript
$this->render('index', array('dataTree'=>$this->createTree($this->classes),'classes'=>'var classes = new Array("'. join($this->classes,'","'). '");'));
}
public function actionAddTreeNode() {
$id=explode("_",$_GET['id']);
$key = array_search($id[0],$this->classes)+1; //the addercontains the name of upper class, means that i must watch next object on classes
switch($this->classes[$key])
{
case 'corporation';
$corp=new Corporation;
$corp->name ='new corporation';
$corp->concurrency=true;
$corp->save();
break;
case 'division';
$div=new Division;
$div->name ='new division';
$div->corporation_id=$id[1];
$div->save();
break;
default:
return false;
break;
}
echo Yii::app()->db->lastInsertID; //id to nsert on jtree
}
public function actionRenameTreeNode() {
$id=explode("_",$_GET['id']);
switch($id[0])
{
case 'corporation';
$model=Corporation::model()->findByPk($id[1]);
break;
case 'division';
$model=Division::model()->findByPk($id[1]);
break;
default:
return false;
break;
}
$model->name =$_GET['name'];
$model->save();
}
public function actionRemoveTreeNode() {
$id=explode("_",$_GET['id']);
switch($id[0])
{
case 'corporation';
Division::model()->deleteAll('corporation_id='.$id[1]);
Corporation::model()->deleteByPk($id[1]);
break;
case 'division';
Division::model()->deleteByPk($id[1]);
break;
default:
return false;
break;
}
}
//creation of the tree with arrays, see .adder
private function createTree()
{
$tree=array();
$addCorporation=array('text'=>'<a class="adder" id="tree">Add</a>'); //adder can be everything, important: class and id
array_push($tree,$addCorporation);
$corporations = Corporation::model()->findAll();
foreach($corporations as $corp)
{
$corporationNode=array('text'=>'<span class="node" id="corporation_'.$corp->id.'">'.$corp->name.'</span>'); //class=node, id=class_id
$addDivision=array('text'=>'<a class="adder" id="corporation_'.$corp->id.'">Add</a>');
$divisions = Division::model()->findAll('corporation_id='.$corp->id);
$corporationNode['children']=array();
array_push($corporationNode['children'],$addDivision);
foreach($divisions as $div)
array_push($corporationNode['children'],array('text'=>'<span class="node" id="division_'.$div->id.'">'.$div->name.'</span>'));
array_push($tree,$corporationNode);
}
return $tree;
}
}
?>
The Jquery script(prova.js):
the important classes are: adder, renamer, deleter, node. The first tree are selfexplained the node is an element that can be changed or deleted.
var controller; //controller name for calling
//actions name for calling
var actionAdd='addTreeNode';
var actionDelete='removeTreeNode';
var actionRename='renameTreeNode';
//the class names passed from the view
var nodes;
function setParams(cont,ns){ //give parameters
controller=cont;
nodes=ns;
}
function getRow(cl, id){ //obtain rows with id class_id
return $("#"+cl+"_"+id);
}
function addNode(id, newId){ //add new rows
var el="";
var str="";
id=id.split('_');
if(id[0]==nodes[0])
el=$("#"+nodes[0]); //root id=treeName
else
el=getRow(id[0],id[1]).parent().children("ul"); //other case example id="classNotRoot_#"
str='<li><span class="node "id="'+nodes[nodes.indexOf(id[0])+1]+'_'+ newId +'">new '+ nodes[nodes.indexOf(id[0])+1] +'</span>';
if(id[0]!=nodes[nodes.length-3]) //isn't one leaf <------------------you decide here where do you watnt stop
str= str + '<ul><li><a class="adder" id="'+nodes[nodes.indexOf(id[0])+1]+'_'+ newId +'">Add</a></li></ul>';
str= str + '</li>';
branches = $(str).appendTo(el); //create new element
$("#"+nodes[0]).treeview({add: branches}); //added to tree
return true;
}
function pushRenameDelete(id) //write on the node add and remove the rename/delete options
{
el = id.split("_");
el = getRow(el[0],el[1]);
if(!el.children("a").text())
el.html(el.html()+' <a href="javascript:inputRename(\''+id+'\')">rename</a> <a class="deleter" id="'+ id +'" href="#">delete</a>');
else if(el.children("a").text()!="change")
el.children("a").remove();
}
function inputRename(id) //write the textfield on the node (called by rename, see function pushRenameDelete)
{
el = id.split("_");
el = getRow(el[0],el[1]);
el.children("a").remove(); //remove rename delete
el.html('<input type="text" value="'+el.text()+'"><a class="renamer" id="'+ id +'"href="#">change</a>');
}
function setName(id,name)
{
el=id.split("_");
getRow(el[0],el[1]).html(name);
}
function delNode(id)
{
id=id.split("_");
branches = getRow(id[0],id[1]).parent();
$("#"+nodes[0]).treeview({remove: branches});
}
//here I watch events and I do the actions that interact with controller
$(document).ready(function() {
$('.adder').live('click',function(e){
var id=$(this).closest('.adder').attr('id');
$.get("index.php?r="+controller+"/"+actionAdd,{'id':id},function(newId){
addNode(id,newId);
});
});
$('.renamer').live('click',function(e){
var id=$(this).closest('.renamer').attr('id');
var name=$("#"+id).children("input").val()
$.get("index.php?r="+controller+"/"+actionRename,{'id':id, 'name':name},function(){
setName(id,name);
});
});
$('.deleter').live('click',function(e){
var id=$(this).closest('.deleter').attr('id');
$.get("index.php?r="+controller+"/"+actionDelete,{'id':id},function(){
delNode(id);
});
});
$('.node').live('click',function(e){
pushRenameDelete($(this).closest('.node').attr('id'));
//here i can add the code for call the pages in another div near this tree
});
});
That’s all, I hope that the comments are OK and that’s useful to someone