I am coding my first experimental administrator/module so that I can understand how Joomla performs ajax calls. I only need to refresh the content of my module with some server info and a couple of Google Charts calls. I want to use Joomla techniques so that I can confidently build more modules in the future using best practices.
I have cut out 90% of the functionality from my project to isolate where I am stuck.
mod_filefinder.php
defined('_JEXEC') or die;
require_once dirname(__FILE__) . '/helper.php';
if(!defined('DS')) define('DS', DIRECTORY_SEPARATOR);
$filefinder = new FileFinder(JFactory::getApplication()->input->post->getString('path'));
require JModuleHelper::getLayoutPath('mod_filefinder');
helper.php
class FileFinder
{
public $currentdirectory = "";
public $subdirectories = array();
public $js = "";
public $html = "";
function __construct($path = null)
{
if (!$path) {
chdir('../');
$this->currentdirectory = basename(JPATH_BASE);
$this->subdirectories = glob($this->currentdirectory.DS."*", GLOB_ONLYDIR);
$this->html = "container";
$this->js = "
jQuery(function($) {
$('#path').on('change', function() {
var path = $(this).val();
console.log({path: path});
$.ajax({
url: 'index.php?option=com_ajax&module=filefinder&method=FileFinder&format=raw', // &ignoreMessages
type: 'POST',
async: true,
cache: false,
data: {path: path},
success: function(response){
console.log(response);
}
});
});
$('#path').trigger('change');
});
";
} else {
$this->currentdirectory = $path;
$this->subdirectories = glob($this->currentdirectory.DS."*", GLOB_ONLYDIR);
}
}
public function FileFinderAjax() {
?><script>console.log('hello');</script><?php
echo "hello"; // how do I get Ajax to get in here?!?
}
}
default.php
defined('_JEXEC') or die;
if ($filefinder->html == "container") { // provide container with default contents
echo "<div id=\"filefinder_container\">";
echo "<span>", JTEXT::_("Current Directory"), " ", $filefinder->currentdirectory, "</span>";
echo "<select id=\"path\"><option value=\"\">Select a Subdirectory</option>";
foreach ($filefinder->subdirectories as $subdirectory) {
echo "<option>$subdirectory</option>"; // value=\"$filefinder->currentdirectory".DS."$subdirectory\"
}
echo "</select>";
echo "</div>";
} else { // return only the new contents to be inserted into old container
echo "<span>", JTEXT::_("Current Directory"), " ", $filefinder->currentdirectory, "</span>";
echo "<select id=\"path\"><option value=\"\">Select a Subdirectory</option>";
foreach ($filefinder->subdirectories as $subdirectory) {
echo "<option>$subdirectory</option>"; // value=\"$filefinder->currentdirectory".DS."$subdirectory\"
}
echo "</select>";
}
if ($filefinder->js) {
JHtml::_('jquery.framework');
$document = JFactory::getDocument();
$document->addScriptDeclaration($filefinder->js);
}
I do have the index.html
and mod_filefinder.xml
files in place, I am just not adding them to my post because it is unnecessary bloat.
Right now, my console.log is displaying these things after I select a new directory:
{path: "administrator\cache"} POST http://localhost/jdem01/administrator/index.php?option=com_ajax&module=filefinder&method=FileFinder&format=raw 404 (Not Found)
I have also tried:
- making
FileFinderAjax()
astatic
public function - and approximately 50 hailmary code adjustments that I cannot recall and don't care to post.
I have fruitlessly read:
https://www.ostraining.com/blog/joomla/search-ajax/
https://docs.joomla.org/Using_Joomla_Ajax_Interface
https://docs.joomla.org/J3.x:Creating_a_simple_module/Developing_a_Basic_Module
Sending POST data within module - AJAX
Using AJAX in a custom module - how to do it?
(... and countless other docs/forums/stackoverflow/stackexchange resources)
(... and all of the "Similar Questions" recommended in the yellow box to the right of my question textarea)
I am using Joomla 3.8.6
Update after preliminary support from @jamesgarrett and @Lodder...
I am just not getting the desired response string.
Here are my files (stripped down even farther):
administrator/modules/mod_filefinder/mod_filefinder.php
defined('_JEXEC') or die;
require_once dirname(__FILE__) . '/helper.php';
$filefinder = new modFileFinderHelper();
require JModuleHelper::getLayoutPath('mod_filefinder');
administrator/modules/mod_filefinder/helper.php
class modFileFinderHelper
{
function __construct() {
$this->currentdirectory = basename(JPATH_BASE);
}
public function FileFinderAjax() {
$data = JFactory::getApplication()->input->post->getArray([]);
$path = $data['data']['path'];
?><script>console.log('<?=$path?>');</script><?php
echo "hello $path";
JExit;
}
}
administrator/modules/mod_filefinder/tmpl/default.php
defined('_JEXEC') or die;
JHtml::_('jquery.framework');
JHtml::_('script', 'administrator/modules/mod_filefinder/ajax.js');
echo "<div id=\"filefinder_container\">{$filefinder->currentdirectory}</div>";
administrator/modules/mod_filefinder/ajax.js
jQuery(function($) {
function loadContent(path) {
console.log({path: path});
var request = {
option : 'com_ajax',
module : 'filefinder', // to target: mod_filefinder
method : 'FileFinder', // to target: function FileFinderAjax in class modFileFinderHelper
format : 'raw',
data : {path: path}
};
console.log(request);
$.ajax({
method: 'POST',
data: request
})
.success(function(response){
console.log('response: '+response);
});
}
console.log('onload, calling ajax with default path value: '+$('#filefinder_container').html());
loadContent($('#filefinder_container').html());
$('#path').on('change', function() {
console.log('change event triggered, calling ajax with path value: '+$(this).val());
loadContent($(this).val());
});
});
This is my console.log data:
So let me try to ask this differently.
What is the simplest file structure that will allow me to:
- Load an empty html structure.
- Send an AJAX call to a single-purpose (build a json string) php file
- Receive the json response and distribute the json data into the html structure
Simple right? Please help.