Using AJAX and format=raw on a Joomla component while also loading CSS & JS

1,117 views
Skip to first unread message

Pieter van Wijngaarden

unread,
Aug 6, 2014, 5:33:34 PM8/6/14
to joomla-de...@googlegroups.com
Hi,

I'm hoping I can get some solid advice here.. I've been searching the Joomla documentation on this topic, but couldn't find it, or I was looking in the wrong places.

I'm building a Joomla component, which does quite a lot of heavy lifting (retrieving JSON from an external API). Therefore, I'd like to load most of the component's views using AJAX, asynchronous from the main site. The component also has some views which I'd like to load in certain module positions (e.g. in a sidebar on the right of the page).

To achieve this, I've created a Custom HTML module that performs an AJAX call, which, most importantly, adds 'format=raw' to the GET parameters of the request. This triggers Joomla to only return the component output HTML, and not the whole page (which is what you would receive without format=raw).

And here is my problem: the component also tries to load a bit of its own CSS and JavaScript. This is done the regular way, via:

$document = JFactory::getDocument();
$document->addScript(..scriptfiles..);
$document->addStylesheet(..stylesheets..);

But because of the 'raw' component output, nothing is done with these additional script declarations! They obviously do not end up in the <head> of the document, because the page has already been rendered.

Is there a way to make Joomla still include the CSS and JavaScript files while also rendering only the raw component HTML? Some expert advice would be most welcome!

I have looked at the following options:

1. Include the scripts and CSS into the template that I'm using, to make sure they are already loaded when I load the rest of the component via AJAX. This can be OK, but it ties the component to the template which is being used.. It sounds to me like my only real option, but I'm still hoping for a more elegant way to handle this :).

2. Instead of 'format=raw', use 'tmpl=bare' and create (again, inside the template, not the component..) a new 'bare' template that loads only the head and the component, like so:

<jdoc:include type="head" />
<jdoc:include type="component" />

This also works, but has an annoying disadvantage that I get all kind of other tags in the middle of my HTML (<base>, <meta>, <title>, <link>), which is not valid HTML anymore..

Any help is greatly appreciated, thanks in advance for your time! I can provide more detailed code examples and a link to the site if someone cares to have a look.

Kind regards,
Pieter

Dimitris

unread,
Aug 6, 2014, 7:30:00 PM8/6/14
to joomla-de...@googlegroups.com
One easy solution is to copy the head.php from libraries/joomla/document/html/renderer in you template directory and in the templates index.php (after the defined('_JEXEC') or die;)  add include_once(dirname(__FILE__) . ‘/head.php’);

inside of the head remove all the meta, etc that you don’t want

Hannes Papenberg

unread,
Aug 7, 2014, 3:28:38 AM8/7/14
to joomla-de...@googlegroups.com
You have an initial view that you load, which loads the rest of the
component via ajax. In that view you have to include the CSS/JS. Another
possibility would be to simply put hardcoded CSS/JS tags into your ajax
output. I wouldn't know another way.

Hannes

Pieter van Wijngaarden

unread,
Aug 7, 2014, 6:57:15 AM8/7/14
to joomla-de...@googlegroups.com
Hi Hannes,

I've tried that too! For all pages where my own component is 'the' component being executed I use this approach (one view that triggers another view via ajax). However in this case, I need the component view in a module position, in a sidebar on the right. So the main part of the site can be rendered by another component, while in the right sidebar I have this custom HTML module that triggers the first ajax request to load a view from my component. Regardless of what I do in my component view then (for example trigger another ajax call), the scripts and styles will still not be loaded.

Hardcoding the tags in the ajax output is a possibility, but then I just realized: on some pages I render 2 views from my component! The one in the sidebar on the right, and a main view. If the sidebar then injects the same scripts as the main view will also do (the main one in the <head>, the sidebar in the place where it's loaded), I'll be loading everything twice perhaps?

I think that in the end including the scripts in the template is the best option.. that way my supporting files are always loaded, no matter what I do & how many ajax calls I trigger :)

If there is a nice way of handling this problem within the Joomla CMS / Framework, please let me know. I'm not that experienced with Joomla, so perhaps I'm missing some big opportunity here and my approach is really stupid, if I only knew what to do in Joomla..

Thanks & kind regards,
Pieter

Pieter van Wijngaarden

unread,
Aug 7, 2014, 7:01:25 AM8/7/14
to joomla-de...@googlegroups.com
Hi Dimitris,

I think I understand what you mean. And then I'd need to remove the <jdoc:include type="head"/> declaration probably?

I'm still stuck with the problem that I have <link> tags in the middle of my HTML.. which works in most browsers, but it's officially not allowed.

Thanks for the advice, let me try this out.

Dimitris

unread,
Aug 7, 2014, 7:19:07 AM8/7/14
to joomla-de...@googlegroups.com
First of all I was referring to the second approach with a template bare.
The template will look like:
<jdoc:include type="head" />
<jdoc:include type="component" />
And then the head.php you have to go through all the $buffer .= Something; And make sure that you end up only with the css and js.
you can try this file I attached
head.php

Dimitris

unread,
Aug 7, 2014, 7:22:20 AM8/7/14
to joomla-de...@googlegroups.com
Sorry I meant that template index.php will look like:

<?php
defined('_JEXEC') or die;
include_once(dirname(__FILE__) . ‘/head.php’);
?>

Hannes Papenberg

unread,
Aug 7, 2014, 7:30:35 AM8/7/14
to joomla-de...@googlegroups.com
What keeps you from adding the CSS/JS stuff in the module? Simply adding
it to the template is not a good solution.

If all that is not sufficient for you, you have to add the CSS and JS
via Javascript when doing your first ajax call or similar.

Hannes
> --
> You received this message because you are subscribed to the Google
> Groups "Joomla! General Development" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to joomla-dev-gene...@googlegroups.com
> <mailto:joomla-dev-gene...@googlegroups.com>.
> To post to this group, send email to
> joomla-de...@googlegroups.com
> <mailto:joomla-de...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/joomla-dev-general.
> For more options, visit https://groups.google.com/d/optout.

Dimitris

unread,
Aug 7, 2014, 7:50:31 AM8/7/14
to joomla-de...@googlegroups.com
Hannes is right here. In order to add scripts or css you have to do it with javascript.
Although the idea with the bare template will work if you use this head.php.
I haven’t try it but it should do the trick
head.php

Dimitris

unread,
Aug 7, 2014, 7:52:24 AM8/7/14
to joomla-de...@googlegroups.com
Try this one the other is faulty
head.php

Hannes Papenberg

unread,
Aug 7, 2014, 8:20:31 AM8/7/14
to joomla-de...@googlegroups.com
Messing around with the header renderer is not something that I would
do. It messes up your whole site.

Hannes

Bakual

unread,
Aug 7, 2014, 8:32:28 AM8/7/14
to joomla-de...@googlegroups.com
I'd just create an own module for it instead of using the custom HTML one.
From there you can do anything again like you would with your component view.

It may also be possible to load the JS and CSS with the custom HTML module, but using an own module is certainly less messy.

Dimitris

unread,
Aug 7, 2014, 9:06:52 AM8/7/14
to joomla-de...@googlegroups.com
Hannes, he is using another template and there he will change the head.php, so really will not mess up anything (maybe the ajax view)
The code I give you in head.php has errors this is the way to do it (in head.php):

For css:
$buffer = '<script type="text/javascript">'.
'link=document.createElement("link");'.
'link.href="'.$strSrc.'";'.
'link.rel="stylesheet";'.
'link.type="text/css";'.
'document.getElementsByTagName("head")[0].appendChild(link);'.
'</script>’;
$strSrc will be your css file

For Js:
$buffer = '<script type="text/javascript">'.
'script=document.createElement("script");'. 
'script.src="'.$strSrc.'";'. 
'script.type="text/javascript";'. 
'document.getElementsByTagName("head")[0].appendChild(script);'.
'</script>’;
$strSrc will be your js file.

If you like to create your own module then again this code will put your css and js in head.
Play around and see what’s easier for you

Anibal

unread,
Aug 7, 2014, 9:12:03 AM8/7/14
to joomla-de...@googlegroups.com
Hi,

As Joomla generates a raw output, in a complex architecture of installed extensions, it's almost impossible to get a pure data structure. As a consequence, it's better to also assume, from Javascript side, a text raw output, and process it to accept your specific information.

Firstly, you generate the output wrapped in a couple of tags @My-START@.... @My-END@ 

Secondly, you accept it as raw text in the Ajax communication: 

wait : true,
dataType : 'text',
error : function(model, fail, xhr) {
alert(fail.responseText);
}


Finally, to parse the output and return the Json enconded data:

var body = resp.split(/@My-START@|@My-END@/);
if (body.length === 3) {
return JSON.parse(body[1]);
}

In this way, the data structure can be generate and processed regardless of the content where it's generated.


Hannes Papenberg

unread,
Aug 7, 2014, 9:59:08 AM8/7/14
to joomla-de...@googlegroups.com
Sorry, but I disagree here. Either your site behaves properly, then you
are good with the format=raw approach and that is it. Or your site does
not behave properly, but then you have serious issues and should look
into fixing those instead of messing around with some sorry excuse of a
workaround. Joomla itself will not polute your output with anything
really when you are using format=raw.

Dimitris

unread,
Aug 7, 2014, 4:16:18 PM8/7/14
to joomla-de...@googlegroups.com
I have to say that Hannes is totally correct here. There is no way that you can do anything in the template to inject css or js. The only way this can be done is to pass the css or js with the snippets i wrote 2 posts before inside the function getAjax() and make sure that you are on a raw format.
Sorry for misleading you on this, I overlooked the case that Ajax is actually injecting DIRECTLY data in the page (json or raw)
Reply all
Reply to author
Forward
0 new messages