Force image to reload in Javascript on Chrome? - javascript

I have two totally separate images called lock-icon.png and lock-unlock-icon.png. On a certain event, I change an image's source in Javascript with
document.getElementById("element").src = "/images/lock-unlock-icon.png";
This always works immediately on Firefox, but because I'm displaying a live HD video stream on the page that requires WebGL hardware acceleration, I need to use Chrome.
It sometimes works on Chrome, but pretty much never immediately; it seems like a random delay of at least a few seconds, at most never. If I examine the current "image location" of the icon after it should've changed, the url is the new, correct URL (which is obviously expected, because it's just querying the src property of the element).
What else should I be doing to force this image to reload in Chrome?

Load both images in separate divs, then just set display:inline on the currently viewable one, and display:none on the other. Then you can just toggle the two images by changing the CSS display property.

Related

Video, memory management problems in Internet Explorer and Edge from many videos on page causing them to display dark/black and/or not play

We have a page that contains 77 or so video thumbnails. When a video thumbnail is hovered over, video starts playing within the thumbnail space.
A problem occurs after many (8 to 60 depending on the system/browser) of them get hovered over. The video starts playing incorrectly, or not playing. Basically the flat/redundant areas turn all dark. In Edge, this corrects itself after a second or two, but for our client this is very undesirable behavior.
We made an improvement by pausing each video on mouse out by calling pause(), removing the src attribute, and then calling load() on the element with an empty src attribute, like so:
function pauseVideo(e) {
$('video', this).get(0).pause();
$('video', this).get(0).removeAttribute('src');
$('video', this).get(0).load();
}
This clears up some memory, but the issue still occurs, though more of the videos can play before the problem becomes apparent.
I does appear to have something to do with memory, and exposes what appears to us to be a memory leak within the Microsoft browsers. Each video increases memory usage, and the memory never gets cleared, as it seems to in Chrome and Firefox. The problem usually occurs when memory usage approaches somewhere between 600mb to 1gb (depending on system) in the task manager. (Chrome always sits around ~500-550 megabytes.
Firefox sits around ~700-800 megabytes.)
We noticed some variance on when the behavior starts to occur that depends on video cards, but the issue always become present at some point.
All of these videos are showed in multiple places on the page. So one thing I was wondering was if it is possible to share video memory between elements.
There are a couple other issues that may be related. In IE the videos go completely black, and their dimensions change onscreen which can change the page layout.
Here is a related issue, but it is not a duplicate, as it doesn't not provide a question or solution about having to facilitate 80 or so videos on one page: How to properly unload/destroy a VIDEO element
We're testing on IE version 11.228.17134.0 and Edge version 42.17134.1.0, both currently the latest.
The desired functionality originally was for the videos to pause on the frame when the user moused off the video, but right now appears we wont be able to do that if we have to unload the video.
I will be adding more information about this issue throughout the day as it becomes available.
Our team has a script that detects if DOM elements are within the viewable area on the page, e.i. not scrolled above the top or below the bottom. As the user scrolls, the script adds/removes a class, and dispatches custom events for each element that has the behavior added. I was able to leverage this system to pause, remove, and dispose (garbage collect) video elements that are not in view, and then, repopulate them as they come back into view, with the original properties stored in an array of objects associated with each video/thumbnail.
This disposes the video. The function must be called with .call(), like: disposeVideo.call(videoElement);
var disposeVideo = function () {
this.pause();
delete(this);
$(this).remove();
}
It's odd that though delete(this) is a hack, and shouldn't work in any browser, it appears to work in all browsers, according to comments I've read around this issue, and my findings in IE/Edge.
On IE (not Edge) this has a side effect of slowing down page scrolling. This is caused by the our in-view checking applied to 80 items on the page, or if it is to do with re-downloading posters (thumbnail images) and video, because it does appear to not be effectively caching these assets to be immediately (re)available to the renderer.
Another side effect (also in IE) related to the above, is that as you scroll the videos appear blank until assets are re-downloaded. We're opting to use images layered behind the videos in favor of using the poster attribute for the videos elements that get removed. This way there will never be blank video thumbnails onscreen.
Update: It is possible that having two or more video elements onscreen can cause the problem. We resorted to only showing one (which worked 100%) but did not try to determine a likely maximum number of video elements.

Chrome keeps requesting image specified in css sprite

We have a simple css sprite with multiple images that are used for different states of buttons and displaying some rich texts eg. "You matched IMG IMG IMG".
.cssinfo_btn_Play_down, .cssinfo_btn_Play_hover, .cssinfo_btn_Play_normal{
background-image: url('pack.png');
background-repeat: no-repeat;}
.cssinfo_btn_Play_down{width:311px;height:107px;background-position:-1569px -664px}
.cssinfo_btn_Play_hover{width:311px;height:107px;background-position:-859px -544px}
.cssinfo_btn_Play_normal{width:311px;height:107px;background-position:-1181px -560px}
Button
<div id="btn-play" ng-class="{'cssinfo_btn_Play_normal': $ctrl.closeState === 1, 'cssinfo_btn_Play_hover': $ctrl.closeState === 2, 'cssinfo_btn_Play_down': $ctrl.closeState === 3}" class="cssinfo_btn_Play_normal" style="opacity: 1;"></div>
The wierd thing is that each time style using css sprite is applied, the source image is requested again. Since the image is already loaded, chrome correctly detects that and loads it from memory so there is no network traffic. While this is fairly quick operation, we do notice a small drop in performance. We also tested on Firefox an there are no additional request after initial load.
Repeated requests
If we untick background-image in element inspector and tick it back everything works as it should and no additional request are performed.
It seems that the moment css file is edited in browser (through inspector or sources) Chrome correctly updates img lookup table.
For buttons we can create workaround with all states precreated and just changing their visibility, but for texts there are simply to many possible combinations.
Any ideas/suggestions why this is happening in Chrome and how to avoid it?

Flickering Images despite preload

I am trying to simulate a video by switching image-frames via javascript. This works perfectly in Chrome while in Firefox (and IE/Edge) the background is shown while updating the frame. This occurs only the first time the image-source is rendered. It seems like the images are not in cache, however the network console shows that they get preloaded correctly.
The way the images are being replaced doesn't seem to matter. I tried changing the source from images/divs as well as controlling them via display, visibility, opacity and even by rearranging the z-index. The way I apply the css to it via jQuery (hide/show, animate, css) also seems to be indifferent. It doesn't even matter if other visible frames are "below" the current frame, it always flashes the background.
I managed to recreate the error:
https://jsfiddle.net/kL54ckLp/

Dynamically resizing image with JS onload event is delayed in Firefox

Ok, so I want to resize a number of images of varying size to 50% of their native size using the following JS:
onload="this.width>>=1;this.onload=null;
This works well in most browsers, except in Firefox whereby it appears to load in full size first before resizing after approximately a second.
What can I do to ensure that the image is resized as soon as the user sees the image?
If the native size of the images cannot be foreknown, then I would add some more attributes to my images. One way is this:
<img onload="this.width>>=1;this.onload=null;this.style.visibility='visible'" style="visibility:hidden">
You can play around with different css properties, like display:none or width:0 until Firefox does what you intend.
Another approach is to use background image instead. But I need more information about your situation to provide an answer with background-image property

Why is image preloading ineffective?

My CMS project has a stylish web 2.0 login screen that fades over the screen using javascript. How come that even though I have made 120% sure that images are preloaded (I used the resource monitor in development tools) they still take a second to show up when my login screen appears. It completely destroys the fanciness! Take a look:
http://www.dahwan.info/Melior (link broken)
When you click login, the screen is supposed to fade to dark using a 75% alpha 1px png image. Even though the image is preloaded, it doesn't show up until after the animation is done. However, if you click cancel and log in again, the animation flows smoothly and perfectly.
Can anyone think of a solution to this problem? I'm having it with the rest of my CMS' GUI as well. It's like there was no image preloading what so ever.
Thanks for answers
EDIT: Ah yes, I'm currently developing this CMS for Google Chrome 5.0.375.99, adding multi browser compatibility later. Sorry for leaving that out
I have come up with a workaround to my problem. I have now tested this in three browsers on two different computers with perfect results. In short, in my image preloading function in javascript, i added each of the images into the DOM in an invisible Div tag.
$('#img_preload').append($('<img />').attr('src', img.src));
The images now being added to the Dom at page load, and according to my theory resting in the memory of my low-end computers, they appears instantly when my CMS needs them.
Thanks for your comments :)
A useful information about this problem:
The Codemonkey solution works because, by putting the images in a hidden div, the browser have to keep those images in memory and ready for a possible change of div's visibility. If the user needs to change de visibility of div from hidden to block, it has to be done instantly. This is why just load all images into an array doesn't work properly.
You could also just preload them into an array. Your problem might be caused by what is known as "garbage collection". This is where the browser looks for objects that are consuming memory which no longer have an instance on the screen and are not being referenced by anything else in memory.
If you preload images into your web age, they should be loaded into the cache, though. So, they should still re-appear when referenced again. However, images can also disappear if the cache expiration is not set for a long enough length of time for these types of files.
Your problem could also be browser-specific.... I have found that it is always best to create an "anchor" for pre-loaded content by placing them into an image array and then using the array to call up the images when needed instead of the image URL(URI).
Here is a quick-and-dirty article that covers this topic.
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5214317.html
The UI thread can only manage one task at a time -- it will either execute javascript or update the UI. If there is a lot of javascript parsing/executing before the code that preloads the image, that might be causing the delay.
Another suggestion is to disable clickability on the login link until after the image has been detected on the page.
To do so is fairly straightforward:
function disableBtn(el){
var btn = document.getElementById(el);
var btnId = btn.id;
btn.disabled = true;
}
To re-enable, set btn.disabled = false (after detecting that your image has been added to the DOM).

Categories