Topic: Error after node is moved

Help Help Help...

I get a error in the situation as described below.

1. I have node with loadable:true. I expand the children of the same ( which has again children( third level ) ). -- OK
2. Then I move one of the child node ( drag and drop ) - OK
3. After move I toggel the parent node( one with loadable:true ). It reloads the children. For that I added following code to to toggel event.

refreshChildren: function()
{
            this.state.loaded=false;
            this.state.open=false;
            this.state.loadable=true;
            this.children=[];
            this.$draw=false;
            this.tree.$getIndex();
            this.getDOM('children').innerHTML='';
            Mif.Tree.Draw.update(this);
            return this;
            } ----- Also OK

all the nodes are back again at there original position

4. Now when I click somewhere on child node icon I get the 'null is null or not an object error' -- NOT OK

After investigating I found

I get this error in getDOM method of Mif.Node because I Guess it tries to lookup the node( one which was moved ) with old UID

But after the reload all the child nodes has new UID.

I am sure I am doing something wrong here.

Last edited by Sanjay (2009-04-28 18:25:33)

Re: Error after node is moved

do you have demo tree? don't understand how you move nodes. Need a better explanation.

Re: Error after node is moved

Hallo Moro attached is  file with my demo code.
( I uploaded it as text file as I couldnt upload as html )

Once again for your understanding.

I move node using drag and drop. and it works fine.( In this demo I don't do any backend operation in onDrop )

Only problem is,  after I reload the node parent( I moved the child of this parent )  I get any error when I click anywhere on the node children.

And the reason I found was that as

all the child nodes get new UID after reload, I get a error when i click somewhere, as it  looks for
a wrapper with UID which doesnt exist.

This is the UID for the node which I moved before reload.

so somehow even after reload the tree is caching the node which I moved before reload

Hope you understand my problem now..

Last edited by Sanjay (2009-04-29 12:10:25)

Re: Error after node is moved

from 1 post:

refreshChildren: function()
{
            this.state.loaded=false;
            this.state.open=false;
            this.state.loadable=true;
            this.children=[];
            this.$draw=false;
            this.tree.$getIndex();
            this.getDOM('children').innerHTML='';
            Mif.Tree.Draw.update(this);
            return this;
            }

from demo code

tree.addEvent('onToggle', function(node, state)
{
    if (!state && (node.type[0] == 'unloaded')) 
    {
        node.state.loaded = false;
        node.state.loadable = true;
        node.children = [];
        node.$draw = false;
        node.tree.$getIndex();
        Mif.Tree.Draw.update(node);
        return node;
    }
});

where is node.getDOM('children').innerHTML='' ?

Re: Error after node is moved

As i was trying different ways to fix this issue I forgot to put it back in the code I send it to you.

So even if i put

node.getDOM('children').innerHTML='';

in my code it does not make any difference.

Re: Error after node is moved

I even tried this

if (!state && (node.type[0] == 'unloaded'))
                {
                    $each( node.getChildren(), function(n)
                    {
                        n.getDOM('node').destroy()
                    }

                    );

                    node.state.loaded = false;
                    node.state.loadable = true;
                    node.children = [];
                    node.$draw = false;
                    node.tree.$getIndex();
                    node.getDOM('children').innerHTML='';
                    Mif.Tree.Draw.update(node);
                    return node;
                }

but still the same error

Re: Error after node is moved

try

tree.addEvent('onToggle', function(node, state){
    if (!state && (node.type[0] == 'unloaded')){
        if(node.contains(node.tree.selected)){
            node.tree.unselect();
        };
        node.state.loaded = false;
        node.state.loadable = true;
        node.children = [];
        node.$draw = false;
        node.tree.$getIndex();
        node.getDOM('children').innerHTML='';
        Mif.Tree.Draw.update(node);
        return node;
    }
});

Re: Error after node is moved

Great.. that works..:) thanks moro

Re: Error after node is moved

Hi moro,

I get exactly the same error.  However, I am loading my root and children using the 'file tree' demo method.  In my case I am have initiated sort with my own function and to activate I reload the children.  I also want to do this with drag'n'drop, etc so the tree will always be in a specific order.  Could you please help with a fix - a subset of my code is below:

Mif.Tree.Node.implement({
    refreshChildren: function() {
        this.state.loaded=false;
        this.state.open=false;
        this.state.loadable=true;
        this.children=[];
        this.$draw=false;
        this.tree.$getIndex();
        this.getDOM('children').innerHTML='';
        Mif.Tree.Draw.update(this);
        return this;
    }       
});
    
tree = new Mif.Tree({
    container: $('mytree'),
    initialize: function(){
        this.initSortable(mySort);
        new Mif.Tree.KeyNav(this);
        this.initRows();
        new Mif.Tree.Drag(this, {
            onDrag: function(){
                //inject inside file not allowed;
                if(this.target && this.target.type=='file' && this.where=='inside'){
                    this.where='notAllowed';
                }
            },
            onComplete: function(){
                if(!this.target) return;
                if(this.emptydrop()) return;
                var from = this.current.data.abs_path;
                var to = this.target.data.abs_path;
                var action=this.tree.key[this.options.modifier] ? 'copy' : 'move';
                if(action == 'move') {
                    this.current.data.abs_path = to+'/'+this.current.name;
                    myRequest.send("f=mgMoveFile&b="+from+"&c="+to);
                }
                //this.target.refreshChildren().toggle(true);
            }
        });
    },
    types: {
        folder:{
            openIcon: 'mif-tree-open-icon',
            closeIcon: 'mif-tree-close-icon',
            loadable: true
        },
        file:{
            openIcon: 'mif-tree-file-open-icon',
            closeIcon: 'mif-tree-file-close-icon'
        },
        loader:{
            openIcon: 'mif-tree-loader-open-icon',
            closeIcon: 'mif-tree-loader-close-icon',
            dropDenied: ['inside','after']
        }
    },
    dfltType:'folder',
    height: 18,
    onRename: function(node, newName, oldName){
        myRequest.send("f=mgRenameFile&b="+node.data.abs_path+"&c="+newName+"&d="+rootDir);
        node.data.abs_path = node.data.abs_path.replace(oldName,newName);
        var parent = node.getParent();
    parent.refreshChildren().toggle(true);
    }
});

tree.load({
    url: rootDir+'plugins/myupload/getRoot.php',
    data: {myRoot: myRoot}
});

tree.loadOptions=function(node){
    return {
        url: rootDir+'plugins/myupload/get_children.php?a=' + $time()+$random(1, 10000),
        data: {abs_path: node.data.abs_path}
    };
};

tree.addEvent('load', function(){
    tree.root.toggle();
});

tree.wrapper.addEvent('keydown', function(event){
    if(event.key!='delete') return;
    if(confirm('Are you sure you want to remove this item?')){
        $(previewMenuDiv).set({html: ""});
        $(previewImage).set({html: ""});
        myRequest.send("f=mgDelete&b="+tree.selected.data.abs_path);
        var forward=tree.selected.getNextVisible();
        if (tree.selected) tree.selected.remove();
        if( forward ) tree.select(forward)
    }
});

function mySort(node1, node2) {
    if((node1.name>node2.name && node1.type == 'folder' && node2.type == 'folder')){
        return 1;
    }else if((node1.name<node2.name && node1.type == 'folder' && node2.type == 'folder')){
        return -1;
    }else{
        return 0;
    }
}

Many thanks

Peter

Re: Error after node is moved

why

Mif.Tree.Node.implement({
    refreshChildren: function() {
        this.state.loaded=false;
        this.state.open=false;
        this.state.loadable=true;
        this.children=[];
        this.$draw=false;
        this.tree.$getIndex();
        this.getDOM('children').innerHTML='';
        Mif.Tree.Draw.update(this);
        return this;
    }       
});

?
and not

Mif.Tree.Node.implement({
    refreshChildren: function() {
        if(this.contains(this.tree.selected)){
            this.tree.unselect();
        };
        this.state.loaded=false;
        this.state.open=false;
        this.state.loadable=true;
        this.children=[];
        this.$draw=false;
        this.tree.$getIndex();
        this.getDOM('children').innerHTML='';
        Mif.Tree.Draw.update(this);
        return this;
    }       
});

Re: Error after node is moved

Moro,

I'm not sure why to be honest but it didn't work.  The result was that the children display was refreshed but not updated, if you see what I mean, but the error on the next select was the same.  If I added this.tree.select(); just before the return then the children display was updated properly but still had the error - it really is down to my misunderstanding of how this is supposed to work.

Peter

Re: Error after node is moved

Moro,

I think I have sorted this now.  I have kept your suggested code above, but would really appreciate an explanation of what it does

Mif.Tree.Node.implement({
    refreshChildren: function() {
            if(this.contains(this.tree.selected)){
                    this.tree.unselect();
            };
            this.state.loaded=false;
            this.state.open=false;
            this.state.loadable=true;
            this.children=[];
            this.$draw=false;
            this.tree.$getIndex();
            this.getDOM('children').innerHTML='';
            Mif.Tree.Draw.update(this);
            return this;
    }       
});

And I replaced the onRename function with a tidier ajx command.  I realised that the refresh was taking place before the ajax call had returned, or something like that.  So it goes from:

    onRename: function(node, newName, oldName){
        myRequest.send("f=mgRenameFile&b="+node.data.abs_path+"&c="+newName+"&d="+rootDir);
        node.data.abs_path = node.data.abs_path.replace(oldName,newName);
        var parent = node.getParent();
    parent.refreshChildren().toggle(true);
    }

to:

    onRename: function(node, newName, oldName){
        var req = new Request({
            method: "get",
            url: rootDir+"plugins/myupload/myupload_ajax.php",
            data: { "f" : "mgRenameFile",
                            "b" : node.data.abs_path,
                            "c" : newName,
                            "d" : rootDir
                        },
            onComplete: function(response) {
                node.data.abs_path = node.data.abs_path.replace(oldName,newName);
                var parent = node.getParent();
            parent.refreshChildren().toggle(true);
            }
        }).send();
    }

Many thanks for your help

Re: Error after node is moved

Mif.Tree.Node.implement({
    refreshChildren: function() {
        if(this.contains(this.tree.selected)){
            this.tree.unselect();
        }
        this.tree.mouse.node=null;
        this.tree.updateHover();
        this.state.loaded=false;
        this.state.open=false;
        this.state.loadable=true;
        this.children=[];
        this.$draw=false;
        this.tree.$getIndex();
        this.getDOM('children').innerHTML='';
        Mif.Tree.Draw.update(this);
        return this;
    }       
});

We unselect removed(refreshed) node. In some situations you can also have error because hovered node not exists, so i'm add yet 2 lines after unselect.

Re: Error after node is moved

Moro,

Many thanks for explaining - it is working really well now.

peter

Re: Error after node is moved

if(this.contains(this.tree.selected)&&this!=this.tree.selected){
       this.tree.unselect();
}