JavaScript
Overview
HUBzero comes with the jQuery Javascript Framework included by a system plugin. jQuery is not only a visual effects library–it also support Ajax request and JSON notation, table sort, drag & drop operations and much more. All current HUBzero JavaScripts are built on this framework.
Note: If running extensions that require the MooTools Javascript framework (Joomla's default), the jQuery system plugin can be run in compatibility mode or turned off completely.
Directory & Files
The jQuery framework can be found within the /media/system/js
directory. It is a compressed version used for production. An uncompressed version may be found at jquery.com.
/hubzero
/media
/system
/js
jquery.js
Most HUBzero templates will include some scripts of their own for basic setup, visual effects, etc. These are generally stored in (but not limited to) a sub-directory, named /js
, of the template's main directory.
/hubzero /media /system /js jquery.fancybox.js jquery.fileuploader.js jquery.ui.js
Of the scripts commonly found in a HUBzero template, hub.js
is perhaps the most important and it is strongly encouraged that developers include these files in their template.
hub.js
//----------------------------------------------------------- // Create our namespace //----------------------------------------------------------- var HUB = HUB || {}; HUB.Base = {}; var alertFallback = true; if (typeof console === "undefined" || typeof console.log === "undefined") { console = {}; console.log = function() {}; } //----------------------------------------------------------- // Various functions - encapsulated in HUB namespace //----------------------------------------------------------- if (!jq) { var jq = $; $.getDocHeight = function(){ var D = document; return Math.max(Math.max(D.body.scrollHeight, D.documentElement.scrollHeight), Math.max(D.body.offsetHeight, D.documentElement.offsetHeight), Math.max(D.body.clientHeight, D.documentElement.clientHeight)); }; } else { jq.getDocHeight = function(){ var D = document; return Math.max(Math.max(D.body.scrollHeight, D.documentElement.scrollHeight), Math.max(D.body.offsetHeight, D.documentElement.offsetHeight), Math.max(D.body.clientHeight, D.documentElement.clientHeight)); }; } var template = {}; jQuery(document).ready(function(jq){ var $ = jq, w = 760, h = 520, templatepath = '/templates/template/'; // Set focus on username field for login form if ($('#username').length > 0) { $('#username').focus(); } // Turn links with specific classes into popups $('a').each(function(i, trigger) { if ($(trigger).is('.demo, .popinfo, .popup, .breeze')) { $(trigger).on('click', function (e) { e.preventDefault(); if ($(this).attr('class')) { var sizeString = $(this).attr('class').split(' ').pop(); if (sizeString && sizeString.match(/d+xd+/)) { var sizeTokens = sizeString.split('x'); w = parseInt(sizeTokens[0]); h = parseInt(sizeTokens[1]); } else if(sizeString && sizeString == 'fullxfull') { w = screen.width; h = screen.height; } } window.open($(this).attr('href'), 'popup', 'resizable=1,scrollbars=1,height='+ h + ',width=' + w); }); } if ($(trigger).attr('rel') && $(trigger).attr('rel').indexOf('external') !=- 1) { $(trigger).attr('target', '_blank'); } }); if (jQuery.fancybox) { // Set the overlay trigger for launch tool links $('.launchtool').on('click', function(e) { $.fancybox({ closeBtn: false, href: templatepath + 'images/anim/circling-ball-loading.gif' }); }); // Set overlays for lightboxed elements $('a[rel=lightbox]').fancybox(); } // Init tooltips if (jQuery.ui && jQuery.ui.tooltip) { $(document).tooltip({ items: '.hasTip, .tooltips', position: { my: 'center bottom', at: 'center top' }, // When moving between hovering over many elements quickly, the tooltip will jump around // because it can't start animating the fade in of the new tip until the old tip is // done. Solution is to disable one of the animations. hide: false, content: function () { var tip = $(this), tipText = tip.attr('title'); if (tipText.indexOf('::') != -1) { var parts = tipText.split('::'); tip.attr('title', parts[1]); } return $(this).attr('title'); }, tooltipClass: 'tooltip' }); // Init fixed position DOM: tooltips $('.fixedToolTip').tooltip({ relative: true }); } //test for placeholder support var test = document.createElement('input'), placeholder_supported = ('placeholder' in test); //if we dont have placeholder support mimic it with focus and blur events if (!placeholder_supported) { $('input[type=text]:not(.no-legacy-placeholder-support)').each(function(i, el) { var placeholderText = $(el).attr('placeholder'); //make sure we have placeholder text if (placeholderText != '' && placeholderText != null) { //add plceholder text and class if ($(el).val() == '') { $(el).addClass('placeholder-support').val(placeholderText); } //attach event listeners to input $(el) .on('focus', function() { if ($(el).val() == placeholderText) { $(el).removeClass('placeholder-support').val(''); } }) .on('blur', function(){ if ($(el).val() == '') { $(el).addClass('placeholder-support').val(placeholderText); } }); } }); $('form').on('submit', function(event){ $('.placeholder-support').each(function (i, el) { $(this).val(''); }); }); } };
HUB Namespace
Typically the template will include a file (hub.js
) that first establishes a HUB
namespace and then proceeds through some basic setup routines. All HUBzero built components, modules, and templates that employ JavaScript place scripts within this HUB
namespace. This helps prevent any naming collisions with third-party libraries. While it is recommended that any scripts you may add to your code is also placed within the HUB namespace, it is not required.
Note: When not using jQuery, the template will include a global.js
file that establishes the HUB namespace.
Some additional sub-spaces for further organization are available within the HUB
namespace. Separate spaces for Modules, Components, and Plugins are created. Once again, this further helps avoid possible naming/script collisions. Additionally, one more Base space is created for basic setup and utilities that may be used in other scripts.
// Create our namespace if (!HUB) { var HUB = {}; // Establish a space for setup/init and utilities HUB.Base = {}; // Establish sub-spaces for the various extensions HUB.Components = {}; HUB.Modules = {}; HUB.Plugins = {}; }
To demonstrate adding code to the namespace, below is code from a script in a component named com_example
.
// Create our namespace if (!HUB) { var HUB = {}; // sub-space for components HUB.Components = {}; } // The Example namespace and init method HUB.Components.Example = { init: function() { // do something } } // Initialize the code (jQuery) jQuery(document).ready(function($){ Components.Example.init(); });
Loading From An Extension
Components
Occasionally a component will have scripts of its own. Pushing JavaScript to the template from a component is quite easy and involves only a few lines of code.
Hubzero\Document\Assets::addComponentScript('com_example');
First, we load the Hubzero\Document\Assets
class. Next we call the static method addComponentScript
, passing it the name of the component as the first (and only) argument. This will first check for the presence of the style sheet in the active template's overrides. If found, the path to the overridden script will be added to the array of scripts the template needs to include in the <head>
. If no override is found, the code then checks for the existence of the script in the component's directory. Once again, if found, it gets pushed to the template.
Modules
Loading Javascript from a module works virtually the same as loading from a component save one minor difference in code. Instead of calling the addComponentScript
method, we call the addModuleScript
method and pass it the name of the module.
Hubzero\Document\Assets::addModuleScript('mod_example');
Plugins
Loading Javascript from a plugin works similarly to loading from a component or module but instead we call the addPluginScript
method and pass it the name of the plugin group and the name of the plugin.
Hubzero\Document\Assets::addPluginScript('examples', 'test');
Plugin Javascript must be named the same as the plugin and located within a directory of the same name as the plugin inside the plugin group directory.
/plugins /examples /test test.css test.php test.xml
View Helpers (all extensions)
Modules, Component, and plugin views now have helpers for pushing Cascading StyleSheets and JavaScript assets to the document. Each method automatically looks for overrides within the current, active template, taking out the busy work of checking yourself each time assets are added. The method names are short, accept a range of options, and allow for method chaining, all tailored for brevity and ease of use.
The css() method provides a quick and convenient way to attach stylesheets. For components, it accepts two arguments:
- The name of the stylesheet to be pushed to the document (file extension is optional). If no name is provided, the name of the component or plugin will be used. For instance, if called within a view of the component "com_tags", the system will look for a stylesheet named "tags.css".
- The name of the extension to look for the stylesheet. For components, this will be the component name (e.g., com_tags). For plugins, this is the name of the plugin folder and requires the third argument of plugin group (type) be passed to the method.
- *Plugin views only.* The name of the plugin.
Example:
<?php // Push a stylesheet to the document $this->css() ->css('another') // Extension (.css) is optional ->css('tags.css', 'com_tags'); // Load CSS from another component ?> ... view HTML ...
Along with file names, the method also accepts style declarations:
<?php // Push a stylesheet to the document $this->css('.foo { color: #000; }'); ?> ... view HTML ...
Similarly, a js() method is available for pushing javascript assets to the document. The arguments accepted are the same as the css() method described above.
<?php // Push some javascript to the document $this->js() ->js('another'); ?> ... view HTML ...
And, just as the css() method accepts style declarations, the js() method accepts script declarations:
<?php // Push some javascript to the document $this->js(' jQuery(document).ready(function($){ $("a").on("click", function(e){ console.log($(this).attr("href")); }); }); '); ?> ... view HTML ...