Home » Php » php – Check if jQuery is included in Header (Joomla)

php – Check if jQuery is included in Header (Joomla)

Posted by: admin July 12, 2020 Leave a comment

Questions:

Is there a way to check if jQuery is loaded using PHP?

I have two different plugins in Joomla that load the jQuery JS, but when it is included more than once it does not work correctly.

To explain the process a bit more:
Joomla offers an ability to intercept the HTML source before it is rendered, essentially working on the source code itself.

This is using the function:

onPrepareContent(&$row, &$params, $limitstart)

$row is the HTML content of the page that can be parsed.

I was thinking that maybe a preg_match could work but don’t have very much experience with it.

How to&Answers:

Better yet, you can verify it with JavaScript and then add it to the head if missing.

   if (typeof jQuery == 'undefined') { 
   var head = document.getElementsByTagName("head")[0];
   script = document.createElement('script');
   script.id = 'jQuery';
   script.type = 'text/javascript';
   script.src = 'js/jquery.js';
   head.appendChild(script); 
}

Answer:

I’m assuming you’re using Joomla1.0?

Joomla buffers content using the PHP output buffer. ie: ob_start().

You can get the contents using: ob_get_contents();

Thus you can have a regular expression that checks for JQuery. Something like:

$jquery_loaded = preg_match("/<script.*?src=[\"']jquery[^\"']\"/i", ob_get_contents());

should be good enough. (I haven’t tested that).

Using ob_get_contents() may not work in situations since the PHP output buffer can be nested. You can start as many buffers within buffers.

For Joomla1.5, you can get the buffer via the API which ensures you’re always getting Joomla output.

$Document =& JFactory::getDocument();
$buffer = $Document->getBuffer();

Whether Joomla1.0 or 1.5 you have to note that Joomla can add to the buffer at any point before it renders the output (calls ob_flush() or equivalent). Thus your check for JQuery has to take into account that JQuery can be loaded after the check.

Note that Joomla buffer is created not only for HTML, but can be CSS, JavaScript, XML, JSON etc. So you might want to check for HTML before doing your JQuery tests. You can also test for the admin panel.

$mainframe =& JFactory::getApplication();
$doctype    = $document->getType();

        // deactivate for backend
        if ($mainframe->isAdmin() || $doctype != 'html') {
            return false;
        }

For reference here is an example system plugin that partly does the things you want. It is a compatibility plugin for MooTools1.2.

<?php
/**
 * MooTools1.2 w/ 1.1 compat for AjaxChat
 * @copyright www.fijiwebdesign.com
 * @author [email protected]
 * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
 */

// included only
defined( '_JEXEC' ) or die( 'Direct Access to this location is not allowed!' );

jimport( 'joomla.plugin.plugin' );

/**
 * Joomla PHP Speedy Integration
 *
 * @author [email protected]
 */
class  plgSystemAjaxchat extends JPlugin
{
    /**
     * Constructor
     *
     * For php4 compatability we must not use the __constructor as a constructor for plugins
     * because func_get_args ( void ) returns a copy of all passed arguments NOT references.
     * This causes problems with cross-referencing necessary for the observer design pattern.
     *
     * @access  protected
     * @param   object $subject The object to observe
     * @param   array  $config  An array that holds the plugin configuration
     * @since   1.0
     */
    function plgSystemAjaxchat(& $subject, $config)
    {
        parent::__construct($subject, $config);

        $mainframe =& JFactory::getApplication();
        $document   =& JFactory::getDocument();
        $doctype    = $document->getType();

        // deactivate for backend
        if ($mainframe->isAdmin()) {
            return false;
        }

        // add mootools 1.2
        if ( $doctype == 'html' ) {
            $document->addScript('components/com_ajaxchat/js/mootools-1.2-core.js');
            $document->addScript('components/com_ajaxchat/js/mootools-1.2-more.js');
            $document->addScript('components/com_ajaxchat/js/mootools-1.2-core-compat.js');
            $document->addScript('components/com_ajaxchat/js/mootools-1.2-more-compat.js');
        }

    }

    /**
     * After Templte output is in buffer
     */
    function onAfterRender() {

        $mainframe =& JFactory::getApplication();
        $document   =& JFactory::getDocument();
        $doctype    = $document->getType();

        // deactivate for backend
        if ($mainframe->isAdmin()) {
            return false;
        }

        // Only render for HTML output
        if ( $doctype !== 'html' ) { 
            return; 
        }

        // get the output buffer
        $body = JResponse::getBody();

        // remove mootools if not needed
        if (stristr($body, 'mootools.js') || stristr($body, 'mootools-uncompressed.js')) {
            $body = preg_replace("/<script.*?mootools(-uncompressed)?\.js.*?<\/script>/i", '', $body);
        } else {
            $body = preg_replace("/<script.*?mootools-1\.2\-.*?\.js.*?<\/script>[\s\t\r\n]*/i", "\n", $body);
        }

        JResponse::setBody($body);
    }

}

?>

Answer:

Should first make the check in javascript. for example:

window.onload = function()
{
   if (typeof(window.jQuery)=="undefined")
      alert('jQuery no load');
   else
      alert('jQuery Ok');
}

then, you could send a message by ajax to the server.

Answer:

That’s not possible. PHP is server-side, while Javascript (the language JQuery is written in) is client-side. PHP code inherently has to run before the text that includes the Javascript even be sent to the user and attempted to be loaded.

Your best bet is to not include jQuery more than once. You could do this by replacing all of your includes with something like:

<script type='text/javascript'>
    if($) { } // test to see if the jQuery function is defined
    else document.write("<script type='text/javascript' src='jquery.js'></script>");
</script>

Admittedly this is a bit of a hack, and there might be a better way.

EDIT: After a bit of thought: this may not even work because of the asynchronicity of loading the jQuery library from the server. It seems like the best way to do this would be with an onload event handler attached to the script include, but the DOM doesn’t support that.

EDIT 2: Okay, now I think that your best bet would be to simply include it once in the page using only one script tag per-page. You could do this by adding it to a global header of some sort and then removing it everywhere else. Then, no matter what, don’t include it again. This might mean that you load it on some pages that don’t need it, but due to cache on modern browsers it shouldn’t be a problem.

Answer:

You might want to try using the JDocument object to get the headers, search for jQuery, then reset as necessary. The getHeadData() and setHeadData() methods should help you from there. You can get the current JDocument object with this code:

$document =& JFactory::getDocument();

You might also want to look at this response to a similar question: Joomla, jQuery modules conflicting

In that one, you’re actually stripping out the redundant jQuery loads.

Answer:

Unless Joomla provides a way of telling you which scripts it is including? (Zend Framework has such a list)