Welcome Guest, Not a member yet? Register   Sign In
Using CI and jsTree to build a tree control
#1

[eluser]Nicholai[/eluser]
In this thread I wanted to create a nested list with checkboxes for saving compatibility information to a database. There wasn't much complete stuff out there, so hopefully this helps someone. First, you need this XML helper and jsTree.

I gave up on the nested list approach after jsTree didn't play nicely with it, though it can easily convert an XML file to a tree. While the naming conventions for jsTree are pretty strict and the documentation a little lacking, it gives a very nice result. Here's the controller:

Code:
function index()
{

$productquery = $this->Compat_model->get_products(NULL);

//create an xml doc and give it a root
$dom = xml_dom();
$root = xml_add_child($dom, 'root');

foreach($productquery as $productrow)
    {
        //jsTree requires data in the form <item><content><name><!CDATA[value]></name></content></item>
        //use parent_id to determine depth of the node, with the base node having a parent of 0
        $product = xml_add_child($root, 'item');
        xml_add_attribute($product, 'parent_id', '0');

        $productcontent = xml_add_child($product, 'content');
        $productname = xml_add_child($productcontent, 'name', $productrow->Description, TRUE);
        xml_add_attribute($productname, 'ID', $productrow->ID);
        xml_add_attribute($productname, 'entry_type', 'product');

        $product_filter = $productrow->ID;            
        $versionquery = $this->Compat_model->get_version($product_filter);

        if(!$versionquery=='')
        {
            foreach($versionquery as $versionrow)
            {
                $version = xml_add_child($product, 'item');
                xml_add_attribute($version, 'parent_id', $product_filter);
                
                $versioncontent = xml_add_child($version, 'content');
                $versionname = xml_add_child($versioncontent, 'name', $versionrow->Description, TRUE);
                xml_add_attribute($versionname, 'ID', $versionrow->ID);
                xml_add_attribute($versionname, 'entry_type', 'version');
    
                $version_filter = $versionrow->ID;
                $patchquery = $this->Compat_model->get_patch($version_filter);

                if (!$patchquery=='')
                {
                    foreach($patchquery as $patchrow)
                    {
                        $patch = xml_add_child($version, 'item');
                        xml_add_attribute($patch, 'parent_id', $version_filter);
                        
                        $patchcontent = xml_add_child($patch, 'content');
                        $patchname = xml_add_child($patchcontent,'name', $patchrow->Description, TRUE);
                         xml_add_attribute($patchname, 'ID', $patchrow->ID);
                         xml_add_attribute($patchname, 'entry_type', 'patch');
                    }
                }
            }
        }
    }
$data['title'] = "Set Compatibility Rules";
$dom->save('rules.xml');
$this->load->view('rules_view.php', $data);
}
#2

[eluser]Nicholai[/eluser]
And here's the JavaScript code for the tree, using the checkbox theme. In the view, I include all the necessary files and this function loads the tree into a DIV with id "tree". Checked items are written to a hidden input called "compat_list" that can be submitted with the form.

I hope this helps someone. If you have a more elegant way of achieving this with less code, I'd be very interested to see how an experienced programmer would approach it.

Code:
function load_admin_tree()
{
$(function () {
    $("#tree").tree({

        data : {
            type  : "xml_nested",
            url  : "&lt;?php echo base_url(); ?&gt;rules.xml"    //this is where we saved the file in the controller
            },

        ui : {
            theme_name : "checkbox"
            },

        rules : {
            clickable : "all",
            multiple : "on"
            },
            
        callback : {
            onchange : function (NODE, TREE_OBJ) {
              var $this = $(NODE).is("li") ? $(NODE) : $(NODE).parent();
              if($this.children("a.unchecked").size() == 0) {
                TREE_OBJ.container.find("a").addClass("unchecked");
              }
              $this.children("a").removeClass("clicked");
              if($this.children("a").hasClass("checked")) {
                $this.find("li").andSelf().children("a").removeClass("checked").removeClass("undetermined").addClass("unchecked");
                var state = 0;
              }
              else {
                $this.find("li").andSelf().children("a").removeClass("unchecked").removeClass("undetermined").addClass("checked");
                var state = 1;
              }
              $this.parents("li").each(function () {
                if(state == 1) {
                  if($(this).find("a.unchecked, a.undetermined").size() - 1 > 0) {
                    $(this).parents("li").andSelf().children("a").removeClass("unchecked").removeClass("checked").addClass("undetermined");
                    return false;
                  }
                  else $(this).children("a").removeClass("unchecked").removeClass("undetermined").addClass("checked");
                }
                else {
                  if($(this).find("a.checked, a.undetermined").size() - 1 > 0) {
                    $(this).parents("li").andSelf().children("a").removeClass("unchecked").removeClass("checked").addClass("undetermined");
                    return false;
                  }
                  else $(this).children("a").removeClass("checked").removeClass("undetermined").addClass("unchecked");
                }
              });

                var ids = [];
                $("a.checked").each(function () {
                if($(this).attr("entry_type") == "patch")    //only keep the IDs for patches
                ids.push(this.id); });
                ids.join(",");  //turn the array into a comma-separated list
                $("#compat_list").val(ids);    //write the list to a hidden form field
                }
            }
        });
    });
}
#3

[eluser]JuanG[/eluser]
Hi Nicholai, I was wondering if you could take a look to my post asking how to integrate CI and jsTree. Maybe what you've already done could help me accomplish this integration.

Thanks in advanced for your time and help.

Cheers,
#4

[eluser]Unknown[/eluser]
someone can send the files of the view? please!!!!!!




Theme © iAndrew 2016 - Forum software by © MyBB