AJAX modification to the Private Files block

AJAX modification to the Private Files block

by Luis de la Torre -
Number of replies: 4

Hi guys,

Once more I beg for some help pfrom the expert moodlers and programmers around here smile

I'd like to add a button to the private files block so that when you click on it, the block refreshes, but not the rest of the webpage.

I know AJAX is exactly meatn for this, Unfortunately, I know almost nothing about AJAX and I don't have a clue about how could I do it. And I'm sure it must be quite simple to do.

Could someone help me a bit here? Just pointing me in the right direction, so I can start programming it myself, would be great!

Thanks.

Average of ratings: -
In reply to Luis de la Torre

Re: AJAX modification to the Private Files block

by Luis de la Torre -

Hi again,

Well, I have done some research in my free time and I have learnt a bit of javascript, YUI and the way Moodle uses them. I used this knowledge to modify the private_files block and now I feel I'm really close to find the solution for adding a button in that block that lets users to refresh its content. But I could still use some help!

Basically, I first added the button icon to the block (block_private_files.php file):

$refresh_button = '<input type="image" id="refreshEJSAppFBBut" align="left" src="' . $CFG->wwwroot . '/blocks/private_files/pix/refresh.png" name="image" width="25" height="25")";>';

Then I wrote this line to the render_private_files_tree() function in renderer.php:

$this->page->requires->js_init_call('M.block_ejsapp_file_browser.init_reload', array($htmlid));

and finally added this to the module.js file inside the private_files block:

M.block_ejsapp_file_browser.init_reload = function(Y, htmlid){
    var button = Y.one("#refreshEJSAppFBBut");
    button.on("click", function (e) {   
        div = document.getElementById(htmlid);
        div.innerHTML = "Whatever";
    });
};

This way, when a user clicks in the new refresh button that appears in the block, its content will change from the tree view of the files that user has in his private files, to a simple text (Whatever). Now I just need to replace "Whatever" with new a call to the function that generates the tree view of the private files.

And this is where I'm stucked at the moment. How can I do that? I think I would need to call the htmllize_tree() function of the renderer.php file from the javascript code in M.block_ejsapp_file_browser.init_reload (module.js file). Is that right? If so, how can I do that?

Thanks again! smile

In reply to Luis de la Torre

Re: AJAX modification to the Private Files block

by Luis de la Torre -

Ok, I'm really, really close now.

I have modified my module.js file so that M.block_private_files.init_reload now looks like this:

M.block_private_files.init_reload = function(Y, url, htmlid){
    var handleSuccess = function(o) {
        div.innerHTML = o.responseText;
        //div.innerHTML = "<li>JARL!!!</li>";
    };
    var handleFailure = function(o) {
        /*failure handler code*/
    }
    var callback = {
        success:handleSuccess,
        failure:handleFailure
    };
    var button = Y.one("#refreshEJSAppFBBut");
    button.on("click", function (e) {   
        div = Y.YUI2.util.Dom.get(htmlid);
        Y.use('yui2-connection', function(Y) {
            Y.YUI2.util.Connect.asyncRequest('GET', url, callback);
        });       
    });
};

 

And I modified the render_private_files_tree function inside the renderer.php file:

public function render_private_files_tree(private_files_tree $tree) {
        $module = array('name'=>'private_files', 'fullpath'=>'/blocks/private_files/module.js', 'requires'=>array('yui2-treeview'));
        if (empty($tree->dir['subdirs']) && empty($tree->dir['files'])) {
            $html = $this->output->box(get_string('nofilesavailable', 'repository'));
        } else {
            $htmlid = 'private_files_tree_'.uniqid();
            $url = 'http://localhost/blocks/private_files/tree_update.php?htmlid='+$htmlid;
            $this->page->requires->js_init_call('M.block_ejsapp_file_browser.init_tree', array(false, $htmlid));
            $this->page->requires->js_init_call('M.block_private_files.init_reload', array($url, $htmlid));
            $html = '<div id="'.$htmlid.'">';
            $html .= $this->htmllize_tree($tree, $tree->dir);
            $html .= '</div>';
        }

        return $html;
    }

 

This way, whatever I echo now in tree_update.php will be shown inside the private files block.

However, I still do not know how to call from php for a new refreshed file tree structure. I guess I could do it using the htmllize_tree() function inside the renderer.php file but since its an internal function of a class I'm not sure how to proceed.

At this stage, I just need to be able to call this function (htmllize_tree()) from my own php  file (tree_update.php) and then echo the result. If I can do that, the rest of my problem is solved smile

Any help here?

PS. I hope these messages could be of any use to other people who starts working with AJAX and Moodle, just like me.

Average of ratings: Useful (1)
In reply to Luis de la Torre

Re: AJAX modification to the Private Files block

by Luis de la Torre -

And one step further.

I basically filled my tree_update.php file with the next code:

 

require_once('../../config.php');

$htmlid = required_param('htmlid', PARAM_TEXT);

$context = get_context_instance(CONTEXT_USER, $USER->id);
$PAGE->set_context($context);
$content = new stdClass();
$renderer = $PAGE->get_renderer('block_private_files');
$content->text = $renderer->private_files_tree($htmlid);

echo $content->text;

 

While this is already working (i.e. when I click the refresh button I added to the private files block I get a refreshed view of the files tree displayed by that block), the tree doesn't appear perfectly: files inside folders appear in a weird way (see attached figure).

Any thoughts?

Attachment after_refresh.jpg
Average of ratings: Useful (1)