Add/Delete Button - javascript

I'm working on this project, and what it is supposed to do is show a series of "business cards" that contain the name of someone and their image. When you hover over the card an x button appears and clicking it will delete the card from the page. There are also to inputs one for the url of an image and another for the name of the person, under these 2 inputs are a submit button, and when it's submitted it's supposed to create the card.
Right now I have the code to create the card, but it does not appear to be working.
document.getElementById('btn').onclick = function() {
var addPhoto = document.getElementById('imagename').value,
src = addPhoto +'.png',
img = document.createElement('img');
img.src = src;
var addName =document.getElementById('actorname').value;
var card = document.createElement('div');
card.setAttribute('class','card');
var title = document.createElement('h1');
container.innerHTML = addName;
var cardImage = document.createElement('div');
cardImage.setAttribute('class','card-image');
var img = document.createElement('img');
image.setAttribute('src',addPhoto);
var button = document.createElement('input');
button.setAttribute('class','buttons');
button.setAttribute('type','image');
button.setAttribute('src','img/close.png');
card.appendChild(title);
card.appendChild(cardImage);
cardImage.appendChild(image);
cardImage.appendChild(button);
document.getElementById("lefty").appendChild(card);
};

To add a new card, you should set everything up from the ground. You should create the following in Javascript before adding it to the page:
<div class="card">
<h1>the_name</h1>
<div class="card-image">
<img src="the_link"/>
<input class="buttons" type="image" src = "img/close.png"/>
</div>
</div>
You already know how to get *'the_name'* and *'the_link'* (the variables for your cards). I'm gonna use those variables in my solution. First you have to create all the elements.
var card = document.createElement('div');
card.setAttribute('class','card');
var title = document.createElement('h1');
container.innerHTML = the_name;
var cardImage = document.createElement('div');
cardImage.setAttribute('class','card-image');
var image = document.createElement('img');
image.setAttribute('src',the_link);
var button = document.createElement('input');
button.setAttribute('class','buttons');
button.setAttribute('type','image');
button.setAttribute('src','img/close.png');
Now you want to paste all the elements to the webpage. First append the elements to each other, then append them to the place you want to get them to (in your case the body).
card.appendChild(title);
card.appendChild(cardImage);
cardImage.appendChild(image);
cardImage.appendChild(button);
document.body.appendChild(card);

You can delete an element in an odd way using javascript. First you have to get the domNode of the element you want to get rid of. For example one of the two nodes:
var unwanted = document.getElementsByTagName('a')[0];
var unwanted = document.getElementById('id_of_unwanted_item');
then you have to execute the following function:
unwanted.parentNode.removeChild(unwanted)

You have the basic idea, you just need to take it a few steps farther. For the delete you'll want to add an ID to each card and then call a JS function with that ID:
<div class="card" id="william">
<h1>William Finley (Phantom of the Paradise)</h1>
<div class="card-image">
<img src="img/avatars/william.png"/>
<input class="buttons" type="image" src = "img/close.png" onclick="removeCard('william')"/>
</div>
</div>
<script type="text/javascript">
var removeCard = function(cardId) {
var cardElement = document.getElementById(cardId);
cardElement.parentNode.removeChild(cardElement);
}
</script>
When you create a card (which Nicky explained well) make sure you add the ID and onclick event to your element generation.

Related

Appending <a> and <img> to document.body removes href and src

So, I'm creating an article block like this:
<article>
<figure>
<img src="source" />
</figure>
<div>
<a href="link"/>
</div>
</article>
This is my js code:
var linkElement = document.createElement('a');
var linkText = document.createTextNode(*some text*);
linkElement.appendChild(linkText);
linkElement.href = *link*;
var imgElement = document.createElement('img');
imgElement.setAttribute("src", *some path*);
imgElement.setAttribute("width", "304");
imgElement.setAttribute("height", "228");
imgElement.setAttribute("alt", temp["name"]);
var article = document.createElement("article"),
figure = document.createElement("figure"),
div = document.createElement("div");
div.appendChild(linkElement);
figure.appendChild(imgElement);
article.appendChild(figure);
article.appendChild(div);
document.querySelector('article').appendChild(article);
This is my html code:
<body>
<header></header>
<section>
<article></article>
</section>
<footer></footer>
<script src = *src of my js*></script>
</body>
If I create one article block, everything is fine. The problem arises when I create an array of article blocks. Every block except the last one loses its href and src for the 'a' and 'img'tags. An empty image box appears and the text without the link appears. Can anyone explain why it happens and how I can change that?
Output
I printing a list of FB movie pages with their picture and links to the page.
My original code:
// data has a list of FB movie pages, each containing the name of t he movie and page id
function print(data)
{
//iterates through the object passed to print movie names in console.
var target = document.querySelector('article');
var docFrag = document.createDocumentFragment();
for (var i = 0; i < data.length; i++)
{
var temp = data[i];
var linkElement = document.createElement('a');
var linkText = document.createTextNode(temp["name"]);
linkElement.appendChild(linkText);
//getting the link to the movie's FB page
getLink(function(response){linkElement.href = response;},temp["id"]);
var imgElement = document.createElement('img');
//getting the src of the picture of the movie's page
getPic(function(response){imgElement.setAttribute("src", response);},temp["id"]);
imgElement.setAttribute("width", "304");
imgElement.setAttribute("height", "228");
imgElement.setAttribute("alt", temp["name"]);
var article = document.createElement("article"),
figure = document.createElement("figure"),
div = document.createElement("div");
div.appendChild(linkElement);
figure.appendChild(imgElement);
article.appendChild(figure);
article.appendChild(div);
console.log(article);
docFrag.appendChild(article);
}
target.appendChild(docFrag);
}
function getLink(callback,id)
{
FB.api('/'+id+'?fields=link', function(response)
{
callback(response.link);
});
}
function getPic(callback,id)
{
FB.api('/'+id+'?fields=cover{source}', function(response)
{
callback(response.cover.source);
});
}
If just going by the OP code, it never appends anything to the DOM. The <article> is created and everything is appended to it but it never finds its way to the DOM.
Once that is taken care of you must be mindful of the urls assigned to your images. They will fail should you mix secured content with unsecured content.
Secured Content:
<img src='https://....>
Unsecured Content:
<img src='http://....>?
BTW, this Demo is reusable and easily expandable. The simple requirement is that for each <article> you must add an appropriate url to the url[] and posters[] arrays. Also the layout is streamlined: <img> is nested with <a> and <a> is nested within <fig>, and <fig> is nested within <article>. This arrangement makes the entire <img> a link.
Demo
Details commented in Demo and references are located below the Demo
// Array of urls to sites for lnk.href
var urls = ['https://www.starwars.com', 'https://www.marvel.com'];
// Array of urls to images for img.src
var posters = ["https://imgc.allpostersimages.com/img/print/u-g-F93H7K0.jpg?w=900&h=900&p=0", "https://imgc.allpostersimages.com/img/print/u-g-F90CQI0.jpg?w=900&h=900&p=0"];
// Reference the DOM target
var target = document.querySelector('.action');
/* Create a DocumentFragment Object to add all of your articles
|| to. The only thing you should ever append to the DOM is the
|| docFrag. It's costly to add to DOM so do it only once.
*/
var docFrag = document.createDocumentFragment();
/* One loop will:
|| - create the 4 components: article, figure, a, img
|| - get the urls from the 2 arrays and assign them to
|| lnk.href and img.src
|| - set the additional attributes to img
|| - append components: img to a--a to fig--fig to art--art to
|| docFrag--docFrag to target(a section attached to the DOM)
*/
/* This `for` loop will go 2 times because the .length of urls[]
|| array is 2 (note: i < urls.length)
*/
for (let i = 0; i < urls.length; i++) {
var art = document.createElement('article');
var fig = document.createElement('figure');
var lnk = document.createElement('a');
lnk.href = urls[i];
var img = document.createElement('img');
img.src = posters[i];
img.width = '200';
img.height = '300';
lnk.appendChild(img);
fig.appendChild(lnk);
art.appendChild(fig);
docFrag.appendChild(art);
}
target.appendChild(docFrag);
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
</head>
<body>
<header></header>
<main>
<section class="action"></section>
</main>
<footer></footer>
</body>
</html>
Reference
What is the DOM?
DocumentFragment

Deteching if child already exists inside parent

I'm working on a Userscript for my use on StackOverflow, that basically replaces all images with a copy of the same image from a proxy.
What I want is for all of the image links posted in comments to be added to a new container inside the comment called imageContainer that should be created if it doesn't already exist, then all images should be moved to this container.
What I have currently sort of works - except for every image in a comment, a new container is created.
Here is the code I currently have:
var links = document.getElementsByTagName('a');
for(var i = 0; i < links.length ; i++) {
var matches = containsAny(links[i].href, matchURLs);
if(matches) {
//link variables
var link = links[i];
var linkParent = links[i].parentNode;
console.log(linkParent);
//create <img> element
var image = document.createElement("img");
image.src = proxy + link.href;
image.height = 50;
image.width = 50;
//alter <a> element
link.href = proxy + link.href;
link.target = "_blank";
link.innerHTML = "";
link.style.borderBottom = "none";
//attach <img> to <a>
link.appendChild(image);
var result = linkParent.contains(document.getElementById("imageContainer"));
console.log(result);
if(!result) {
//create imageContainer (div) element
var container = document.createElement("div");
container.id = "imageContainer";
linkParent.prepend(container);
}
//append image to container that exists from last check
linkParent.querySelector("#imageContainer").appendChild(link);
}
}
This line:
var result = linkParent.contains(document.getElementById("imageContainer"));
always results in false, even if I have already created the container on the previous loop, which means a new div is created for every image that is converted by the code, which makes it much harder for me to format correctly.
Basically, the current code will generate the following HTML in the comment I am testing this on:
<span class="comment-copy">
<div id="imageContainer"><img src="http://web.archive.org/web/https://i.stack.imgur.com/I8WNI.png" height="50" width="50"></div>
<div id="imageContainer"><img src="http://web.archive.org/web/https://i.stack.imgur.com/I8WNI.png" height="50" width="50"></div>
currently testing my new userscript (relevant to discussion)
</span>
As you can see, it contains 2 copies of the div imageContainer, even though the loop I have should check if it exists, and only create it if it doesn't.
The result I expect is as followed:
<span class="comment-copy">
<div id="imageContainer">
<img src="http://web.archive.org/web/https://i.stack.imgur.com/I8WNI.png" height="50" width="50">
<img src="http://web.archive.org/web/https://i.stack.imgur.com/I8WNI.png" height="50" width="50">
</div>
currently testing my new userscript (relevant to discussion)
</span>
The script is being run from tampermonkey on page load.
Why is a new div created for every link?
A Discovery:
There is a variable that is mentioned in the code above called matchURLs - I've just discovered the weirdest thing.
This variable is defined as
var matchURLs = ["https://i.stack.imgur.com/", "https://i.imgur.com/"];
it's basically just the URLs to check if the image is from (I don't want to proxy every image, only ones from the URLs above)
But the weird part of this is, if I remove the second link from the array, e.g if I define matchURLs as
var matchURLs = ["https://i.stack.imgur.com/"];
then the code works as expected and puts all of the images inside a single imageContainer div instead of multiple divs. Is this the cause of the issue? Why?
The containsAny() function is defined as:
function containsAny(str, substrings) {
for (var i = 0; i != substrings.length; i++) {
if(str.startsWith(substrings[i])) {
return true;
}
}
return false;
}
Use parentLink.querySelector( '.image-container' ) to try and select the image container that is a child of the .comment-copy element. If it is null, it doesn't exist, otherwise you have a reference to that element.
Run the snippet to see the first and third comment returning the proper element with innerHTML 1 and 3 respectively and the second comment returning null because the image container doesn't exist yet.
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
var link = links[i];
var linkParent = links[i].parentNode;
result = linkParent.querySelector('.image-container');
console.log(result);
}
<span class="comment-copy">
this comment has some links like <a href="https://i.stack.imgur.com/I8WNI.png" >image</a> and <a href="https://i.stack.imgur.com/I8WNI.png" >image</a>
<div class="image-container">1</div>
</span>
<span class="comment-copy">
this comment has some links like <a href="https://i.stack.imgur.com/I8WNI.png" >image</a> and <a href="https://i.stack.imgur.com/I8WNI.png" >image</a>
</span>
<span class="comment-copy">
this comment has some links like <a href="https://i.stack.imgur.com/I8WNI.png" >image</a> and <a href="https://i.stack.imgur.com/I8WNI.png" >image</a>
<div class="image-container">3</div>
</span>

Generate html using Javascript

I have a gallery page that is updated often with new images. I use simple HTML to post the photos. My process currently is copy and paste the set of tags for a photo and change the number to correspond with the image file name. E.G. I change the number 047 to 048. Copy-Paste, change it to 049. This goes on until I have reached the number of additional photos. As you can see, this is very inefficient and there must be a better way of doing this. I was wondering if there is a simpler way to achieve this with Javascript? Perhaps generate additional tags by inputing a certain number or range?
Any ideas that would make this process efficient are welcomed please! Thank you!
<div class="cbp-item trim">
<a href="../assets/images/trim/img-trim-047.jpg" class="cbp-caption cbp-lightbox" data-title="">
<div class="cbp-caption-defaultWrap">
<img src="../assets/images/trim/img-trim-047.jpg" alt="">
</div>
</a>
</div>
You could use a templating solution. There are several libraries for that, but you can also implement it yourself.
Here is one way to do that:
Put the HTML for one image in a script tag that has a non-standard language property so the browser will just ignore it
Put some keywords in there that you'll want to replace, e.g. {url}. You can invent your own syntax.
Read that template into a variable
In the JS code, put all the images' URLs in an array of strings
For each element in that array, replace the keywords in the template string with that particular URL, and concatenate all these resulting HTML snippets.
Inject the resulting HTML into the appropriate place in the document.
Here is a snippet doing that:
// Add new images here:
var images = [
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/330px-SNice.svg.png",
"https://nettemarie357.files.wordpress.com/2014/09/smiley-face.jpg?w=74&h=74",
];
// Load the template HTML
var template = document.querySelector('script[language="text/template"]').innerHTML;
// Use template to insert all the images:
container.innerHTML = images.map(url => template.replace(/{url}/g, url)).join('');
img { max-width: 50px }
<div id="container"></div>
<script language="text/template">
<div class="cbp-item trim">
<a href="{url}" class="cbp-caption cbp-lightbox" data-title="">
<div class="cbp-caption-defaultWrap">
<img src="{url}" alt="">
</div>
</a>
</div>
</script>
This would help you creating it programatically:
var new_row = document.createElement('div');
new_row.className = "cbp-item trim";
var a = document.createElement('a');
a.href = "../assets/images/trim/img-trim-047.jpg";
a.className= "cbp-caption cbp-lightbox";
document.body.appendChild(a);
var div = document.createElement('div');
div.className = "cbp-caption-defaultWrap";
var img = document.createElement('img');
img.src= "../assets/images/trim/img-trim-047.jpg";
div.appendChild(img);
a.appendChild(div);
new_row.appendChild(a);
If it is just about printing HTML, I suggest you to use plugins like Emmet for Sublime Text editor.
When you install this plugin and see how it works, you can simple create a complex html in a way that 'for' loop would do this. This will help you to change only the image/link number of every item.
Check the demo in the link, that I added.
Here's an example in Java Script that will generate the html you will need. Set the total to whatever number you need to generate the number of images you want.
var total = 47;
var hook = document.getElementById('hook');
// Main Node for SlideShow
var node = document.createElement('div');
node.classList = "cbp-item trim";
// Work out the correct number
var n = function(int) {
var length = int.toString().length;
return length === 1
? '00' + int
: length === 2
? '0' + int
: length
}
// Create the item
var createItem = function(int){
// Create Anchor
var a = document.createElement('a');
a.href = '../assets/images/trim/img-trim-' + ( n(int) ) + '.jpg" class="cbp-caption cbp-lightbox';
a.classList = 'cbp-caption cbp-lightbox';
// Create Div
var div = document.createElement('div');
div.classList = 'cbp-caption-defaultWrap';
// Create Image
var img = document.createElement('img');
img.src = '../assets/images/trim/img-trim-' + ( n(int) ) + '.jpg';
img.alt = 'gallery image';
// Finalise Dom Node
var container = div.appendChild(img)
a.appendChild(div);
// Return Final Item
return a
}
// Create Items
for (var i = 1; i < total + 1; i++) {
node.appendChild(createItem(i));
}
// Append Main Node to Hook
hook.appendChild(node);
<div id="hook"></div>

Create figure using function javaScript function createElement(tagName)

I need to create a new figure at runtime on my web app. I am using javascript and html/css.
The element that i got to create is the follow:
<figure id = "myImage" class="ball" >
<span class="shadow">
</span>
</figure>
I have tried some tag names and the "ball" isn't created.
The following code is an example(not working) what is the problem?
var generatedBall = document.createElement("FIGURE");
generatedBall.class = 'ball';
generatedBall.style.background = 'yellow';
document.body.appendChild(generatedBall);
Thanks for help.
It's working for me, see my fiddle.
You just have to give it height;
var generatedBall = document.createElement("figure");
generatedBall.classList.add('ball'); //Edited this
generatedBall.style.background = 'yellow';
generatedBall.style.height = '100px'; //Added bit
document.body.appendChild(generatedBall);
See the exact output on this page See Here
var innerSpan = document.createElement('span');
innerSpan.classList.add('shadow');
var generatedBall = document.createElement('figure');
generatedBall.setAttribute("id","myImage")
generatedBall.classList.add('ball');
document.body.appendChild(generatedBall);
generatedBall.appendChild(innerSpan);
The Element does not have a class property. Instead, you can add and remove classes using classList. So your example would become:
var generatedBall = document.createElement('figure');
generatedBall.classList.add('ball');
generatedBall.style.background = 'yellow';
document.body.appendChild(generatedBall);

Javascript: Get the innerHTML of a dynamically created div

I am retrieving some information from an xml file ( movie information ) and I am creating dynamically some DOM elements according to each movie. I want, when I click on the test element, to get the value of the title of the movie. Right now, no matter which movie I click, it gets the title of the last movie that was introduced.
How can I get the title of each individual movie when I click on that div and not the last one introduced by the for-loop?
xmlDoc=xmlhttp.responseXML;
var x=xmlDoc.getElementsByTagName("movie");
for (i=0;i<x.length;i++)
{
var titlu = x[i].getElementsByTagName("title")[0].childNodes[0].nodeValue;
var description = x[i].getElementsByTagName("description")[0].childNodes[0].nodeValue;
var descriere = document.createElement('div');
descriere.className='expandedDescriere';
descriere.innerHTML = description;
var titlediv = document.createElement('div');
titlediv.className = 'title';
titlediv.id='title';
titlediv.innerHTML = title;
var test=document.createElement('div');
test.className='test';
test.onclick= function(){
var filmName= test.previousSibling.innerHTML;
alert(filmName);
}
placeholder.appendChild(titlediv);
placeholder.appendChild(test);
placeholder.appendChild(descriere);
}
I think your problem might be in the function you assigned to onclick:
test.onclick= function(){
var filmName= test.previousSibling.innerHTML; // <===
alert(filmName);
}
the marked line should be var filmName= this.previousSibling.innerHTML;
My guess is that the var test is hoisted out of the for loop, meaning that when the loop finished, all the onclick function are referencing the same test variable which is the last element you created.
Use this to reference the clicked element:
test.onclick = function() {
var filmName = this.previousSibling.innerHTML;
alert(filmName);
};

Categories

Resources