jQuery script not working as excepted - javascript

I have a jQuery script that should open images full size when they are clicked.
$('img').click( function() {
var src = $(this).attr('src');
window.location.href=src;
});
However, when images are clicked they don't open as expected. Does anyone have any idea why? Any help appreciated :)

Your code seems to work just fine here: http://jsfiddle.net/jfriend00/n6n5R/
So, there is likely some issue with your event handler getting installed properly. Here are things to check:
Are you waiting for the document to load before installing your event handlers?
Are your images dynamically loaded?
Do you have any script errors that are preventing your event handler from running?
For item #1, I would suggest this:
$(document).ready(function() {
$("img").click(function() {
window.location.href = this.src;
});
});
For item #2, you may want to use delegated event handling instead:
$(document).ready(function() {
$(document).on("click", "img", function() {
window.location.href = this.src;
});
});
For item #3, you need to check your browser error console or the debug console and see what script errors might be causing your scripts to stop executing prematurely.
P.S. You may also note that I've simplified your code a bit by just using this.src rather than $(this).attr("src"). No point in using jQuery when it is just longer and slower.

Make sure Jquery is loaded before your script .Also if images are loaded dynamically use this script:
$('body').on('click','img', function() {
var src = $(this).attr('src');
window.location.href=src;
});

Have your images absolute path names? if not, you want to do something like this:
window.location.href = window.location.href.substr(0, window.location.href.lastIndexOf('/')) + src;

Related

Why does DOM appendChild() fire on('load', ...) but jQuery append() does not?

I have the following to snippets of code:
$(document).ready(function() {
document.head.appendChild(
$('<script />').attr('src', 'source.js').on('load', function() {
...
})[0]
);
});
This will fire the load handler.
Whereas using the normal jQuery append():
$(document).ready(function() {
$('head').append(
$('<script />').attr('src', 'source.js').on('load', function() {
...
})
);
});
This will not fire the load hander.
What am I missing: why does jQuery append() not work?
Is using document.head.appendChild() a bad idea?
NOTE: I can't use $.getScript(). The code will run on a local file system and chrome throws cross site script errors.
Update
Some people had trouble reading the compact style, so I used extra line feeds to clarify which objects where calling which methods. I also made it explicit that my code is inside a $(document).ready block.
Solution
In the end I went with:
$(document).ready(function() {
$('head')[0].appendChild(
$('<script />').attr('src', 'source.js').on('load', function() {
…
})[0]
);
});
I think #istos was right in that something in domManip is breaking load.
jQuery is doing some funny business in its DOM manipulation code. If you look at jQuery's source, you'll see that it uses a method called domManip() inside the append() method.
This domManip() method creates a document fragment (it looks like the node is first appended to a "safe" fragment) and has a lot of checks and conditions regarding scripts. I'm not sure why it uses a document fragment or why all the checks about scripts exist but using the native appendChild() instead of jQuery's append() method fires the event successfully. Here is the code:
Live JSBin: http://jsbin.com/qubuyariba/1/edit
var url = 'http://d3js.org/d3.v3.min.js';
var s = document.createElement('script');
s.src = url;
s.async = true;
$(s).on('load', function(e) {
console.log(!!window.d3); // d3 exists
$(document.body).append('<h1>Load fired!</h1>');
});
$('head').get(0).appendChild(s);
Update:
appendChild() is a well supported method and there is absolutely no reason not to use it in this case.
Maybe the problem is when you choose DOM appendChild, actually you called the function is document.on('load',function(){});, however when you choose jQuery append(), your code is $('head').on('load', function(){}).
The document and head are different.
You can type the code below:
$(document).find('head').append($('<script />').attr('src', 'source.js').end().on('load', function() {
...
}));
You should probably make sure that the jquery append is fired when the document is ready. It could be that head is not actually in the dom when the append fires.
you don't have to ditch jquery completely, you could use zeptojs. Secondly, I couldn't find out how and why exactly this behavior is happening. Even though i felt answer was to be found in links below. So far i can tell that if you insert element before definig src element then load won't fire.
But for manual insertion it doesn't matter. (????)
However, what i was able to discover is that if you use appendTo it works.
Code :http://jsfiddle.net/techsin/tngxnkk7/
var $ele = $('<script />').attr('src', link).load(function(){ abc(); }) ).appendTo('head');
New Info: As is understood adding script tag to dom with src attribute on it, initiates the download process of script mentioned in src. Manual insertion causes page to load external script, using append or appendTo causes jquery to initiate downloading of external js file. But event is attached using jquery and jquery initiates download then event won't fire. But if it's the page itself initiates the download then it does. Even if event is added manually, without jquery, adding via jquery to dom won't make it fire.
Links in which i think should be the answer...
Append Vs AppendChild JQuery
http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/
http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/
https://github.com/jquery/jquery/blob/master/src/manipulation.js#L477-523
http://ejohn.org/blog/dom-documentfragments/

Asynchronous image loading

I'm creating a Hangman game for a project. I have most of the functionality I need, however I am having one issue. When the last incorrect guess is made, it displays the alert box telling you you've lost, before loading the image. I want the image to load first and then the alert box.
I realize that the issue is with the way the DOM loads elements and that I should create a callback function in jQuery.
This is the line in my code that changes the image, and it works fine until it gets to the last one.
document.getElementById("gallows").src = displayGallows[incorrectGuesses - 1];
I have tried using a Jquery function to get this working but my knowledge of jQuery is pretty much non-existent.
var img = $("gallows");
img.load(function() {
alert("Unlucky, you lost. Better luck next time!");
});
img.src = displayGallows[incorrectGuesses - 1];
I have compared this to many posts I have found online and to my untrained eye, it looks OK. When I was troubleshooting I did realize that the img.src was assigned the correct value but the image didn't appear on my page or didn't fire the alert box.
This led me to believe that it may be an issue with linking to the jquery.js file. I have an HTML page that references the jQuery file in it's head tag.
<head>
<title>Hangman</title>
<link rel="stylesheet" href="base.css"/>
<script src="jquery.js"></script>
<script src="hangman.js"></script>
<script src="home.js"></script>
</head>
The file I am writing my JavaScript and jQuery from is the hangman.js file.
Do I also need to refer to the jquery.js file from the hangman.js file? While reading up on this I found that I may have to do this, so I've tried this:
///<reference path="jquery.js" />
and this
var jq = document.createElement('script');
jq.src = 'jquery.js';
document.getElementsByTagName('head')[0].appendChild(jq);
but to no avail, though I don't really understand the second one, as I found these examples on the internet.
Note that in my home.js file I have simple a simple jQuery function to em-bold the text on a button when you mouseover it and this works OK.
If anyone could help me out or point me in the right direction that would be great.
Your best bet here is probably not to use alert at all; instead, use modern techniques like an absolutely-positioned, nicely-styled div to show your message. Showing that won't get in the way of the browser showing the image once it arrives, whereas alert basically brings the browser to a screeching halt until the user clicks the alert away.
But if you want to use alert:
Your concept of waiting for the load event from the image is fine, but you may want to yield back to the browser ever-so-briefly afterward to give it a chance to display the image.
Not using jQuery, as you don't appear to be using it otherwise:
var img = document.getElementById("gallows");
img.onload = img.onerror = function() {
setTimeout(function() {
alert(/*...*/);
}, 30); // 30ms = virtually imperceptible to humans
};
img.src = displayGallows[incorrectGuesses - 1];
That waits for the load or error event from the image, then yields back to the browser for 30ms before showing the alert.
But if you pre-cache the images, you can make the load event fire almost instantaneously. Most browsers will download an image even if it's not being shown, so if you add
<img src="/path/to/incorrect/guess.png" style="display: none">
...to your page for each of the incorrect guess images, then when you assign the same URL to your #gallows image, since the browser has it in cache, it will load almost instantly. Here's an example using your gravatar and a 30ms delay after load: http://jsbin.com/fazera/1
Firstly, to get an object by ID in jQuery, you have to use #.
var img = $("#gallows");
You can not use src or other "vanilla" properties directly on a jQuery object. You can, however do any of these:
Get the actual element from the jQuery object.
var img = $("#gallows");
img.load(function() { ... }
img[0].src = "image.jpg"; // First element in jQuery object
Use the jQuery method attr (recommended).
var img = $("#gallows");
img.load(function() { ... }
img.attr("src", "image.jpg");
Get the element just like you do now.
var img = document.getElementById("gallows");
img.onload = function() { ... }
img.src = "image.jpg";
please make sure that you have your jQuery code that's within the HEAD tag, inside:
$( document ).ready(function() { ...your jQuery here... });
More info: Using jQuery, $( document ).ready()
Your question: "Do I also need to refer to the jquery.js file from the hangman.js file?"
No, but place <script src="hangman.js"></script> tag in the header after referring to your jQuery file:
<head>
<script src="jquery_version_that_you_are_using.js"></script>
<script src="hangman.js"></script>
<script>
$( document ).ready(function() {
//Your jQuery code here
});
</script>
</head>

Check if image can be loaded

I have a page with lots of images on it. My images are loaded from an external server. Usually this server it's loading tooooooooo slow, so my page stay loading until the external server starts running again. I want to put a blank image loaded from mine when the external server is down.
Is there any method to do something like this?
if ($("img").load=false) {
$("img").src="cantload.png";
}
Thank you so much, in advance!
If you're using jquery, and this piece of code happens before the binding of the image.
$("img").error(function() {
alert("Could not load image");
});
If not, then you could do something like this, which will always work, but will need to be on each image:
<img src="image.gif" onerror="alert('Could not load image.')">
If you want to activate this function after the elements are already in the DOM, you can use something like this.
var defaultSource = 'cantload.png';
$('img').each(function() {
var originalSource = $(this).attr('src');
$(this)
.attr('src', defaultSource)
.error(function(){
$(this).attr('src', defaultSource );
})
.attr('src', originalSource);
});
The above code would bind the inner function to handle the images' loading errors, and then make them all reload. The pictures that are already reloaded won't be actually reloaded again, but those with the errors will trigger the error handler and change the source attribute into cantload.png
jsFiddle Demo

Small riddle: Why this isn't working on Chrome?

Any ideas on why the following code perfectly 'posts' when using FF (I can see the DB updated) but fails on Chrome?
$("a").click(function() {
$.post("ajax/update_count.php", {site: 'http://mysite.com'});
});
Tip: jQuery version is jquery-1.4.3.min.js
Update
The issue seems to be that when the link is clicked, a new page is loaded, which seems to be stopping the post in Chrome... Is that a possible explanation? If so, what can I do?
You need to prevent the default behavior of an <a>. Use this:
$("a").click(function (e) {
e.preventDefault();
// Your code
});
or, if you actually want the link to load the new page, you could try:
$("a").click(function (e) {
e.preventDefault();
var href = this.href;
// Might want to put a "loading" spinner on the page here
$.post("whatever", {}, function () {
window.location.href = href;
});
});
Might have to change it a little - maybe use $(this).attr("href") or $(this).prop("href"), not this.href...the differences those evaluate to may or may not work with window.location.href (I'm sure both do).

Javascript appending onload to a popup window

I'm trying to append an onload event to a popup window in the following manner:
var explorerWindow = window.open(PARAMS...);
explorerWindow.onload = function() {window.opener.unlockObj(id);}
The idea is to make the button that generates the popup window readonly, making it usable again once the popup window has loaded all of its contents. However, the event doesn't seem to be firing at all. I even changed it to the following and got nothing:
explorerWindow.onload = function() {alert("bloop");}
Is there something terribly wrong with my syntax or am I missing something else entirely? Also, I'm using JQuery if there are any appropriate gems there that will help in this situation. I tried the following with similar results, but I'm not so sure I got the call right:
$(explorerWindow).load(function() {alert("bloop");});
Any help is greatly appreciated.
This won't work in all browsers. I'd suggest putting the onload handler in the document loaded into the new window and have that call out to the original page:
window.onload = function() {
opener.doStuff();
}
I actually managed to get it working in the browsers I have to support with the following:
explorerWindow.onload = new function() { explorerWindow.opener.unlockObj(id); }
Thanks for the reply though Tim.

Categories