How to check if certain JS file was included in a webpage? - javascript

In my custom JS code file I use various plugins, for instance, the Masonry plugin for JQuery. However, I don't include the plugin on every page or at the master page file level (in some yes, in some no) but I do include my custom file on every page. Therefore, the code in my JS file will issue an error if the Masonry plugin is missing.
If someone could reply with a solution of how to:
Check if certain JS plugin was referenced (included) and only run the code then,
(optionally) include the file at runtime if it is missing.
I have it working with JQuery and JQuery UI because they both introduce a class into DOM structu (jquery and jquery.ui objects) but there are other plugin's like lightbox scripts, the forementioned Masonry etc..

Rather than checking whether a particular JavaScript file has been 'included', I'd just check if the functionality that you need is available (i.e. if you need a function named foo, just do something along the lines of typeof foo == 'undefined' to see if it is there ...).

What you are trying to do is probably a bad idea, but anyway here's how to determine if a given plugin has been defined. In jQuery they are just namespaces to the jQuery scope:
if(!jQuery().somePlugin) {
// the plugin is not loaded => load it:
jQuery.getScript('/url_of_the_plugin', function() {
// the plugin is now loaded => use it
});
}

You can only check if its class or methods are defined, in your case:
if (typeof($.fn.masonry) == 'undefined') ...
Anyway, I'll recommend including every script at every page, compressed into one file. The cost of downloading and parsing potentially not needed code is often far less than penalty of having multiple HTTP requests.

Related

Find out what js file was loaded, but not used

Is there a way to know what js files was loaded in html, but not used? Let's say I load on a HTML page jQuery, jQuery Tabs, jQuery DatePicker libs, but on that page I use none o them, except jQuery. Is there a way to find out what js files where used ( executed )?
Short answer - No.
Long answer:
Since the files are referenced in the page itself, all scripts would be loaded, executed and it's code(global variables and functions - $ for example) exposed.
The only way to check if a certain part of a script is executed, is to observe the actors or -in other words- the calling code and the called code.
For example:
function callingFunction() {
console.log('I will call this code!');
calledFunction();
}
function calledFunction() {
/// <summary>
/// Lets say this function is added in a external file
/// </summary>
console.log('My code was called!');
}
onDemand scriptloading
A good aproach would be to load your libraries only when needed. jQuery's $.getScript is doing a great job here. If you reference your libraries like this, you can check the currently loaded ones via the network panel.
Update
Chrome 59 now supports Code coverage which does something similar.
Check it out
https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage
No not really. When you include all files, all javascript code in that file is loaded. If you want to load the js file at the moment you use a function in it, you can check if the plugin is available. If it isn't available then include the file.
E.g.:
if(jQuery().datepicker) {
//Include datepicker here
}
No cause when you include any js into your page it gets loaded,
though you can check what is getting run when you interact with things using thne chrome event listeners tab.
That's the closest you are gonna get
I don't think there is an easy way to do what you want. If the purpose is to do lazy loading, prefer use a library like require

How to handle dependencies when libraries are loaded asynchronously?

Google Pagespeed said I should load my JS files asynchronously, but this has introduced a problem for many of my pages with code using libraries and plugins.
For example, I have the following code on one page:
$(document).ready(function () {
var hound = new Bloodhound({ .......
});
So when the page loads, I am creating a Twitter Bloodhound (goes with Typeahead) object. The problem is, if Bloodhound and Typeahead are loaded asynchronously, then an error is thrown:
Uncaught ReferenceError: Bloodhound is not defined
This is because those scripts haven't been loaded yet.
I came up with this solution:
$(document).ready(function () {
createBloodhound();
});
function createBloodhound() {
if (typeof Bloodhound != "undefined") { // if bloodhound JS has loaded
var hound = new Bloodhound({ .......
}
else {
setTimeout(function(){
createBloodhound();
}, 10);
}
}
Is this a good practice, or is there a better way?
NOTE: I realize there are libraries like RequireJS out there to handle dependencies when loading files, but I don't think this type of solution will not work in my case because I load the libraries asynchronously in a wrapper file (since they're required for every page). The example code here would not be on every page, but only on a specific page on my website.
The best approach is to use a callback mechanism, which you can react to, rather than using a polling mechanism. I used script.js, which is simple and yet functional, and offers the callback mechanism.
Without that, you could implement something yourself. Performance-wise though, utilizing callback are better.
Depending on the complexity of your site, different options might be best. If...
All of your javascript is in JS files
Your above-the-fold content looks identical before and after the JS is loaded (or close enough to identical that the flash of change when your JS does load wouldn't distract your users)
The total file size is small (or most of your JS is needed on pages everyone will visit every time they visit your site)
... then combine them into one file and just server that instead of all the individual ones. Then you don't have to worry about dependencies at all. Include that script file at the bottom of your body tag (no need for async or defer attributes, but you can use them if you want).
If some of your javascript is necessary to make your above-the-fold content look correct, do the same thing, except split your JS into two files. One file contains only what is necessary to make the above-the-fold content look correct, and the other file contains everything else. Include the first one in your head tag (possibly inlining it), and include the second one at the bottom of your body tag. If the second one depends on the first tag, do not use the async attribute, because it might get executed first.
If you have some large JS files that are only used on some pages, and those files depend on other JS files, stick your scripts at the bottom of your body tag and use the defer attribute.
If you have javascript mixed in with your HTML, you can use a callback mechanism (like script.js), or you can build up execution queues like Google Analytics does, which the external script knows to look for when it first loads.

Error loading KnockoutJS as part of a third party package when host site uses RequireJS

I've developed a JavaScript plugin to be included on our customers' websites. The plugin I've created depends on some external libraries, which are bundled and delivered to the client as one big package: jQuery 1.8.2 and KnockoutJS v3.0.0.
The plugin plays fine on most sites, but if the host site uses RequireJS, my package fails to load because KnockoutJS automatically detects that RequireJS exists and attempts to use it. Here is the error that gets thrown:
Mismatched anonymous define() module
Obviously, I've found an "explanation" of the error message on the RequireJS site. Unfortunately, I don't understand how to avoid it. In my local copy of the KnockoutJS library, I've found the offending line:
(function(factory) {
// Support three module loading scenarios
if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
// [1] CommonJS/Node.js
var target = module['exports'] || exports; // module.exports is for Node.js
factory(target);
} else if (typeof define === 'function' && define['amd']) {
// [2] AMD anonymous module
define(['exports'], factory);
} else {
// [3] No module loader (plain <script> tag) - put directly in global namespace
factory(window['ko'] = {});
}
}
If I manually edit this file so that condition [2] never executes and only condition [3] every executes, then everything works fine. Of course, I don't want to do this because it requires me editing an external library, which I'd prefer to keep in pristine condition so I can upgrade it later.
I have a feeling there may be a way to make this work, I just don't understand how RequireJS works. Obviously, KnockoutJS is TRYING to play nice with RequireJS, but in my case, it's failing. For me, in this case, even though RequireJS exists, I don't need KnockoutJS to use it.
How can I get these two libraries to work side by side?
EDIT
I have no control over when my library is loaded vs. all other libraries the host site already loads. In fact, most of the time my plugin will be included, it will be by someone with NO web dev experience using a terrible WYSIWYG platform like WordPress, Webs.com or Weebly so sometimes my script tag might make it to the top of the head element, other times it might be included in the body element somewhere.
Also, to be clear, my library does NOT use RequireJS. It just so happens that one of our customers that is trying to use my library DOES use RequireJS and when my library gets included, KnockoutJS (bundled with my library, but NOT already on the host site) throws an exception because it thinks it needs to register itself with RequireJS (or at least that's my speculation as to the exception).
While, in principal, I'm not opposed to loading the libraries my code depends on on demand, the truth is that it will create a slow, poor experience for my users as it will take additional request/response cycles to load them.
Well, the easiest thing to do would probably be to load knockout before requirejs. ko will no longer detect that require is present, and will go with option [3]. If you can't do this, the other option is to add your plugin and ko file in a require hierarchy.
So let's say that you plugin looked like this:
(function(ko){
//stuff
ko.applyBindings({});
})(ko)
You would need to change it to this:
require([
"knockout-3.0.0.js" // this should be the url you use for knockout
], function(ko){
//stuff
ko.applyBindings({});
})
and NOT load the knockout.js file as a separate tag. Require will handle the loading. The server must still be able to deliver the "knockout-3.0.0.js" url of course. This is how require works. It loads whatever urls you pass as elements in the array parameter of require, and passes what they return as parameters to the function.
If you need to minify/bundle both the plugin file and the ko file into a single file, you can use the reuquirejs minifier/optimizer (http://requirejs.org/docs/optimization.html). It will navigate the dependency tree and output only one js file with all modules inside. One quirk here: you need to drop the .js extension for the minifier to work, read more about it the documentation, I just mentioned it to save some headaches.
Also, more documentation on how to use ko with require can be found here: http://knockoutjs.com/documentation/amd-loading.html
EDIT, after op edit:
OK, so in this case you should create a separate scope, in which you can do what you want. You'll need to copy the ko code inside your file, but like this you'll at least get a single file.
So, first create a scope:
(function(){
})()
Then copy ko code inside:
(function(){
//ko code here, should be a single, minified line
})()
Then you need to trick ko into using option 3, so do this:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
})()
Optionally, you might also want to reassign window in the step above, if you don't want ko to be available to the entire page.
And now add your plugin code:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
//plugin code here;
})()

Rails/Javascript selectors won't find elements

I am in the process of installing the asset pipeline into an older rails app. I am getting some really strange results though. I can see that the page is rendering all of the css and the jquery that is in the app/assets directory but its having a hard time interacting with the html.
For instance if i inspect the page and in the console call $("html").html(); to try grab all the html it returns TypeError: Cannot call method 'html' of null same when trying to grab any element that is being rendered? but the page is there. if i call jQuery it will return fine. so its not like it jQuery isnt there.
$ is just a shorthand way of writing jQuery. If the latter works but the former doesn't, then another script in your pipeline is probably conflicting with jQuery and trying to use the $ symbol for something else.
Are you using any other plugins or libraries that might be trying to use $? Or have you accidentally overwritten it yourself by writing $ = (something) anywhere? Without more information it's hard to know where the problem is exactly.
If all else fails you can just stick to using jQuery() for all your calls. In your external script file you could also circumvent this by passing the jQuery object to a wrapper function, e.g.:
(function ($) {
$('div').append('You can use $ here without having to worry about conflict.');
}(jQuery))

Where to put JavaScript configuration functions?

What is the general developer opinion on including javascript code on the file instead of including it on the script tag.
So we all agree that jquery needs to be included with a script file, like below:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"
type="text/javascript"></script>
My question is, in order to get functions on a page that is not on all pages of a site. Do we include the functions like below in the same page or in a global include file like above called mysite.js.
$(document).ready(function(){
$(".clickme").click(function(event){
alert("Thanks for visiting!");
});
});
ok. So the question is: if the code above is going to be called in every class="clickme" on a specific pages, and you have the ability to call it either from an include separate file called mysite.js or in the content of the page. Which way will you go?
Arguments are:
If you include it on the page you will only call it from those specific pages that the js functionality is needed.
Or you include it as a file, which the browser cached, but then jquery will have to spend x ms to know that that function is not trigger on a page without "clickme" class in it.
EDIT 1:
Ok. One point that I want to make sure people address is what is the effect of having the document.ready function called things that does not exist in the page, will that trigger any type of delay on the browser? Is that a significant impact?
First of all - $("#clickme") will find the id="clickme" not class="clickme". You'd want $(".clickme") if you were looking for classes.
I (try to) never put any actual JavaScript code inside my XHTML documents, unless I'm working on testing something on a page quickly. I always link to an external JS file to load the functionality I want. Browsers without JS (like web crawlers) will not load these files, and it makes your code look much cleaner to the "view source".
If I need a bit of functionality only on one page - it sometimes gets its own include file. It all depends on how much functionality / slow selectors it uses. Just because you put your JS in an external JS file doesn't mean you need to include it on every page.
The main reason I use this practice - if I need to change some JavaScript code, it will all be in the same place, and change site wide.
As far as the question about performance goes- Some selectors take a lot of time, but most of them (especially those that deal with ID) are very quick. Searching for a selector that doesn't exist is a waste of time, but when you put that up against the wasted time of a second script HTTP request (which blocks the DOM from being ready btw), searching for an empty selector will generally win as being the lesser of the two evils. jQuery 1.3 Performace Notes and SlickSpeed will hopefully help you decide on how many MS you really are losing to searching for a class.
I tend to use an external file so if a change is needed it is done in one place for all pages, rather than x changes on x pages.
Also if you leave the project and someone else has to take over, it can be a massive pain to dig around the project trying to find some inline js.
My personal preference is
completely global functions, plugins and utilities - in a separate JavaScript file and referenced in each page (much like the jQuery file)
specific page functionality - in a separate JavaScript file and only referenced in the page it is needed for
Remember that you can also minify and gzip the files too.
I'm a firm believer of Unobtrusive JavaScript and therefore try to avoid having any JavaScript code in with the markup, even if the JavaScript is in it's own script block.
I agreed to never have code in your HTML page. In ASP.net I programmatically have added a check for each page to see if it has a same name javascript file.
Eg. MyPage.aspx will look for a MyPage.aspx.js
For my MVC master page I have this code to add a javascript link:
// Add Each page's javascript file
if (Page.ViewContext.View is WebFormView)
{
WebFormView view = Page.ViewContext.View as WebFormView;
string shortUrl = view.ViewPath + ".js";
if (File.Exists(Server.MapPath(shortUrl)))
{
_clientScriptIncludes["PageJavascript"] = Page.ResolveUrl(shortUrl);
}
}
This works well because:
It is automagically included in my files
The .js file lives alongside the page itself
Sorry if this doesn't apply to your language/coding style.

Categories

Resources