Find the last element that has appeared DOM html - javascript

I have a code that puts images on a table(html), and I want to focus on the image that has just appeared.
I know that i have to use $(this) but i don't know how, here is my code
function positioning(year, mon) {
$('#' + year + ' .' + mon).prepend('<img class="black_point" src="./images/circle.png"/>');//that adds the image
var table = document.getElementById("table");
var images = table.getElementsByTagName("img");
//here I need the current image I had just add to send to that function
function connect(images) {
var tabBcr = table.getBoundingClientRect();
var imgBcr = image.getBoundingClientRect();
x = imgBcr.left + (imgBcr.width / 2) - tabBcr.left;
y = imgBcr.top + (imgBcr.height / 2) - tabBcr.top;
}
}
I hope I have explained well .

I think it will work, add this where you want to get that img element:
var imgelem=$('#' + year + ' .' + mon).find("img:first");

Related

What's causing Intersection Observer API to respond differently when replacing synchronous logic with asynchronous logic?

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

Replace image with error image by image name with onChange="swapImage()"

Pretty new to Javascipt.
Using a form with on top of the form a image. If they change an option in one of the eight dropdown boxes the image will change. However, if they make a configuration that doesn't exsist, the image is not found and the standard broken imagelink will be displayed.
Is there a way to check when I'm changing a value and trigger the onChange="swapImage()"from a dropdown to trigger an event to check if image exsists, and if not, replace it with an error image?
<script type="text/javascript">
function swapImage(){
var image = document.getElementById("imageToSwap");
var hoogte = document.getElementById("hoogte").value;
var bt = document.getElementById("bt").value;
var fase = document.getElementById("fase").value;
var aardlek = document.getElementById("aardlek").value;
var kook = document.getElementById("kook").value;
var groepen = document.getElementById("groepen").value;
var merk = document.getElementById("merk").value;
image.src = "http://www.groepenkasten.expert/images/" + merk + "/" + hoogte + "_" + bt + "_" + fase + "_" + aardlek + "_" + kook + "_" + groepen +".gif";
};
Because the image is Dynamic, there is no full page reload,. Therefore it will not detect the error that the broken image produce when the image doesn't exsist.
Link to the form: http://www.groepenkasten.expert/meld-uw-storing/kant-en-klare-groepenkasten

How to retrieve function input javascript

I've got the following code that produces a dynamically created image button and panel in asp.net: -
Panel panBlocks = new Panel();
panBlocks.ID = "PanBlockQuestionID" + recordcount.ToString();
panBlocks.Width = 1300;
panBlocks.Height = 50;
panBlocks.BackColor = Color.Pink;
ImageButton cmdBlocks = new ImageButton();
cmdBlocks.ImageUrl = "~/Images/block3.png";
cmdBlocks.ID = "lblImg" + recordcount.ToString();
cmdBlocks.Attributes["class"] = "liQuestionsLabel2";
cmdBlocks.Width = 30;
cmdBlocks.Attributes.Add("OnMouseOver", "showPanel(" + "CPH_Body_" + panBlocks.ClientID.ToString() + ")");
cmdBlocks.Attributes.Add("OnMouseOut", "hidePanel();");
li.Controls.Add(cmdBlocks);
li.Controls.Add(panBlocks);
When I hover over the image I want it to display a particular panel. I've added the "CPH_Body_" + panBlocks.ClientID.ToString() as an attribute.
I've got the following javascript code:
function showPanel(PanelID)
{
document.getElementById("CPH_Body_liQuestions1").style.height = "40px";
}
How do I retrieve the PanelID in the javascript please as it looks like an array. I need to retrieve this so I know which panel to display please.
IIUC (!!):
Change this :
cmdBlocks.Attributes.Add("OnMouseOver", "showPanel(" + "CPH_Body_" + panBlocks.ClientID.ToString() + ")");
To:
cmdBlocks.Attributes.Add("OnMouseOver", "showPanel('" + panBlocks.ClientID.ToString() + "')");
And change this :
function showPanel(PanelID)
{
document.getElementById("CPH_Body_liQuestions1").style.height = "40px";
}
To
function showPanel(PanelID)
{
document.getElementById(PanelID).style.height = "40px";
}

Clone DIV and its contents with new ids [duplicate]

This question already has answers here:
Clone <div> and change id
(4 answers)
Closed 9 years ago.
I'm trying to clone a div and the input elements inside it. When I clone it, I would like all the ids to increment by one. I've made a fiddle to show you what I'm doing.
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount);
$(cloned_div).clone().attr('id', 'class-' + new_amount).insertAfter('#class-' + amount);
});
jsFiddle
So far I've cloned the whole div itself and the ids increment but the elements inside remain the same. How would I get all elements inside the div to increment by one?
You have cloned the entire div without modifying it's contents. Try something like:
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount);
$(cloned_div).clone().attr('id', 'class-' + new_amount).insertAfter('#class-' + amount).find('input').each(function (i, e) {
$(e).attr('id', $(e).attr('id').replace(amount, new_amount));
});
});
DEMO
You can recursively replace all id's using find / replace:
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount).clone();
cloned_div.insertAfter('#class-' + amount);
cloned_div.find('[id$="-' + amount + '"]').andSelf().each(function(index, child) {
child.id = child.id.replace("-" + amount, "-" + new_amount);
});
});
See jsFiddle
cloned_div.find('[id$="-' + amount + '"]') will search for all child elements having an id attribute ending on "-" + amount, .andSelf() will include the cloned div as you want to change the id there also. Then simply replace the number part in the id of each child (and self).
Try adding this:
$('#class-' + new_amount + ' input:nth-child(1)').attr('id', 'name-class-' + new_amount);
$('#class-' + new_amount + ' input:nth-child(2)').attr('id', 'number-class-' + new_amount);
$('#class-' + new_amount + ' input:nth-child(3)').attr('id', 'book-class-' + new_amount);
just below your $(cloned_div).clone() statement.
See it in action:
http://jsfiddle.net/ZHHcA/1/
These other answers are close, but the problem with their solutions is the original ID prefixes are being lost: number-class-1 is becoming class-1 which is not ideal.
Here is a better option:
$("#add").click(function (e) {
var amount = $('div.classes').length;
var new_amount = amount + 1;
var cloned_div = $('#class-' + amount);
var $cloned = $(cloned_div).clone().attr('id', 'class-' + new_amount).insertAfter('#class-' + amount);
$cloned.children().each(function(){
var $child = $(this);
var oldID = $child.attr('id');
var newID = oldID.replace(/[0-9]+$/, new_amount); // replace just the number, leave the rest of the ID name in tact
$child.attr('id', newID);
})
});
And a working example

Is it possible to use cloneNode to clone multiple divs?

I'm trying to clone to divs in and append them to to other divs (their parents). I'm using clonenode for this but it doesn't seem to work. It clones the div in the first function and appends it to the parent of the div in the second function! Not sure what I'm doing wrong.
Here's the code (*EDIT:*var added):
function cloneQ() {
//Cloning questions and shit
cloneQ.id = (cloneQ.id || 0) + 1;
var question = document.getElementById("question");
var clone = question.cloneNode(true);
var numberOfQuestions = $('.question').length;
var id = "questioncon" + cloneQ.id;
clone.id = id;
question.parentNode.appendChild(clone);
var inid = "question" + cloneQ.id;
var optionid = "optionsdiv" + cloneQ.id;
$('#' + id + ' ' + '.' + 'questionin').attr('id', inid);
$('#' + id + ' ' + '.' + 'options').attr('id', optionid);
$('#' + id + ' h2').html('Question ' + cloneQ.id);
//Question Cloned
}
function cloneforPrint() {
cloneforPrint.id = (cloneforPrint.id || 0) + 1;
var questionprint = document.getElementById("questionprint");
var cloneprint = questionprint.cloneNode(true);
var printid = "questionprint" + cloneforPrint.id;
cloneprint.id = printid;
questionprint.parentNode.appendChild(clone);
var printinid = "thequestionprint" + cloneforPrint.id;
$('#' + printid + ' ' + '.' + 'thequestionprint').attr('id', printinid);
}
LIVE here: http://bit.ly/R8hB2m
Edit : Global vars are the problem.
You aren't putting var in front of your variables, making them global. The cloneForPrint function is picking up vars defined in cloneQ.
Init all the variables properly and you'll get some errors indicating where the problems are.
CloneQ is indeed appending to questions parent, but cloneForPrint then moves it somewhere else.
-- Old answer --
There's not enough here to work out what the problem is. My 1st guess is that the question element has the same parent as the questionprint element.
Based on the code given, cloneQ should definitely append to questions parent. So to give the appearance you've specified the DOM probably doesn't look like what you expect.

Categories

Resources