Using multiple jQuery plugins on multiple pages? - javascript

I have site which is using a few JavaScript/jQuery plugins, I then have a default.js file which uses the plugin functionality for each of the different pages.
E.g. some plugins I have include:
a custom scrollbar plugin
a slideshow plugin
a cookie plugin
etc.
Then in the default.js file, I'll do something as follows (pseudocode):
var scrolling = findScrollbarDiv;
scrolling.ScrollFunction({ options });
(and then the same for the slideshow + other plugins I have)
However, if there is a plage where findScrollbarDiv returns null, I get an error something like the following:
ScrollFunction is not a function
This is not because the elements are returning null, but because I haven't included the plugin file for this page. My reasoning behind this is that I don't want to include every file on every page (even if it's not needed) as this could cause unnecessary HTTP requests (especially on the homepage, which only needs one plugin)
This error in turn messes up the rest of the JavaScript.
What is the best way to overcome this? Should I just include every plugin file on every page regardless of whether it is needed or not? Or is there some JavaScript like the following that I can use:
var scrolling = findScrollbarDiv;
if(scrolling != null) {
scrolling.ScrollFunction({ options });
}
(this feels a bit clunky to me, but if this is the best solution let me know)
Or is using one default js file to launch all plugins a bad idea?

If you're using the same header file and you don't mind having the file included, you can always check if the element exists before attaching an event to it.
Heres an example:
if(jQuery('#someElement').length > 0){
jQuery('#someElement').ScrollFunction({ options });
}
Either that, or have a JavaScript file for each function.
So you'd have one for the gallery and one for the cookies etc.. And include only the ones necessary for each page.

You can just do it as a conditional statement and avoid the clunky if:
scrolling && scrolling.ScrollFunction({ options });
This works great for any method you want to call and want to check if the parent object exists before you do.
You can go further (if you need to) and check if the method itself exists before execution:
scrolling && scrolling.ScrollFunction && scrolling.ScrollFunction({ options });
if scrolling is a collection, just check it's length (if length == 0 the statement will fail):
scrolling.length && scrolling.ScrollFunction({ options });

Related

how to handle javascript that only runs on certain pages when bundled together

When working on small client sites, I often end up working with a main.js file that includes a bunch of jQuery plugins and small toggle functionality. Some of these code snippets are only relevant on certain pages, but ends up bundled together in one main.min.js file.
My question is, how do people write the individual code snippets in order to only execute that code when the correct page is being rendered?
Here's an example: Let's say I have a page with a search input field. This input is hooked up with jQuery autocomplete in order to show search suggestions as the user types. the code in main.js could look something like this:
var data = [
{
value: 'some value',
data: 'some data'
},
{...}
]
$('#autocomplete').autocomplete({
lookup: data,
lookupLimit: 10,
minChars: 3,
});
This code is only useful on the template that has that input field, but as main.js contains a bunch of other smaller bits like this that are useful globally and on other pages, the whole file is loaded on every pageview. What strategy should I use to only execute that piece of code when the page needs it?
I though of a few ways my self:
Check if the DOM-element (in this case #autocomplete) exists.
Check if the URL is == '/page-with-autocomplete'.
Use a class on , and check for that class i n order to run the script.
Other ideas? Any standard way to do this sort of thing? Anything considered a "best practice"?
Stick your JS in an if block and check for the unique DOM element on the page you want the script to run.
Although you can't just do:
if ( $('#my-el') ) {}
You have to check if the element has a length, like:
if ( $('#my-el').length ) {}

Include a javascript file only once in Joomla

now, this question has been asked and answered successfully many times, yet none of the things i try work.
I have tried head.js & require.js libraries
I have also tried
if (!window.unique_name) {
unique_name = true;
//code here..
}
none of which I can get to work (the global variable is always undefined)
the script I am trying to include runs something like this:
//clock.js
clockyTick = function() {
//my code here
}
setInterval(clockyTick, 1000);
the apps that call this script, standalone, work fine.
only when both apps are included on the same page (via calls to PHP require()) they break.
Here is the cause of the problems (I think):
I am building custom web apps on a (Joomla) site and have the requirement of displaying two of my apps on the same page.
Both apps need the same .js file to operate correctly, which works fine when they run standalone, but as soon as both apps are running on the same page (in the admin section) the scripts conflict and stop each other from working
(the script in question is a dynamic clock script that grabs the specialised contents of a div and modifies it to something else)
I think the reason I cannot get aforementioned libraries to work, is the fact that they also are being included twice on the admin page.
is there any way around this, or do I have to bite the bullet and integrate a library into the main Joomla template? (meaning the library is uselessly loaded on every single page, yet only used on 3 of hundreds)
jQuery is also required, separately, on each app..but thankfully I am able to use noConflict to avoid problems there (not ideal)
The joomla way would be to instantiate the document inside your module and unset only the conflicting script as described in this question here just before you load the module's script:
1) get an instance if the document object and remove the js files (you
could do that in a plugin) :
<?php
//get the array containing all the script declarations
$document = JFactory::getDocument();
$headData = $document->getHeadData();
$scripts = $headData['scripts'];
//remove your script, i.e. mootools
unset($scripts['/media/system/js/mootools-core.js']);
unset($scripts['/media/system/js/mootools-more.js']);
$headData['scripts'] = $scripts;
$document->setHeadData($headData);
?>
Or in your case, I think you could try the dirty solution below inside your js files:
//1st module script
var unique_name;
if (unique_name == false || unique_name == null) {
unique_name = true;
//code here..
alert("Included 1st script");
}else{
//do nothing
alert("Not included 1st script")
}
//2nd module script
var unique_name;
if (unique_name == false || unique_name == null) {
unique_name = true;
//code here..
alert("Included 2nd script");
}else{
//do nothing
alert("Not included 2nd script")
}
Here is a DEMO
If you are having conflicts with PHP require(), you can try require_once(). However, as mentioned, that’s not the Joomla way of doing things.

How to include javascript file only once

I want to give clients an HTML block they can include in their site, and this HTML will contain some table and image, plus a javascript that will make manipulations over the HTML block.
so I give them the HTML :
<a data-theme="1" data-srv="http://localhost:50987/" class="block1" href="http://myserver/payment/Details">outer information</a><script type="text/javascript" src="http://myserver/Scripts/checkout.js"></script>
in checkout.js I have included JQuery if no Jquery exists in document and do manipulation over the element $('a.block1') ... the problem is when someone puts this block of HTML more then once over the same page, I want that the client will not call "checkout.js" more then once,
I've tried declaring global var inside "checkout.js" and check if it's exists, it works good to stop doing the same manipulation more then once but I want to stop the call to JS al together .
Javascript runs after it loads, you can't stop the JS running, if it is referenced multiple times. It won't be loaded multiple times, so the overhead of it running again is basically nil.
To stop the behavior of the javascript happening again, just put the check at the top level of the file, put the rest of the file in the conditional, and write to a global variable to make sure you don't run again.
if (window._your_unique_id === undefined) {
window._your_unique_id = true;
// the rest of your javascript
}
that will mean nothing in the script runs. You can still define whatever you like in that if statement, though if you define functions and variables in there, you may have to explicitly put them on the window object, because they'll otherwise be local (but then, it is bad practice to have anything implicitly defined global anyway, so it shouldn't make any difference if your code is well structured).
Just deploy your code as a module.
Ie.
(function(window){
if(window.CheckoutModule) return;
// now you're certain there's no global module loaded
var CheckoutModule = window.CheckoutModule = {};
// you can, ie, add a jQuery check here.
if('undefined' != typeof jQuery) {
// do your jQuery thing here.
}
return ;
})(window, jQuery);

how to apply DRY principle to javascript and query

I've got about 30 web pages, all of them HTML forms. Each page has two or more different form elements - select, input text, checkboxes, text areas - along with various ui elements, popups, form validation etc. I'm trying to refactor the jquery used in the pages to use the DRY principle but am not sure how to do it. Here area few examples of some of the jquery used:
Example Code Block A:
$(".show-tool", _container).mouseover(function() {
$(this).nextAll(":hidden").css('display','block');
});
Example Code Block B:
$(".optional").blur(function(){
if ($(this).val() == '')
{
$(this).addClass('optional');
$(this).val('(Optional)');
}
});
Example Code Block C:
$('.howtoremain').click(function() {
$('.hiddendiv').slideToggle("10000");
if($(this).hasClass('howtoremain')) {
$(this).removeClass('howtoremain').addClass('howtoremain2');
}
else {
$(this).removeClass('howtoremain2').addClass('howtoremain');
}
});
All of these are contained in the document.ready. The actual code list above isn't that relevant. I'm trying to have each HTML page only include the jquery code that is relevant. For example page 1 might use code block A and B. Page 2 might use A,B,C,D,E, and F. Page 3 might use code block C and G. Rather than have one giant document.ready with every code block (which will probably cause bugs at some point anyway if one code block needs to be slightly different than another for the same form element), how do you code this? Have one javascript file per code block also seems lousy, as it would cause multiple hits to the server per page. I think I am trying to get at one big javascript file, but only initialize in the document.ready those functions that are relevant to each page.
In my projects, I have gone over to using multiple JS-Files per module and concatenating them into a closure within a build process. This is similar to what jQuery does in its build process (cf. intro.js, outro.js)
This way, I can use granular, DRY modules in smaller files, then concatenate them. A typical single module file might look like this for your Example B:
( function($) {
var subjects = $('.optional');
if ( subjects.length === 0 ) {
// this is a knockout criteria for this module, thus exit this enclosed function
return;
}
subjects.blur(function(){
if ($(this).val() == '')
{
$(this).addClass('optional');
$(this).val('(Optional)');
}
});
// now use whatever you need to initialise.
})($);
As you can see, I use the outer function not only to keep my scope clean, but much more important, to be able to cancel the module's initialisation as soon as I realise, it is not needed on the current page / event / ... - Of course, you may find several more efficient ways of determining whether or not each module should initialise itself.
On some projects, I have a build script to concatenate these modules within another closure which might look like this:
( function( window ) {
var $ = window.jQuery; //call me paranoid, but I like my vars clean
$(document).ready( function() {
// stuff the modules here, one after another, in any sensible order.
});
}(window);
In other projects, I am able to move the $(document).ready()-Bit into the modules where document.ready is needed, and listening to other Initialisation-Events within others, which feels a bit cleaner for me.
But anyway - having
a build process rather than a lot of single requests
several small, "one-thing-only"-Files to go into the build
a self-enforced "top-level lambda function" due to the intro/outro-Concatenation-Style I adapted from jQuery itself
has significantly improved my DRY-ness and, even, my JS code style.

How can I combine my JavaScript files and still have my callbacks wait for a ready state?

I have lots of functions and event handlers that are split across multiple javascript files which are included on different pages throughout my site.
For performance reasons I want to combine all of those files into 1 file that is global across the site.
The problem is I will have event handlers called on elements that won't necessarily exist and same function names.
This is an example of a typical javascript file...
$(document).ready(function(){
$('#blah').keypress(function(e){
if (e.which == 13) {
checkMap();
return false;
}
});
});
function checkMap() {
// code
}
function loadMap() {
// code
}
I would need to seperate this code into an object that is called on that specific page.
My thoughts are I could re-write it like this:
(function($) {
$.homepage = {
checkMap: function(){
// code
},
loadMap: function(){
//code
}
};
})(jQuery);
And then on the page that requires it I could call $.homepage.checkMap() etc.
But then how would I declare event handlers like document.ready without containing it in it's own function?
First of all: Depending on how much code you have, you should consider, if serving all your code in one file is really a good idea. It's okay to save http-requests, but if you load a huge chunk of code, from which you use 5% on a single page, you might be better of by keeping those js files separated (especially in mobile environments!).
Remember, you can let the browser cache those files. Depending on how frequent your code changes, and how much of the source changes, you might want to separate your code into stable core-functionality and additional .js packages for special purposes. This way you might be better off traffic- and maintainance-wise.
Encapsulating your functions into different objects is a good idea to prevent unnecessary function-hoisting and global namespace pollution.
Finally you can prevent calling needless event handlers by either:
Introducing some kind of pagetype which helps you decide calling only the necessary functions.
or
checking for the existence of certain elements like this if( $("specialelement").length > 0 ){ callhandlers}
to speed up your JS, you could use the Google Closure Compiler. It minifies and optimizes your code.
I think that all you need is a namespace for you application. A namespace is a simple JSON object that could look like this:
var myApp = {
homepage : {
showHeader : function(){},
hideHeader : function(){},
animationDelay : 3400,
start : function(){} // the function that start the entire homepage logic
},
about : {
....
}
}
You can split it in more files:
MyApp will contain the myApp = { } object, maybe with some useful utilities like object.create or what have you.
Homepage.js will contain myApp.homepage = { ... } with all the methods of your homepage page.
The list goes on and on with the rest of the pages.
Think of it as packages. You don't need to use $ as the main object.
<script src="myapp.js"></script>
<script src="homepage.js"></script>
<-....->
<script>
myApp.homepage.start();
</script>
Would be the way I would use the homepage object.
When compressing with YUI, you should have:
<script src="scripts.min.js"></script>
<script>
myApp.homepage.start();
</script>
Just to make sure I've understood you correctly, you have one js file with all your code, but you want to still be in control of what is executed on a certain page?
If that is the case, then the Terrific JS framework could interest you. It allows you to apply javascript functionality to a module. A module is a component on your webpage, like the navigation, header, a currency converter. Terrific JS scans the dom and executes the js for the modules it finds so you don't have to worry about execution. Terrific JS requires OOCSS naming conventions to identify modules. It's no quick solution to your problem but it will help if you're willing to take the time. Here are some more links you may find useful:
Hello World Example:
http://jsfiddle.net/brunschgi/uzjSM/
Blogpost on using:
http://thomas.junghans.co.za/blog/2011/10/14/using-terrificjs-in-your-website/
I would use something like YUI compressor to merge all files into one min.js file that is minified. If you are looking for performance both merging and minifiying is the way to go. http://developer.yahoo.com/yui/compressor/
Example:
Javascript input files: jquery.js, ads.js support.js
run yui with jquery.js, ads.js, support.js output it into min.js
Javascript output files: min.js
then use min.js in your html code.

Categories

Resources