jQuery method .width() was used to get the width of the generated element as:
html:
<div class='row-fluid' id='photo-preview'></div>
javascript:
for(i = 0;i < 4;i++){
var imageSpan = "<div class='span3' id='span_" + i + "'><img src='" + images[i] +"'></div>"
$('#photo-preview').append(imageSpan);
var w = $('#span_' + i).width();
console.log(w);
}
But it got the incorrect value of width. It was the value of percentage instead of pixel. E.g, w should be 400 (400px) but the js got 80 (80%).
I thought the problem may be because the element was dynamically generated. In the console I can got the right value with .width() when all the elements were loaded.
Any ideas to work around with it?
You have to wait for the load event of the image before you can get the correct height.
var img = '<img src="img_path.jpg">';
$(img)
.load(function() {
console.log("width", $(this).width());
})
.appendTo('#photo-preview');
Edit: To match with your example :
html:
<div class='row-fluid' id='photo-preview'></div>
javascript:
for(i = 0;i < 4;i++){
var img = "<img src='" + images[i] +"'>";
$(img)
.load(function() {
console.log("width", $(this).width());
})
.appendTo("<div class='row-fluid' id='photo-preview'>")
.appendTo('#photo-preview');
}
Try using offsetWidth
I.E.
var w = $('#span_' + i).offsetWidth;
console.log(w);
Here's a really silly fiddle I made. I set the width to 80%. If you go to the console, you should see the pixel width (448 px)
http://jsfiddle.net/bwm5s/
Related
Context
I've used the "Intersection Observer API" to build an infinite scroll image gallery. Basically this API allows me to load more items when a certain dummy DOM element enters the viewport.
Prototype
Currently the prototype is implemented for an “iPhone X” (375x812) mobile device only. See: http://urbexco-acceptance.droppages.com/min_rep_ex_working (use Chrome DevTools 'inspect' device toolbar to select the right resolution). The image gallery is generated based on 57 items in the "database". When scrolling down, first 15 elements are loaded, then 15 more elements are loaded, then another 15 elements are loaded into the DOM, then another 10 elements are loaded, and finally 2 elements are loaded. When there are still more than 15 items left to be loaded, they are added using the following logic:
function addItems(n){
// Append new items to .items-wrapper
var items = document.querySelector('.items-wrapper');
for (var i = 0; i < n; i++) {
var url = 'https://img01.ztat.net/article/spp-media-p1/09742e38c25b3e1d9716e02f8e76e87d/89fc0bda6a2c446a8e9e0d8adbc9a4fe.jpg';
width = 170.5;
height = 246;
var newDiv = document.createElement('div');
newDiv.classList.add('item');
items.appendChild(newDiv);
newDiv.innerHTML = "<img src=" + '"' + url + '"' + "width=" + '"' + width + '"' + "height=" + height + "/>";
}
}
Minimal Working Example (no mobile view possible)
https://jsfiddle.net/9jqgzymo/
Objective
Since image width and height are currently hardcoded, I am now trying to assign width and height dynamically based on the image url. I try to achieve this using the getMeta() function:
function addItems(n){
// Append new items to .items-wrapper
var items = document.querySelector('.items-wrapper');
for (var i = 0; i < n; i++) {
var url = 'https://img01.ztat.net/article/spp-media-p1/09742e38c25b3e1d9716e02f8e76e87d/89fc0bda6a2c446a8e9e0d8adbc9a4fe.jpg';
getMeta(url);
}
}
function getMeta(url){
var img = new Image();
img.onload = function(){
res = calculateAspectRatioFit(this.width, this.height, 170.5, 246)
var newDiv = document.createElement('div');
newDiv.classList.add('item');
var items = document.querySelector('.items-wrapper');
items.appendChild(newDiv);
newDiv.innerHTML = "<img src=" + '"' + url + '"' + "width=" + '"' + res.width + '"' + "height=" + res.height + "/>";
};
img.src = url;
}
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return { width: srcWidth*ratio, height: srcHeight*ratio };
}
Challenge
When implementing it this way, I see that - on initiation - already 30 items from the "database" where added to the DOM. Sometimes even all of them? Currently the non-working prototype is implemented for an “iPhone X” (375x812) mobile device only. See: http://urbexco-acceptance.droppages.com/min_rep_ex_not_working (use Chrome DevTools 'inspect' device toolbar to select the right resolution). For a minimal working example, see: https://jsfiddle.net/k3p20qno/
Key question
What is the reason that with my new implementation, on initiation, already 30 or more items are added to the DOM? How can I fix it?
Well the problem lies in here :
function getMeta(url){
var img = new Image();
img.onload = function(){
res = calculateAspectRatioFit(this.width, this.height, 170.5, 246)
var newDiv = document.createElement('div');
newDiv.classList.add('item');
var items = document.querySelector('.items-wrapper');
items.appendChild(newDiv);
newDiv.innerHTML = "<img src=" + '"' + url + '"' + "width=" + '"' + res.width + '"' + "height=" + res.height + "/>";
};
img.src = url;
}
Above code does an async operation with onload event. So it doesn't wait to image to be loaded.
If you turn this into a function that returns a promise you will get the result that you expect. And you should await where you call the function. That way when you add the intersection element it will add it as the last element of the items wrapper. If you don't await it will be added as the first element because the loading of the images will be async and will happen later.
function getMeta(url){
var img = new Image();
const p = new Promise(resolve =>{
img.onload = function(){
console.log( this.width+' '+ this.height );
res = calculateAspectRatioFit(this.width, this.height, 170.5, 246)
var newDiv = document.createElement('div');
newDiv.classList.add('item');
var items = document.querySelector('.items-wrapper');
items.appendChild(newDiv);
newDiv.innerHTML = "<img src=" + '"' + url + '"' + "width=" + '"' + res.width + '"' + "height=" + res.height + "/>";
resolve()
};
})
img.src = url;
return p;
}
Fiddle
Edit: Put the resolve() in the right position which is inside the load function
I have this function to print the image dimensions of all <img> having the attribute [proto].
When I try the function with this each method, it only returns a function.
What is the mistake?
function size(){
var $img = $('img[proto]');
$($img).each(function(){
var height = $(this).height;
var width = $(this).width;
$(this).parent().find('p').remove();
$(this).parent().append('<p class="size">' + width + '-' + height + '</p>');
});
}
size();
These are functions not properties, height and width:
var height = $(this).height();
var width = $(this).width();
Change you elements declartion. Because you do it like this: $($('img[proto]')). This way you cast your elements two time into jQuery.
width and height are functions, not properties. So you need to add brackets.
function size() {
$('img[proto]').each(function() {
var height = $(this).height(),
width = $(this).width();
$(this).parent().find('p').remove();
$(this).parent().append('<p class="size">' + width + '-' + height + '</p>');
});
}
size();
I would even prefer to only get the elements you needed once. The way you did it casts this four times into an jQuery object and search two times for the parent. The performance could be saved.
var element = $(this),
parent = element.parent(),
height = element.height(),
width = element.width();
parent.find('p').remove();
parent.append('<p class="size">' + width + '-' + height + '</p>');
And if you want to execute the function directly, you can use an IIFE or just remove the function around and execute it directly.
(function() {
$('img[proto]').each(function() {
// ...
});
})();
I'm working with markers on google map and this is what happens
I call this variable to the images and upload to the database and use a query to put two images into a single file (GROUP_CONCAT)
var image = markers[i].getAttribute("image");
image = image.split(",");
And here I show these pictures.
var html = div id = "iw-container" +
'a Href="'+image[0]+'" data-lightbox="roadtrip" <img src = "' + image [0] +" "width = 100" height = "100" / a '+
'a Href="'+image[1]+'" data-lightbox="roadtrip" <img src = "' + image [1] + '" width = 100 "height =" 100 " / a '+
'a Href="'+image[2]+'" data-lightbox="roadtrip" <img src = "' + image [2] + '" width = 100 "height =" 100 " / a '+
'/ Div';
The problem is if a marker is less than 3 images, for example a marker has 2 images, one of the images appear broken. obviously because not defined. ()
I wonder if there is any function or something to check if an image has the "SRC" undefined, remove it or hide it or do something to not appear.
Any help is good, thanks :)
Code like this should get you past this issue:
var html = '';
for(var i=0;i < image.length; i++) {
html += image[i];
}
I am trying to display preloaded images in a newly created popup window. Here is the code:
HTML
<div id="hiddenImages" style="display: none;"></div>
<img src="SmallImage1.gif" width="196" height="130" border="0">
<img src="SmallImage2.gif" width="196" height="130" border="0">
JS
<script type="text/javascript">
preloadImages('BigImage1.png','BigImage2.png');
</script>
// PreLoadImages:
function preloadImages() {
var hiddenDiv = document.getElementById('hiddenImages');
var i;
var img;
for(i = 0; i < arguments.length; i++) {
img = document.createElement('img');
img.src = arguments[i];
img.id = arguments[i];
img.alt = '';
hiddenDiv.appendChild(img);
}
}
// OpenImage:
function OpenImage(element,e)
{
e.preventDefault();
var big_image = element.getAttribute("href");
var img = document.getElementById(big_image);
var top = (screen.height/2)-(img.height/2);
var left = (screen.width/2)-(img.width/2);
var str = "\"" + "width=" + img.width + ",height=" + img.height + ",top=" + top + ",left=" + left + ",status=0, scrollbars=0, resizable=0" + "\"";
alert(str);
var myWindow = window.open(img.src , "win1", str);
}
When I output 'str' variable in OpenImage() function, this code gives perfect dimensions of the big image. However, the size of popup window is always different than size of the image. IE stretches the popup window horizontally while Google Chrome stretches it vertically. In spite of the fact that both browsers show exactly the same dimensions for the image. And these dimensions of the image are actually being set as size of the pop up window.
Regards.
Try this out, also try to rename your variable top, I think javascript read this as a keyword.
var str = "width=" + img.width + ",height=" + img.height + ",top=" + tops + ",left=" + left + ",status=0, scrollbars=0, resizable=0 ";
So like i wrote in the title, i have multiple elements with same class i fetch that class and try to check for the child image's width/height/src of that image.
i only manage to get the height // width of the first image however i get the src of all images.
here is the html:
<a class="test">
<img src="http://www.kitchenspro.com/files/Testimonials/Large/1502046700250312a71707.jpg">
</a>
<a class="test">
<img src="http://www.kitchenspro.com/files/Testimonials/Large/40183.9461166782.jpg">
</a>
<a class="test">
<img src="http://sphotos-a.xx.fbcdn.net/hphotos-ash4/s480x480/391362_365319466870994_1543740404_n.jpg">
</a>
here is the jquery
var imagesrc= "";
var imageheight = "";
var imagewidth = "";
var i=0;
$(".test > img").each(function() {
i++;
imagesrc = $(this).attr("src");
imageheight = $(this).width();
imagewidth = $(this).height();
document.write("<br>This is image's src: " + imagesrc + " This is img height: " + imageheight + " this is width: " + imagewidth + "<br>");
});
I apologize if i didnt present the code the right way.
Any help would be highly appreciated.
Thanks in advanced.
The first call to document.write destroys the rest of elements so that's why you only get information from one of them, use .append() or something else to show your results.
Exactly what #Musa said.
To help clean up your code and give a lesson on efficiency and native javascript, I have supplied a snippet.
// Document Fragments are lightweight DOM containers. Append elements to this in loops and then attach the fragment to the actual DOM afterwards to increase efficiency.
var frag = document.createDocumentFragment();
// i, or index, comes out of box in most loops.
$(".test img").each(function(i, el) {
// Local variables specific to each image
var imagesrc = $(this).attr("src");
var imageheight = $(this).width();
var imagewidth = $(this).height();
var message = "This is image's src: " + imagesrc + " This is img height: " + imageheight + " this is width: " + imagewidth;
// Appending the node to the frag with native js
var p = document.createElement("p");
p.innerText = message;
frag.appendChild(p);
// Viewing the console message for fun
console.log(message);
});
document.body.appendChild(frag);