Remove images from UIWebview - javascript

In my iPhone app, an epub reader, based off the method here, I have parsed the epub, created the UIWebviews, but I have a slight problem. There are images in the epubs that are larger than the width of the iPhone's screen (320 px.). Is there a Javascript method I can invoke on the UIWebview ([view stringByEvaluatingJavaScriptFromString:SomeJavaScriptString]) and remove those images programatically without changing the epub manually?
UPDATE: Could the issue be that the source file is an xml file and not HTML?

You probably want something like: document.getElementById('id_of_your_image').style.visibility = 'hidden'
UPDATE
To hide all images in a document,
for (i=0; i<document.getElementsByTagName("img").length; i++) {
document.getElementsByTagName("img")[i].style.visibility = 'hidden';
}
should do the trick.

var images = Array.prototype.slice.call(document.getElementsByTagName('IMG'), 0);
var imageCount = images.length;
for (var i = 0; i < imageCount; i++) {
var image = images[i];
image.parentNode.removeChild(image);
}

If you're not dealing with graphs or images where seeing the detail is important why not:
1) write some CSS that sets a max-width on images of 320px or 640px, depending on orientation.... see http://www.thecssninja.com/css/iphone-orientation-css for how to use different css for different orientations.
2) insert that CSS in each HTML file after any other styles or stylesheet links - inside a <style> element added just before the </body> would work.
?
That way images are still visibile but won't extend past a single page width.
As a next step you could wrap images with something like <a href='zoom://x'> where x is the image filename - then in your UIWebViewDelegate' "shouldStartLoadWithRequest" function check to see if request.URL.scheme == "zoom" - if it is you could push a new view containing image x in a zoomable container, like iBooks.

Related

Download background-images of divs before using those divs

I am doing an animation where based on the scroll I change multiple background images of a main div amoled-section. Hence, I am doing this by adding a class whenever the scroll hits a trigger e.g. #amoled-section-frame6.Every time when trigger hits#amoled-section-frame6 it adds a class to amoled-section.on-frame6
.amoled-section.on-frame-6 {
background-image: url("https://image.shutterstock.com/image-photo/portrait-cheerful-male-architect-wearing-260nw-1060056851.jpg");
z-index: 1;
}
It was working all good until I observed that if I have a multiple image change it will require a time to download the image and will create a glitch effect. The problem that I want to resolve is somehow download background-images of divs before using them and in this way, the background image transition will work fine.
I attached in Codepen a link to the full code, however is not working probably because Srollmagic is not that flexible with Codepen. Link below.
https://codepen.io/obsesie/pen/qBZKzGz
I have worked with ScrollMagic.js before and had an issue as same as you have. There are two solutions I prefer.
Embed images with the style of "display: none"
Use javascript to preload those images.
<script type="text/javascript">
<!--//--><![CDATA[//><!--
var images = new Array()
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image()
images[i].src = preload.arguments[i]
}
}
preload(
"http://domain.tld/gallery/image-001.jpg",
"http://domain.tld/gallery/image-002.jpg",
"http://domain.tld/gallery/image-003.jpg"
)
//--><!]]>
</script>
There would be other solutions but I hope this would help.
Also, this link would be useful for you.
https://perishablepress.com/3-ways-preload-images-css-javascript-ajax/#:~:text=JavaScript%20Method%20%232&text=As%20you%20can%20see%2C%20each,as%20many%20images%20as%20necessary.

In Chrome the currentSrc of an img element is sometimes empty. How can I prevent this?

UPDATE:
I just found some more info. It seems that in Chrome, the currentSrc of the image will often be empty, whereas in Firefox, the URL is always correct. Is the JS trying to access currentSrc before it's available? Is there a way to prevent this?
I am creating a Drupal 8 website, and in order to use the responsive images module with a background-image, I came up with the following workaround. The JS function below, setParallaxImage(), takes the currentSrc from the img in the picture element and sets it as the background-image for the outermost div. The img itself is not displayed (display: none in CSS) and is given a dummy image, as I only need it to get the currentSrc. The function is called with onload and onresize.
The code seems to work well in Firefox. When resizing the browser past a breakpoint, the image goes grey for a split second, then loads the image from the proper source. However, with Chrome, when quickly resizing past a breakpoint, the image may become grey and not get displayed at all, that is, background-image: url(). Usually if I resize the window a couple more times, the image will finally appear. Does anyone know why this might be happening? Thank you for reading.
JS
function setParallaxImage() {
const parallaxContainer = document.getElementsByClassName('paragraph--type--parallax-banner-with-text');
for(var i = 0; i < parallaxContainer.length; i++) {
console.log('in setparallax');
var x = parallaxContainer[i];
var parallax = x.getElementsByClassName('field--name-field-parallax-image-top-')[0];
var picture = parallax.getElementsByTagName("picture")[0];
var sourceURL = picture.querySelector('img').currentSrc;
x.setAttribute('style', 'background-image: url(' + sourceURL +')');
var img = picture.getElementsByTagName("img")[0].setAttribute('src', '/sites/default/files/src_images/dummy_image.gif');
}
}
window.onload = setParallaxImage
window.onresize = setParallaxImage;
HTML
<div class='paragraph--type--parallax-banner-with-text'>
<div class='field--name-field-parallax-image-top-'>
<picture>
<!-- several source tags here -->
<img src="will-be-given-dummy-image-in-JS">
</picture>
</div>
</div>
You can use the property "complete" to check, if the image was already loaded. If not, u can use the onload-Event to fire, when the image is available.
if (img.complete) {
console.log(img.currentSrc);
} else {
img.onload = function() {
console.log(img.currentSrc);
}
}

How to cancel a background image from loading

How can you cancel the loading of an image defined by a background-image attribute?
There a few questions that show how to cancel the loading of an <img> tag by setting the src to '' or to a different image (such as this one, answered by Luca Fagioli). But this does not work for background images.
Luca provided a jsfiddle ( jsfiddle.net/nw34gLgt/ ) to demonstrate the <img src="" /> approach to canceling an image load.
But modifying that jsfiddle to use background-image instead clearly shows that the image continues loading, even if:
you do background-image: none (as suggested here)
or background-image: url("web.site/other_image.jpg")
or background-image: url('').
In fact, in my testing on Firefox 54, the background image continues loading even if you do window.stop() or close the tab.
So, is there any way at all to stop loading a background image once it starts?
My use-case for this is client-side, so I can't change the site to not use background images. I am viewing a gallery of many thumbnail images, but the thumbnails are much larger than they need to be. Smaller versions are available so I wanted to replace the large thumbnails with the smaller versions via Greasemonkey to ease the network load on my poor, slow connection. Each entry in the gallery is a <div> with a background-image inside an <a> linking to the full-size image. (using Fotorama).
If you need to target inline styles on the elements, then I think you can run a script near the bottom of the page to do that.
Testing this locally, the original images do not show as loading in the network tab.
var allDivs = document.getElementsByTagName('DIV');
for (var i = 0; i < allDivs.length; i++) {
// check for inline style
var inlineStyle = allDivs[i].getAttribute('style');
// check if background-image is applied inline
if (inlineStyle && inlineStyle.indexOf('background-image') != 1 ) {
allDivs[i].style.backgroundImage = 'url("newImg.jpg")'; // assign new value?
}
}
That is going to grab every div, so hopefully these elements have a class you can use to query first. Then you have a smaller collection to run the above on.
Classes, not inline styles:
If you could target classes, it would look a bit cleaner. You could create a new class and use it.
var els = document.querySelectorAll('.bg-img');
for (var i = 0; i < els.length; i++) {
els[i].classList.remove('bg-img');
els[i].classList.add('no-bg-img');
}

swapping src to lazy

Not happy with existing lazy loading plugins (they are so complex that I can't even understand the codes in them), I thought I can create a simple, easy to understand script that lazy loads images.
My idea was simple. Start out with a following (deformed) img tag.
<img lazy="http://lorempixel.com/400/200"/>
Using javascript, swap out the word "lazy" with "src" when the page is being scrolled up or down.
function hackyaFunction_lazy() {
[].forEach.call(document.querySelectorAll('img[lazy]'), function(img) {
img.setAttribute('src', img.getAttribute('lazy'));
img.onload = function() {
var imgs = document.querySelectorAll('[lazy]');
for (i = 0; i < imgs.length; i++) {
var o = imgs[i],
lazy = o.getAttribute('lazy');
if (o.y <= (window.screen.height + window.scrollY + 50) && o.y >= (window.scrollY - 50)) {
o.setAttribute('src', lazy);
o.removeAttribute('lazy');
}
}
}
window.onload = window.onscroll = hackyaFunction_lazy;
});
}
I know enough of javascript to hack together bits & pieces to make something that works. And the above code kinda works.
On my console, I see that the word "lazy" has been successfully replaced with "src" for images that are in viewport.
However, images that are outside of the viewport, this is what I see.
<img lazy="http://lorempixel.com/400/200/sports/Dummy-Text" src="http://lorempixel.com/400/200/sports/Dummy-Text">
So I have half working code & this is the best that I can do.
I should have just used any one of the plugins that are available out there; just wanted to see if I can create something simple & easy.
Now that I am so close to making this thing work, I am reluctant to give it up.
Any help will be greatly appreciated.
I wanted to put together the whole thing (html & js) on jsfiddle but images fail to show on jsfiddle. Don't know why.
The code works (as described) on local environment.
The first line within the .forEach() changes the src of the current image without removing lazy and without testing whether it is in view or not, so after the .forEach() has run that line for every image they will all have been updated. That's why when you inspect the elements with the dev tools many of the images have both a src and lazy attribute.
If the idea is to only set the src once the image scrolls into view, and for any images that are already in view on page load, you can do it by keeping just the inner for loop of your function:
function hackyaFunction_lazy() {
var imgs = document.querySelectorAll('[lazy]');
for (i = 0; i < imgs.length; i++) {
var o = imgs[i];
if (o.y <= (window.screen.height + window.scrollY + 50) && o.y >= (window.scrollY - 50)) {
o.src = o.getAttribute('lazy');
o.removeAttribute('lazy');
}
}
}
window.onload = window.onscroll = hackyaFunction_lazy;
This works because on each scroll it first selects whatever elements still have the lazy attribute, then for those elements it tests whether they're in view and if so it sets their src and removes the lazy. Elements that have not yet been scrolled into view are not updated.
See it working here: https://jsfiddle.net/vb779g7v/2/
Edit/P. S. Note that your if test checking if the element is in view isn't right, because screen.height gives, as the name suggests, the height of the whole screen, not the height of the client area within the browser. But that's not really central to your question, so I'll leave fixing that as an exercise for the reader...

Improve image load time

I have a few img tags whose src is changed onmouseover. This takes an inordinate amount of time to load. How can I improve the load time? The images are basically just different icons.
You can do a few things.
1) CSS Sprites is probably the preferred method.
2) You can load the images in a div and set that div to display none, making it so the images are already loaded so on mouseover they'll be there instantly.
Also here's a link on how to PreLoad images with CSS
There are a few ways to do it, the ideal solution in your case would be to use CSS sprites considering they're icons. However, depending on the situation sometimes sprites aren't ideal.
Here's one solution using JavaScript to preload images:
var images = new Array();
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image();
images[i].src = preload.arguments[i];
}
}
preload(
'http://image-1.jpg',
'http://image-2.jpg',
'http://image-3.jpg'
);
What you're trying to do is achieve a rollover. It is strange that you'd experience a very long delay in this process. Usually, if the images aren't stored in some remote location, they're pretty fast.
Look at this article for some guidance
Other things you could try:
- sprites in css
- you could use two overlapping divs and hide one and unhide the other and vice versa

Categories