Do browser vendors optimize against jQuery?
I know this sounds absurd anti-standard, but I can imagine browser vendor has optimization against jQuery code built into their JS compiler/interpreter.
For example, lets say the JS compiler/interpreter sees, $('.blah > p'), the browser can say, hmm, I see that user is trying to grab an element, instead of letting jQuery do all the browser detection, it could just take the [actual DOM object], and return $([actual DOM object]) right away.
No guessing what $ does would break any scripts that use $ for different purposes. Consider a page like this (this is actually a pretty weak example relative to what could be found in the wild, but I think it still demonstrates the difficulty well enough):
<div class="bar">
<div class="foo">
<div class="bar">
How will the browser know to select this div with the selector '.bar .foo .bar', without actually running this script the way it is designed?
</div>
</div>
</div>
<script>
window.onload = function(){
var x = $('.foo');
console.log(x);
console.log(x.selector) // '.bar .foo .bar'
};
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
var $ = function(){
return arguments[0];
};
$ = (function($){
return function(selector){
return jQuery('.bar ' + selector + ' ' + $('.bar'));
}
})($);
</script>
It would be beyond an optimization for the browser to know which div to select in advance. In fact the browser has to run the scripts the way it is designed to in order to select the correct div.
However many browsers to compile Javascript to a slightly lower level language such as Java or C++ code. Then if the browser downloads and caches jQuery once it will be cached it a compiled form on the users computer. This is not a jQuery specific optimization since it will happen with any cached script, but it is more significant of an optimization for large scripts like jQuery.
No browser vendor announced such a feature at the moment.
It is possible, however. You can easily store for reference parsed Javascript (IL/bytecode, whatever you use in your engine) for most often used versions of jQuery inside JS engine and when incoming function matches that signature, replace it with native version.
I guess the only thing that you have to take in consideration is how much time you'd spend on implementing it vs. speed gains against modern JIT engines. Because some of them already compile code to some native form, at least partially, it is not quite clear if there will be any substantial gains or not.
Related
I'm having an issue with updating a web application in Chrome. It’s an ASPX site, but I don’t believe it’s relevant to this conversation. The issue is that our clients don’t get the latest programming in Chrome, because most of the time, it fails to release Javascript and CSS programming from memory, then proceeds to cause all kinds of mayhem while in use.
I tried placing this piece of code in the <head>, like many have suggested, but it doesn’t work all the time.
<script type="text/javascript">
function reload_js(par_src) {
src = $('script[src$="' + par_src + '"]').attr("src");
$('script[src$="' + par_src + '"]').remove();
$('<script/>').attr('src', par_src).appendTo('body');
}
reload_js("../../global/scripts/global_scripts.js");
reload_js("scripts/main.js");
reload_js("scripts/tabs/jquery.ui.core.js");
reload_js("scripts/tabs/jquery.ui.widget.js");
reload_js("scripts/tabs/jquery.ui.mouse.js");
reload_js("scripts/tabs/jquery.ui.sortable.js");
reload_js("scripts/tabs/jquery.ui.tabs.js");
reload_js("scripts/chat_room.js");
</script>
And I use this Javascript file to refresh my css's. One that I found here.
<script src="../../global/scripts/css_refresh.js" type="text/javascript"></script>
I'm scared that these methods cause unnecessary overhead, because they run every time a page is loaded.
Could one of you experts please tell me if this is the most efficient method for updating? Or perhaps recommend a better method to keep these files up to date?
Simplest way to fix this is to add an identifier to the script/style-files. Just add something like ?version=12 (and update the number for each release) then the browser will fetch the newest file. You can also use some sort of server-side date-option after the ?of course, to force a new fetch every day or similar.
I want to improve an existing website (I have no access to) by using my own javascript.
This means I have to add an < script > to the < head >. I am currently doing this by clicking on a bookmark which has something like this as its target:
javascript: if(document.createElement){
void(head=document.getElementsByTagName('head').item(0));
void(script=document.createElement('script'));
void(script.src='http://local/script.js');
void(script.type='text/javascript');
void(head.appendChild(script));
} // i added some spacer to make it readable
This works fine, but since i've got a lot of different scripts it gets complicated to organize them.
I am now looking for a way to automatically insert a defined script-uri if the top.location.href matches a given string.
Is there a way firefox can do something like this - maybe with the help of an add-on?
Userscripts are what you're looking for. Use Greasemonkey for Firefox to run your own script on specific sites.
https://addons.mozilla.org/en-US/developers/docs/sdk/1.12/modules/sdk/page-mod.html uses the add-on sdk, and provides precisely what you're looking for (i.e. an easy way to attach a script to a webpage if it matches a given domain). That gives you the option of making your addon a standalone one easily; moreover, if you were to extend its functionality significantly, the addon sdk would certainly be the way to go!
I've been spending some thinking time recently on how to best handle resource failure for a page.
Of course with JavaScript files there isn't much 'clever' stuff that you can do. If you're loading from a CDN we can do something like this (taken from the HTML5 Boilerplate project):
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="local/jquery-1.6.1.min.js">\x3C/script>')</script>
However I haven't seen much documented on CSS failure.
If your page is a blog post or something similar then best practice would be to make sure your markup is good, so that the un-formatted version is still a very much readable, if only a little boring, document.
But what if you don't want to fall back to Lynx style? There may be a good reason; for example your application is complicated and is very much dependant on your layout. In which case, showing the page with no stylesheet is probably worse for user experience than not showing it at all.
Therefore, I wondered if a solution such as this would work - and if any of you are using it (or something similar)?
Add a helper class at the end of your CSS file #test { line-height: 1; }
Add this JavaScript at the end of your page
var el = document.createElement('div');
el.setAttribute('id', 'test');
document.body.appendChild(el);
var o = (el.currentStyle) ? el.currentStyle['line-height'] :
(window.getComputedStyle) ? document.defaultView.getComputedStyle(el, null).getPropertyValue('line-height') : null;
if (o !== '1px') {
document.body.innerHTML = '<p>Resources failed to load, a prettier message should go here</p>';
}
See this JS Fiddle for it all together.
Questions are
Thoughts on the above?
Are you using something like this?
Do you think its a good pattern (note that I'm only advocating this for web apps that are reliant on their styles).
Your rule may not take due to user stylesheets or other browser settings overriding the rule you're testing on. line-height seems especially vulnerable to this, plus also any rule that takes a length value runs the risk of returning a computedStyle in a different unit to the one you expected, making the string comparison fail. (Not to mention the 1/1px confusion in your example.)
In general I think this needs to fail better. If you think styles haven't loaded, add a warning to the page by all means, but don't replace the whole page with an error, making it completely useless to someone who might have been able to at least try to use it. This fragility is bad for accessibility.
First of all I am new to javascript so this question might be stupid.
I have a requirement where i would provide a js script to other websites to include in their webpages.
Now my question is should I use jquery or plain javascript.Will/Can jquery effect the rest of the functionality of the site.
Plus what is the benefit I will get using jquery over plain javascript.
My requirement is to get all images of the website and do some processing on the images on these websites.
Thanks in Advance.
I would say, if the processing does not involve jQuery then do not use it.
You need to deal with the following issues if you include it
failure to load (for network reasons)
conflict with other versions locally loaded
conflict with other libraries locally loaded
All issues have workarounds/solutions but you have to implement each an everyone of those.
If you just need to find all images in page, then you can use the .getElementsByTagName() method
var imagelist = document.getElementsByTagName('img');
and just do the processing on that..
You might need of-course to attach your code at the load event to be sure that whatever your code does, the DOM is ready to accept it..
for modern browsers that would be .addEventListener(), while for IE it would be .attchEvent()
your script could be something like this
(function(){ // wrap in a self-invoking function to avoid global name-space pollution
// attach to the load event so out code runs once the page has loaded
if (window.addEventListener) { // modern
window.addEventListener('load', imageProcessor, false);
}
else if (window.attachEvent) { // IE
window.attachEvent('onload', imageProcessor );
}
function imageProcessor(){
// get all images
var imagelist = document.getElementsByTagName('img');
// loop the list of images to do something with each image
for (var img = 0; img < imagelist.length; img++)
{
var currentImage = imagelist[img];
// do processing on the currentImage which hold a reference to the image
}
}
})(); // do the self-invoking
demo: http://jsfiddle.net/gaby/nXPzk/
this would be much more easier to achieve with jQuery, mostly because you want to be able to distribute your script to any browser(and jQuery is a cross-browser library), but it does have it's downsides.
If it's your own project, your own page, you know exactly what and when to load/execute, but if you're giving your script to other folks, you have to think of 3 problems at least:
different libraries conflicts
This can be resolved using jquery's noConflict method, but I've seen it fail in some circumstances
same library conflicts
Say that the user already has loaded version X of jQuery. You oblige him to load version Y too, and besides the fact that this would be very inefficient, it may cause conflicts between different jQuery versions.
There are workarounds for this( to check if jQuery exists and load it asynchroniously if it doesn't) but the code gets a bit more complicated.
code size
When i think of a third party piece of code, I'm thinking...hmm a few kb to load to be able to run a function, but if you want to use jQuery, you may be forcing the one who uses your script to load a whole library just for your one functionality instead of a 1-2 kb (needles to say what the implications are if the user has a slow connection)
Having both the ups and downs in mind, it really depends on what are you doing, so, as Gaby aka G. Petrioli said, " if the processing does not involve jQuery then do not use it".
JQuery is much more convenient than plain javascript. You don't have to worry about cross-browser compatibility (e.g. IE vs. Firefox vs. Chrome). I would recommend this over javascript unless you are want to handle that yourself :)
You can load in the Jquery library, but that might be a little heavy than what you're looking for. Also, you will need to fetch the library from a server, which adds another point of failure (however, if you host this on your own server, then you will have more control).
TLDR: JQuery is convenient. If you have access to it, then you should use it.
Background
I am working on a project that runs in an embedded web browser in a small device with limited resources. The browser itself is a bit dated and has limits to its capabilities (HTML 4.01†, W3C DOM Level 2†, JavaScript 1.4). I have no documentation on the browser, so what I do know comes from trial and error.
The point is to retrieve dynamic content from a server so that only a minimal amount of inflexible code needs to be embedded into the device running the web browser. The browser does not support the XMLHTTPRequest object, so AJAX is out. Working with I do have, I wrote a bit of test code to dynamically insert JavaScript.
† Minor portions of these standards not supported
EDIT
While I cannot actually confirm it, I believe that this site may list the DOM support for the embedded browser because I see "Mozilla/4.0 (compatible; EBSWebC 2.6; Windows NT 5.1)" as the user agent in the server log.
<html>
<head>
</head>
<body onload="init()">
<div id="root"></div>
<script type="text/javascript">
<!--
function init() {
// Add a div element to the page.
var div = document.createElement("div");
div.id = "testDiv";
document.getElementById("root").appendChild(div);
// Set a timeout to insert the JavaScript after 2 seconds.
setTimeout("dynamicJS()", 2000);
}
function dynamicJS() {
...
}
//-->
</script>
</body>
</html>
Method 1
I initially implemented the dynamicJS function using Method 1 and found that while the code executes as expected in Chrome, IE8, and FireFox 3.5, the JavaScript is not actually retrieved by the embedded browser when the element is appended.
function dynamicJS() {
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "js/test.js";
document.getElementById("root").appendChild(js);
}
Method 2
Looking for a work around, I implemented Method 2. This method actually works in the embedded browser as the JavaScript is retrieved and executed, but it does not work in other modern web browsers's I tested against (Chrome, IE8, FireFox 3.5).
function dynamicJS() {
var js= '<script type="text/javascript" src="js/test.js"> </s' + 'cript>';
document.getElementById("testDiv").innerHTML = js;
}
Question
I'm new to JavaScript and web programming in general, so I'm hoping one (or more) of the experts here can shed some light on this for me.
Is there anything technically wrong with Method 2 and if not, why doesn't it work in modern web browsers?
There is nothing technically wrong with method 2 but most modern browsers have very loose HTML parsers that tend to get caught up in the code that you're sending. Specifically they parse the </script> in your JavaScript string literal as an end tag. This manifests itself in two ways:
You'll see an "Unterminated String Literal" error.
All code after the </script> text will be rendered as text on the page.
A common workaround for this problem is to split the </script>. You can do this with the following code. Yes, I know its a hack, but it works around the problem.
function dynamicJS() {
var js= '<script type="text/javascript" src="js/test.js"></s' + 'cript>';
document.getElementById("testDiv").innerHTML = js;
}
Realistically though, you should be able to use your first approach strictly using the DOM APIs. I've found that some browsers can be really picky about loading scripts added by script in that they will only load them if they are placed as a child of the <head> element. This is how the YUILoader works, so I'd be surprised if it didn't work in all browsers.
Here's an example, you'll want to check this to make sure that it works in all browsers, and add some error checking around the assumption that there will be a <head> element but it give you the general idea.
if (!document.getElementsByTagName) {
document.getElementsByTagName = function(name) {
var nodes = [];
var queue = [document.documentElement];
while (queue.length > 0) {
var node = queue.shift();
if (node.tagName && node.tagName.toLowerCase() === name) {
nodes.push(node);
}
if (node.childNodes && node.childNodes.length > 0) {
for (var i=0; i<node.childNodes.length; i++) {
if (node.childNodes[i].nodeType === 1 /* element */) {
queue.push(node.childNodes[i]);
}
}
}
}
return nodes;
};
}
function dynamicJS() {
var js = document.createElement("script");
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', 'js/test.js');
var head = document.getElementsByTagName('head')[0];
head.appendChild(js);
}
The innerHTML property has not yet actually been standardized, though all modern browsers support it, and the draft standard of HTML5 includes a definition of how it should work. According to the HTML5 specification:
When inserted using the document.write() method, script elements execute (typically synchronously), but when inserted using innerHTML and outerHTML attributes, they do not execute at all.
innerHTML was first introduced in Microsoft Internet Explorer 4, and due to its popularity among authors, has been adopted by all of the other browsers, which is what led to its inclusion in HTML5. So, let's check Microsoft's documentation:
When using innerHTML to insert script, you must include the DEFER attribute in the script element.
So apparently, in IE you can get scripts inserted via innerHTML to execute, but only if you add a defer attribute (I do not have IE in front of me to test this). defer is another feature that was first added to IE; it was included in HTML 4.01, but not picked up by any of the other browsers for quite a while. HTML5 includes a much more detailed description of how <script defer> should work, though it appears to be slightly incompatible with how it works in IE, as it does not allow execution of scripts added via innerHTML. The HTML5 definition of <script defer> appears to be implemented in Firefox 3.5 and Safari 4.
In summary, innerHTML hasn't really been standardized yet, but instead simply implemented by all of the browser vendors in slightly different ways. In IE, the original implementation, it didn't support execution of scripts except with a defer attribute, and defer hasn't been supported in other browsers until just recently, and so the other browsers simply don't support execution of scripts added using innerHTML. This behavior is what HTML5 is standardizing on, so unless Microsoft objects, is probably going to be what goes into the standard.
It sounds like the browser you are working with didn't do as good a job of implementing a compatible innerHTML, as it executes scripts added using innerHTML no matter what. This is unsurprising, as the behavior isn't standardized and so needs to be either reverse engineered or gleaned from reading the documentation of other browsers (which may not have included this fact in the past). One of the main goals of HTML5 is to actually write down all of these unwritten assumptions and undocumented behaviors, so that in the future, someone implementing a browser can do so without being misled by a spec that doesn't match reality, or without having to do the effort of reverse engineering the existing browsers.
It looks to me that you may have to use Method 2 on your embedded browser, and Method 1 if you want to run on the common desktop browsers. It would probably be a good idea to try Method 1 first, and fall back to Method 2 if that does not work, and then error out (or silently fail, depending on your needs) if neither one works.
A long shot but does the embedded browser support iframes?
And if so would you be able to use that to load in whatever additional JS you needed and access it via the iframe?