Contextualizing jQuery - javascript

I've got a fairly large site, with a lot of jQuery code for lots of different pages. We're talking about 1000 lines of fairly well optimized code (excluding plugins).
I know jQuery is fairly good at ignoring listeners for page elements that don't exist, but it still has to test their existence when the page loads. I'm also creating a load of vars (including decent sized arrays and objects), but only a few of them are used on each page.
My Question is: What's the best method of cutting down the amount of work each page has to do?
However, I do NOT want to split up the code into separate files. I want to keep all my code in 1 place and for the sake of efficiency I only want to call the server to download JS once (it's only 30kb, smaller than most images).
I've thought of several ways so far:
Put all my code chunks into named functions, and have each page call the functions it needs from inline <script> tags.
Have each page output a variable as the pageID, and for each chunk of have an if statement: if (pageID = 'about' || pageID = 'contact') {code...}
Give each page (maybe the body tag) a class or ID that can be used to identify the chunks that need executing: if ($('.about').length || $('.contact').length) {code...}
Combine 1 and 2 (or 1 and 3), so that each page outputs a variable, and the if statements are all together and call the functions: if (pageID = 'about') {function calls...}
Any other ideas? Or which is the best/most efficient of those?

Your first option will be fastest (by a minute margin).
You'll need to remember to call the functions from the correct pages.
However, don't bother.
Unless you've measured a performance impact in a profiler, there is no need to optimize this much.

I would argue that you are taking more of a performance hit for downloading the 30k then you will ever see from the code execution. That said, you could always test your url to determine the page and run all setup methods through a bootloader that determines the correct functions to run/ events to bind at load time. Something like the following maybe:
$(function(){
var page_methods = {
home : [meth_1, meth_2],
about : [meth_3, meth_2]
},
page = location.pathname.match(/\/(\w)$/)[1],
i = 0,
meth;
for ( ; meth = page_methods[ page ][ i++ ] ; ){
meth();
}
});

Related

Javascript shorthand loading time

I was playing around so I ran into a JS shorthands. I know they, of course, do not change code however do they lower loading time since there is less data?
Testing codes such as one below in Chrome DOM inspector did not give me an answer (probably because they are one-line codes so it does not make any difference).
if (x == 0) {x=1} else {x=2}
x == 0 ? x = 1 : x = 2;
If your goal is to optimize the speed with which your page loads by minimizing the size of your JS payload, there are lots of tools that will automatically rebuild your files into a single bundle that is compressed (i.e., all unnecessary whitespace removed, variables/functions renamed to shorter lengths, etc.). When it comes to writing code, you should always value readability first.
Write code that other people can easily understand. Then, when you're ready to deploy, look into a tool like UglifyJS2, which will enable you to take code like this:
function square(numToSquare) {
var squareProduct = numToSquare * numToSquare;
return squareProduct;
}
square(15);
..and turn it into this:
function square(r){return r*r}square(15);
The less characters and whitespace in a file, the lower the download size of said scripts is.
Readability is also a matter of utmost importance though, and ternary operators can be confusing in certain scenarios.
I would recommend that for those cases where you expect your codebase to increase to a certain extend over time, you stick to more readable constructs and use a minification/uglification process to lower file size.

Ok to call document.querySelector( ) a bunch

If I have multiple instances of the following lines of code through out my js file:
document.querySelector('#IdName').play();
document.querySelector('#IdName').pause();
Is it a good idea to create a function and pass it the IdName(IdName will change in various parts of the code)? I know what it does but I'm really just curious if it's a good practice to call document.querySelector( )a bunch of times in the file or put it in a function where I only call it twice to perform the play and pause actions.
If you constantly need the same element, change the function to take a DOM node, and store the element in a variable instead
function doStuff(elem) {
elem.play();
}
function stopStuff(elem) {
elem.pause();
}
var element = document.querySelector('#IdName');
doStuff( element );
// later
stopStuff( element );
That way you only get the element once, and avoid unneccesary DOM lookups
The best approach is to cache that query in a variable so you don't need to search the DOM each time.
For an ID selector this time saving is likely minimal but for more complex collections can help
var $el = document.querySelector('#IdName');
$el.play();
$el.pause();
It is good practice to write code that is reusable, so in that case a function is better practice. If the function only contains 1 line of code and you call it many times, it is still preferable because then if you ever decide to update that line of code or add more code, it's centralized and you change in one place only.
As far as actual execution is concerned, these are the same:
document.querySelector('#IdName1').play();
document.querySelector('#IdName1').pause();
document.querySelector('#IdName2').play();
document.querySelector('#IdName2').pause();
document.querySelector('#IdName3').play();
document.querySelector('#IdName3').pause();
vs
playpause("#IdName1");
playpause("#IdName2");
playpause("#IdName3");
function playpause(idname){
document.querySelector(idname).play();
document.querySelector(idname).pause();
}
In addition to Steve's answer, also note that if you are using the same one twice in a row:
document.querySelector('#IdName').play();
document.querySelector('#IdName').pause();
then it is a better practice to do:
var thing_with_play_and_pause = document.querySelector('#IdName');
thing_with_play_and_pause.play();
thing_with_play_and_pause.pause();
This reduces the number of queries you have to make. Some IDEs (PyCharm for instance) will complain if you don't because it is less efficient.

How do I go about scraping a url from inline javascript

This is repeated 240 times, each time the two sets of the last digits are different numbers, i would like a list of all the urls.
So i suppose i need to find each script and then find the first "commtArr" in each script, assuming its always the first.
Where do I even start?
<script type="text/javascript">
commArr[commArr.length] = "http://example.com/index.php?option==down&pid=123&id=389";
commtArr[commtArr.length] = "mp3";
commnArr[commnArr.length] = "john doe.mp3";
</script">
The URL is actually being inserted into commArr, not commtArr
It seems commArr will only ever have the URL.
Assuming the script is repeated X times on the same page, you're left with a single variable with all the URLs already.
It's just a simple case of listing it out.
for (i = 0; i < commArr.length; i++) { console.log(commArr[i]) }
If it's on various pages, then you may need some kind of spider bot script to go to all the pages, run a script that grabs commArr and persistently saves it. I'm afraid I can't suggest anything for that aside from doing it manually.

Is it a good idea to cache jQuery selections on a page level?

I am working on an intranet website where there is a lot of interaction with the main page. The site uses jQuery extensively. So I thought about caching the jQuery selections the first time they are requested and pull them from the cache for each subsequent request. (I also have built in an override if I want to force a re-selection).
Here is the basic snippet of code I am wondering about:
( function(window, $, undefined) {
var mp = {};
mp.cache = [];
mp.get = function ( selector, force) {
return ( !force || !mp.cache[ selector ] ) /*separating for readability */
? mp.cache[ selector ] = $( selector )
: mp.cache[ selector ];
}
/* more functions and code */
window.mp = mp;
window.$$ = mp.get;
})(window, jQuery);
It would be used just like a normal jQuery selection but checks to see if that selector already exists in the cache array and, if it does, just returns the results from there.
UPDATED EXAMPLE
$('#mainmenu').on('click','.menuitem', highlightSelectedMenuItem );
function highlightSelectedMenuItem () {
var menuitems = $$('.menuitem'); //selected first time, from cache every other time
menuitems.find('.current').removeClass('current');
$(this).addClass('current');
}
There are about 20 - 30 different selections in the code. So each would be cached on first call. This code will only be run on desktop clients (no phones/tablets).
Good idea? Any issues this might cause? Is there a good way to test if this helps/hurts performance? Any pros/cons you can come up with would be appreciated.
Let me know if more information is required.
Here is a fiddle to "fiddle" with.
Thanks!
Bottom line: Probably a bad idea.
You're introducing complexity that is likely unnecessary and is likely just going to eat up memory.
If you're trying to speed up selections that are repeated, then store the selection in a variable. When it's no longer needed, the garbage collector will remove it. For 99% of applications out there, that's as much caching as you need.
A big problem with your example is that the items you've selected will stick around indefinitely. Think about the people who may work on this code later. Everyone may just start using $$('....') because they see it in a few spots and it does the same thing as $('....'). Suddenly you're storing thousands of DOM elements in memory for no reason at all.
Beyond that, if the DOM changes and you don't know about it changing, the code that you have in cache is useless.. but unless you're forcing it to reload then you'll end up continuing to get that cached code. Which of course introduces bugs. In order to prevent that from happening, you'd have to force reload the cache constantly, which pretty much negates the usefulness of it.
You're going to be better off just following good, solid programming patterns that are already out there.. rather than programming up a caching mechanism that is going to be a bug magnet.
I made your question into a jsperf, and I found that un-cached jQuery appears to run faster.
http://jsperf.com/jquery-cache-array-test
because of this I would recommend just using pure jQuery.
I think it's a bad idea. If you need to use a selection in several places the save the selection to a variable.
var mySelection = $(#myId).
it will be garbage collected when its no longer needed.

How to increase speed of getElementById() function on IE or give other solutions?

I have a project using Javascript parse json string and put data into div content.
In this case, all of itemname variables is the same div's id.
If variable i about 900, I run this code in Firefox 3 for <10ms, but it run on IE 7 for >9s, IE process this code slower 100 times than Firefox
I don't know what happen with IE ?
If I remove the line document.getElementById(itemname), speed of them seems the same.
The main problem arcording to me is document.getElementById() function?
Could you show me how to solve this prolem to increase this code on IE ?
Thank in advance.
var i = obj.items.length-2;
hnxmessageid = obj.items[i+1].v;
do{
itemname = obj.items[i].n;
itemvalue = obj.items[i].v;
document.getElementByid(itemname);
i--;
}while(i>=0);
Are you really noticing any latency?
gEBI is natively very very fast, I don't think you can avoid it anyway for what you're doing. Could you provide a low-down of what you're doing precisely? It looks like you're using a loop, but can you post exactly what you're doing inside of the loop, what your common goal of the script is?
document.getElementByid(itemname) is the fastest way to get a single element from the DOM in any real application you will sould not see any problems with using it, if you do see a problem you need to rethink you code a little it possible to acomplish any task with just a handfull of calls for this method. You can present you full problem if you like so I could show you an example
At least cache the reference to document:
var doc = document;
for(;;) {
doc.getElementById(..);
}

Categories

Resources