Javascript replace( ) function running more than once on the same image - javascript

I'm running a Javascript replace function to replace standard images with class="replace-2x"on my jQuery Mobile site with Retina-quality images if the user is on a mobile device with Retina display. For example, on a Retina device, logo.png will be replaced with logo#2x.png. The JS function is here:
function highdpi_init() {
$(".replace-2x").each(function () {
var src = $(this).attr("src");
$(this).attr("src", src.replace(".png", "#2x.png").replace(".jpg", "#2x.jpg"));
});
}
$(".page").live('pageinit',function(event){
highdpi_init();
});
I'm now running into an issue where the replace function is running more than once. So for example, it replaces logo.png with logo#2x.png as the page is loading, but then as the page continues to load, it KEEPS replacing .png with #2x.png in the img src over and over so that the image tag ends up looking like this:
<img src="mobile/images/logo#2x#2x#2x#2x#2x#2x#2x#2x#2x#2x#2x.png" class="replace-2x" alt="logo" width="200">
How can I prevent this from replacing on a single img element more than once? Keep in mind, I will have multiple images on the same page, so the function will need to apply to all images, but only one time each.

The problem is surely that your 'pageinit' event is being called more than once. You can either follow MДΓΓ БДLL's idea (which won't work if images are dynamically added) or you can make your handler smarter so that it doesn't replace the src if it already was replaced
function highdpi_init() {
$(".replace-2x").each(function () {
var $this = $(this);
var src = $this.attr("src");
$this.attr("src", src.replace(".png", "#2x.png").replace(".jpg", "#2x.jpg"));
// Remove the class so it doesn't replace it again
$this.removeClass('replace-2x')
});
}
You don't need JS for this, you could do it in CSS only.
<link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" href="/css/highdpi.css"/>
You could make your images look like
<img src="transparent.gif" class="logo-a" alt="logo" width="200" />
And in highdpi.css you could do
img.logo-a {
background-image: url('file#2x.png')
}
And in lowdpi.css
img.logo-a {
background-image: url('file.png')
}

Using .one() should work since it is just a binding and if you are using Jquery Mobile the way that is suggested it will be just fine. That is unless you are passing back the html from the server. In which case it would be a good idea to add an extra condition to make sure that the src doesn't already have #2x.png before replacing.

There is disappointingly little documentation on pageinit on the offical jQuery Mobile docs. So I'm going to speculate here. It looks like pageinit is used to fire events for when a specific DOM element has finished loading, since it may not have been loaded on the initial page load (deferred until needed). That being said, it may be that adding/altering images to the DOM element in question fires the pageinit again. Could you tag each updated image with something that says, 'hey, I've already been updated to 2x'? Something such as
$.data(targetimg, 'retinafied', true);
And then check for that value before replacing the src?

Related

How can I block images using js only?

I want to block all the images of any web page to lower the page loading time, consider the web page source code is loaded into browser but the documents/files still needed to be downloaded, is there any event to cover this problem?
I think can method must be followed in browsers text only mode.
No. If the src tag is already set the browser will Load the images no matter what. Remove the src tag after it was loaded doesn't change the fact that it was already downloaded.
The only way to avoid this is to set the src tags of imgs by Javascript dynamicly. And therefore not set images if you don't want to.
You can't make the browser not loading images if it's already in the html.
I'm not sure if it solves your problem but maybe you can try this:
<script type="text/javascript">
$(document).ready( function() { $("img").removeAttr("src"); } );
</script>
<div class="image"><img external-src="original.jpg" src="fake.jpg" /></div>
$(window).load(function(){
$('.image img').attr("src", $(this).attr('external-src')).removeAttr('external-src');
});
This will load all the images after whole dom loaded
You can remove the whole img tag
$("img").remove();
or you can just remove the image tag source attribute
$("img").removeAttr("src");
or you can just replace all the image source having shorter loading time
$("img").attr("src",'http://someimage.jpg');

Why is my div not updating when changing its class with JavaScript?

I currently have a div that's used to display and image via CSS.
For example:
HTML
<div id="myDiv" class="play"></div>
CSS
.play{background: url('../img/playIcon_black.png') no-repeat;}
This image appears as it should.
What I'm attempted to do is to change the image by changing the class (via JavaScript).
Example:
CSS
.pause{background: url('../img/pauseIcon_black.png') no-repeat;}
JavaScript
function myFunction() {
myDiv.className = "pause";
}
When I call myFunction() everything seems to work correctly with one exception. Occasionally the image does not update in the browser.
A few things to note:
I'm certain the function is being called correctly. If I put a console.log() statement within the function, it prints when it should. Additionally, if I inspect the element within the browser, the class is in fact changed to .pause
The image changes from the "play icon" to blank once the function is called, BUT upon hovering over the div the images then appears permanently.
This only seems to happen once the page is initially loaded. Meaning, I can only recreate the issue once upon refresh, then everything works correctly after that.
I have attempted to clear my cache but nothing seems to have changed.
(I'm not sure how relevant this is) I'm calling myFunction() via onended attribute of an audio tag.
For example:
<audio onended="myFunction()"></audio>
But I'm not certain if this would affect anything because the function appears to be called correctly.
Any ideas of why this might be happening?
So the issue is that when you change the class, the browser has to fetch the new image, which takes time. One way to fix the issue is by using sprites, where both images are actually in one image and you only show a piece of that image at a time.
Another solution is to preload the image and then apply the preloaded image source to your new element like this:
var image = newImage();
image.src = '../img/pauseIcon_black.png';
function myFunction() {
var cssBackground = 'url(' + image.src + ') no-repeat';
myDiv.style.background = cssBackground;
// Optionally with jQuery instead:
// $('#myElementID').css('background', cssBackground);
}
Note that if you call myFunction before the image loads you'll encounter the same error. The difference is that this will load the image when the page is loaded (or more properly, when this JS executes and myFunction is assigned) rather than when myFunction is called. To ensure the image is loaded you can use the onLoad event handler for the image object. For more details on preloading images check out this answer: preload image then change background javascript
You need to get the element id
function myfunction(){
var myDivElem = document.getElementById('myDiv');
myDivElem.className = 'pause';
}
You can use document.getElementById("myDiv").className="";in your function
OK if you don't want use first solution you can use second one:
You can add a class to element using
document.getElementById("myDiv").className +=" n";
Then add a class named .play.n to your css file after class named.play
Then add your image address.
If you want to manipulate the div with id "myDiv". Use it as
document.getElementById('myDiv').class
Sample codesnippet: example snippet

How to prevent an <img> tag from loading its image?

I have the following script which take a string with html information (containing also reference to images).
When I create a DOM element the content for the image is being downloaded by the browser. I would like to know if it is possible to stop this Beauvoir and temporary prevent loading.
I am targeting web-kit and presto browsers.
relativeToAbosluteImgUrls: function(html, absoluteUrl) {
var tempDom = document.createElement('div');
debugger
tempDom.innerHTML = html;
var imgs = tempDom.getElementsByTagName('img'), i = imgs.length;
while (i--) {
var srcRel = imgs[i].getAttribute('src');
imgs[i].setAttribute('src', absoluteUrl + srcRel);
}
return tempDom.innerHTML;
},
Store the src path into an HTML5 data-* attribute such as data-src. Without src being set, the browser will not download any images. When you are ready to download the image, simply get the URL from the data-src attribute and set it as the src attribute
$(function() {
// Only modify the images that have 'data-src' attribute
$('img[data-src]').each(function(){
var src = $(this).data('src');
// modify src however you need to, maybe make
// a function called 'getAbsoluteUrl'
$(this).prop('src', src);
});
});
The approach taken by popular image library, Slimmage, is to wrap your img tags in noscript tags:
<noscript class="img">
<img src="my-image.jpeg" />
</noscript>
Web scrapers and people with JS turned off will see the image as if the noscript wasn't there but other browsers will completely ignore the noscript and img tags.
You can then use JavaScript to do whatever you want with it, for example (using jQuery):
$('noscript.img').replaceWith(function(){
return $(this.innerText).removeAttr('src');
});
I think you should reverse the logic, don't load the images by default and at the moment the image is needed, update it's src attribute to tell browser to start loading.
Or even better way would be to use some jquery lazy image loading plugin like this one:
http://www.appelsiini.net/projects/lazyload
Hope this helps.
To prevent images from being show, you could use this.
$(window).loaded( function() {
$("img").removeAttr("src");
});
It might be tricky and give unexpected results, but it does it.

javascript to cancel image loading

I am looking for a way to cancel image loading using javascript. I've looked at other questions and hiding them is not enough. Also, the rest of the page must load (window.stop() is out of the question).
The page that is being loaded is not under my control, only one thing is guaranteed - the first <script> on the page is my javascript (lightweight - no jquery).
I have tried setting all img sources to nothing, that did not help since the dom is created after the page is parsed, and all browsers have the same behavior - the img is loaded once it is parsed.
Not possible with modern browsers. Even if you alter the src attribute of image tag with JavaScript browsers still insist on loading the images. I know this from developing the Lazy Load plugin.
The only way I can see to stop images loading is to not have an src attribute present in the image itself, and using a custom data-* attribute to hold the location of the image:
<img data-src="http://path.to/image.png" />
Obviously this doesn't gracefully degrade for those (admittedly rare) JavaScript disabled browsers, and therefore requires a noscript fall-back:
<img data-src="http://path.to/image.png" />
<noscript><img src="http://path.to/image.png" /></noscript>
And couple this with a simple function to load the images when you, or your users, are ready for them:
/* simple demo */
function imagePopulate(within, attr) {
within = within && within.nodeType == 1 ? within : document;
attr = attr || 'data-src';
var images = within.getElementsByTagName('img');
for (var i = 0, len = images.length; i < len; i++) {
if (images[i].parentNode.tagName.toLowerCase() !== 'noscript') {
images[i].src = images[i].getAttribute(attr);
}
}
}
document.getElementById('addImages').onclick = function(){
imagePopulate();
};
JS Fiddle demo.
I can't be sure for all browsers, but this seems to work in Chrome (in that there's no attempt, from looking at the network tab of the developer tools, to load the noscript-contained img).
It can be done with webworkers. See the following example:
https://github.com/NathanWalker/ng2-image-lazy-load.
Stopping a web worker cancels the image loading in browser
Recalling the onload event:
window.onload=function(){
imgs = document.getElementsByTagName('img');
for(i = 0; i < imgs.length(); i++){
imgs[i].src = '#';
}
};
If you want to only cancel the loading of the image , you can use sємsєм's solution
but i do not think it will work by using an window onload event .
You will probably need to provide a button to cancel the image load. Also i suggest, instead of setting the src attribute to "#" , you can remove the src attribute itself using
removeAttribute()
[Make sure you disable the cache while testing]
You need a proxy.
Your script can redirect to another server using something like
location.replace('http://yourserver.com/rewrite/php?url='+escape(this.href));
perhaps you tell us why you want to cancel image loading and whose site you are loading on so we can come up with a better solution
If there is nothing on the page other than images, you could try
document.write('<base href="http://yourserver.com/" />');
which will mess with all non-absolute src and hrefs on the page.
UPDATE Horrible hack but perhaps this almost pseudo code (I am off to bed) will do someting
document.write('<script src="jquery.js"></script><div id="myDiv"></div><!-'+'-');
$(function() {
$.get(location.href,function(data) {
$("#myDiv").html(data.replace(/src=/g,'xsrc='));
});
})
The closest you can get to what you maybe want is to have a quickly loaded placeholder image (ie. low resolution version of your image) and a hidden image (eg. {display:none}) in which the large image gets loaded but not displayed. Then in the onload event for the large image swap the images over (eg. display:block for the large image display:none for the smaller). I also use an array (with their url), to reuse any images that have already been opened.
BTW if you open an image in a new webpage when it gets closed then the image loading will be cancelled. So maybe you can do something similar in a webpage using an iframe to display the image.
To close the iframe and therefore unload the image, remove the frame from the DOM
(another advantage is that browsers spawn another process to deal with iframes, so the page won't lock up while the image loads)

Pre Load images to display later on click event jQuery

I have a web page where lots of images called from server using image
scr attribute.
I have created a function like which is triggered by td click.
function GoToStep(stepNo) {
var imgSrc = $("#h1" + stepNo).val();
$(".img_vertical").css("background-image", "url(" + imgSrc + ")");
}
Now the problem is this. For slower connections the images come after some
moment.
Can I pre load images to avoid waiting time when user clicks
td?
I have seen some jquery function to pre load images.
Kindly give some idea how can I achieve it.
Pre-loading an image is equivalent to loading an image but never displaying it. So, you can easily do it like this:
<img src="image.png" alt="" style="display:none;"/>
Now this image will be loaded as soon as the html starts rendering. Whenever you need to use this image as a display or background, just set the address to image.png and it will automatically be fetched from browser's cache.
This can be done using some javascript functions. Quoting from another question.
function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
$('<img/>')[0].src = this;
// Alternatively you could use:
// (new Image()).src = this;
});
}
// Usage:
preload([
'img/imageName.jpg',
'img/anotherOne.jpg',
'img/blahblahblah.jpg'
]);
Explanation of how javascript preloaders work (different question)
[...] The way it works is simply by creating a new Image object and setting
the src of it, the browser is going to go grab the image. We're not
adding this particular image to the browser, but when the time comes
to show the image in the page via whatever method we have setup, the
browser will already have it in its cache and will not go fetch it
again. [...]
So in your case, you should use something like
$(function() {
// Do stuff when DOM is ready
preload([
'img/bg1.jpg',
'img/bg2.jpg',
'img/bg3.jpg'
]);
});

Categories

Resources