I am building a simple photo editor app using imgix, and I want the image src attribute to be updated when a user input fields receive values. Is there a way to append my new parameters onto the end of the src url?
I have been able to use template literals to create a new url, however I haven't been able to figure out how or if I can update the image src as the user types. Or if the only way to do this would be submitting the changes and show the new image on page reload. I have tried reassigning image.src to the new url, but that hasn't worked.
HTML:
<form id="form" class="input-container">
<input type="text" placeholder="Enter Text" id="title"/>
<input type="text" placeholder="Enter Hexcode Color" id="overlay" />
<input type="submit" value="Apply Changes" id="edit-submit">
</form>
JavaScript:
let form = document.getElementById("form");
let titleInput = document.getElementById("title");
let encodedTitle = encodeURI(titleInput);
let overlayColor = document.getElementById("overlay");
let image = document.getElementById("image");
let timeout = null;
form.onkeyup = function(e) {
let encodedTitle = "&txt=" + encodeURI(titleInput.value);
let newColor = "&blend=" + overlayColor.value;
let url = new URL(`${image.src}`);
url = `${url}${encodedTitle}${newColor}`;
console.log(url);
document.getElementById("url-result").value = url;
image.src = url;
};
I am able to grab the values but I haven't figured out what I'm needing to do to apply it to the img src url.
Your code changes the URL of the image, but the URL gets longer and longer with each keyup.
Look at this snippet - maybe it helps.
let form = document.getElementById("form");
let titleInput = document.getElementById("title");
let encodedTitle = encodeURI(titleInput);
let overlayColor = document.getElementById("overlay");
let image = document.getElementById("image");
let timeout = null;
// URL base for your image - so it doesn't get longer-and-longer
// with each keyup
let baseURL = image.src
// just a display element, so you can see the URL created
let display = document.getElementById('new-url')
form.onkeyup = function(e) {
const newURL = `${baseURL}&txt=${encodeURI(titleInput.value)}&blend=${overlayColor.value}`
document.getElementById("url-result").value = newURL;
image.src = newURL
display.textContent = newURL
};
img {
width: 100px;
height: 100px;
}
<img id="image" src=""><br />
<label for="url-result">URL Result:
<input type="text" id="url-result">
</label>
<div>Display new URL: <span id="new-url"></span></div>
<form id="form" class="input-container">
<input type="text" placeholder="Enter Text" id="title" />
<input type="text" placeholder="Enter Hexcode Color" id="overlay" />
<input type="submit" value="Apply Changes" id="edit-submit">
</form>
Related
I have the following problem that I cannot solve
is a form of this type
in HTML
<button (click)="addform()">agregar formulario</button>
<div class="conten-form">
<div class="MyForm">
<label>Nombre</label>
<input type="text" class="name">
<label>descripcion</label>
<input type="text" class="description">
<label>Foto</label>
<div class="img-cont">
<div class="img">
<img src="{{img}}">
</div>
<div class="addimg">
<input type="file" (change)="createimg($event)">
</div>
</div>
</div>
<div class="AddForm"></div>
<input type="buttom" value="enviar" (click)="enviarform()">
</div>
in TS
img : any; //to show
imgfile : any; //to send it through the form
constructor(...){...}
addform(){
let addform = document.querySelectorAll('.AddForm');
let myform = document.querySelectorAll('.MyForm');
let cloneform = myform.cloneNode(true);
addform.appendChild(cloneform);
}
createimg(event){
this.imgfile = event.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(this.imgfile);
reader.onload = () => {
this.img = reader.result;
};
}
enviarform(event){
let nombre = document.querySelectorAll(".name");
let description = document.querySelectorAll(".description");
let formdata = new FormData;
//add all inputs class name
for (let i = 0; i < nombre .length; i++) {
let stringname = (nombre.[i] as HTMLTextAreaElement).value;
formdata.append('name',stringname);
}
//add all inputs class description
for (let i = 0; i < description.length; i++) {
let stringdescription = (description.[i] as HTMLTextAreaElement).value;
formdata.append('description',stringdescription );
}
//send the form
}
As you will see, I can add more forms with the add button, cloning the first one, the part of the text inputs I have solved to add as many as I want, but in the part of the inputs for the image I have no idea how to do it, the operation is that after attaching an image to the input, I get a preview image of what I am going to attach in the div.class = img, this makes it only work in the first form, and it no longer works in the forms that I add dynamically, as it could fix this issue? taking into account that I have to send it through the formdata in a single shipment, I thank you in advance.
you should not use
let addform = document.querySelectorAll('.AddForm');
let myform = document.querySelectorAll('.MyForm');
let cloneform = myform.cloneNode(true);
at all. to add forms. instead you should create a separate component for each form.
check my question earlier on stackoverflow to get what I mean.
more specifically check the answer stackblitz.
So I'm trying to get a file on submit but i got this code snippet that gets it onchange. Truthfully i do not really understand the first line and how it transitions BUT basically i want to turn it to a function i can call when i click submit and without having the eventlistener there as sometimes it does not work unless called on the html form.
const fileSelector = document.querySelector('#a_pic');
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
file = fileList[0];
pic_url = URL.createObjectURL(file);
alert(file)
document.querySelector('#secondcheck').innerHTML = '<img src = "' + pic_url + '">';
a_pic = file;
});
Html code:
<form>
<input class= "form-control" type = "file" name= "a_pic" id= "a_pic" accept= "image/*">
<button type="button" value = "submit" name = "submit" id="submit" onclick = "whatever_the_newfunction_may_be()">submit</button>
Please any explanation is appreciated as i am relatively new green in javascript.
This works fine. There's a variety of ways to handle a form submission, but here's one where you don't use the form's submit event but instead just a button's click event.
const fileSelector = document.querySelector('#a_pic');
let picBlobUrl;
fileSelector.addEventListener('input', (event) => {
const fileList = event.target.files;
file = fileList[0];
picBlobUrl = URL.createObjectURL(file);
});
function submitClicked() {
document.querySelector('#secondcheck').innerHTML = '<img src="' + picBlobUrl + '">';
}
<div>
<input class="form-control" type="file" name="a_pic" id="a_pic">
<button onclick="submitClicked()">submit</button>
</div>
<div id="secondcheck"></div>
Basically, I have a simple webpage with two text fields, and a button to choose an image from the computer. What I need to happen, is for the user to pick a photo, fill in the "artist" and "text" field, press the "Add image" button. This should then add all three items to an array, and display both the image in a div, and the text in an "li" list item.
At the moment, the image works, and will display on the screen when the button is pressed, the text seems to get pushed into the array, but no matter what I do, I can't get the text to display on the web page. I also couldn't get the image to display if I turned the array into objects, which is why I've split the pushing of the text to a separate function.
Either way, whatever I try, either breaks the image display, or breaks the text display. I can't get both to display on the page. I am trying to make it so whenever a new image and text is added, it will all display one after another sort of like this:
[album cover]
[text]
[album cover]
[text]
And this would carry on down the screen as you keep adding more. Can someone please tell me where I'm going wrong with this. Thanks.
var info = {
myImages: [],
addImage: function(imageBlob) {
this.myImages.push(imageBlob);
},
addInfo: function(artist, title) {
this.myImages.push({
artist: artist,
title: title
});
},
redrawImages: function() {
var divForImages = document.getElementById('myImages');
divForImages.innerHTML = '';
this.myImages.forEach((imageBlob) => {
var img = document.createElement('img');
img.style.width = "200px";
img.style.height = "200px";
img.src = URL.createObjectURL(imageBlob);
divForImages.appendChild(img);
});
},
redrawInfo: function() {
var ul = document.querySelector('ul');
this.myImages.forEach(function (item) {
let li = document.createElement('li');
ul.appendChild(li);
li.innerHTML += item;
});
}
}
var handlers = {
addImageAndRedraw: function() {
var fileInput = document.getElementById('fileInput');
var artistField = document.getElementById('artistField');
var titleField = document.getElementById('titleField');
if (fileInput.files.length === 1) {
info.addImage(fileInput.files[0]);
info.addInfo(artistField.value, titleField.value);
info.redrawImages();
info.redrawInfo();
}
}
}
var button = document.getElementById('button');
button.addEventListener('click', handlers.addImageAndRedraw);
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>My images</h1>
<input id="fileInput" type="file" accept="image/*" multiple="false" value="Select image">
<input id="button" type="button" value="Add image and redraw">
<div>
<input id="artistField" type="text" placeholder="artist">
<input id="titleField" type="text" placeholder="title">
</div>
<hr>
<div id="myImages">
</div>
<ul></ul>
<script src="album.js"></script>
</body>
</html>
You're adding the info to the same array as the images, so it will end up like [image, info, image, info] etc.. You're better off adding an object that contains both the image and the info, and then treating it as a single object when you add the contents to the page, rather than adding the images and text in separate functions. Also, you're not clearing the info list, so it would grow exponentially.
Here's a modified example, just after tweaking the bits I mentioned above...
var info = {
myInfo: [],
add: function(imageBlob, artist, title) {
this.myInfo.push({
image: imageBlob,
artist: artist,
title: title
});
},
redraw: function() {
var divForImages = document.getElementById('myImages');
divForImages.innerHTML = '';
var ul = document.querySelector('ul');
ul.innerHTML = "";
this.myInfo.forEach((info) => {
var img = document.createElement('img');
img.style.width = "200px";
img.style.height = "200px";
img.src = URL.createObjectURL(info.image);
divForImages.appendChild(img);
let li = document.createElement('li');
ul.appendChild(li);
li.innerHTML = info.artist + " - " + info.title;
});
},
}
var handlers = {
addImageAndRedraw: function() {
var fileInput = document.getElementById('fileInput');
var artistField = document.getElementById('artistField');
var titleField = document.getElementById('titleField');
if (fileInput.files.length === 1) {
info.add(fileInput.files[0], artistField.value, titleField.value);
info.redraw();
}
}
}
var button = document.getElementById('button');
button.addEventListener('click', handlers.addImageAndRedraw);
<h1>My images</h1>
<input id="fileInput" type="file" accept="image/*" multiple="false" value="Select image">
<input id="button" type="button" value="Add image and redraw">
<div>
<input id="artistField" type="text" placeholder="artist">
<input id="titleField" type="text" placeholder="title">
</div>
<hr>
<div id="myImages"></div>
<ul></ul>
I have a list of buses that a user can choose to track. The html looks like this:
<div class="bus-container">
<div class="bus-heading">
<h1>My Buses</h1>
<svg width="15px" height="15px" class="add-bus"><use xlink:href="#plus"></use></svg>
</div>
<form class="hidden">
<select name="company">
<option value="greyhound">Greyhound</option>
<option value="zippy">Zippy</option>
<option value="carta">Carta</option>
</select>
<input type="text" name="number" placeholder="Enter Bus Number" />
<input type="text" name="route" placeholder="Enter the route" />
<input type="submit" value="Submit">
</form>
<div class="bus active">
<img src="img/greyhound.png" width="100" height="40" />
<p class="bus-number">12345043</p>
<p class="route">Jefferson</p>
</div>
<div class="bus active">
<img src="img/zippy.png" width="100" height="40" />
<p class="bus-number">12345043</p>
<p class="route">Jefferson</p>
</div>
<div class="bus active">
<img src="img/carta.png" width="100" height="4" />
<p class="bus-number">12345043</p>
<p class="route">Jefferson</p>
</div>
</div>
I am wondering what is the best way to use Javascript to create a new instance of the .bus div when the user inputs their info and clicks submit. I know I need to call on onsubmit function on the form and prevent the default click on the submit button itself. But I am pretty clueless as to how to append the new .bus div based on the user's input.
Try using a re-usable function called within onsubmit handler for form element, passing select value, number and route as parameters
window.onload = function() {
function addBus(company, number, route) {
var buses = document.querySelectorAll(".bus");
var curr = document.createElement("div");
curr.setAttribute("class", "bus active");
var img = new Image();
img.src = "img/" + company + ".png";
img.width = 100;
img.height = 40;
var p1 = document.createElement("p");
p1.setAttribute("class", "bus-number");
p1.innerHTML = number;
var p2 = document.createElement("p");
p2.setAttribute("class", "route");
p2.innerHTML = route;
curr.appendChild(img);
curr.appendChild(p1);
curr.appendChild(p2);
if (buses.length) {
buses[buses.length - 1].insertAdjacentHTML("afterEnd", curr.outerHTML)
} else {
document.forms[0].insertAdjacentHTML("afterEnd", curr.outerHTML)
}
}
var obj = {
company: "",
number: "",
route: ""
};
document.forms[0].onchange = function(e) {
obj[e.target.name] = e.target.value;
}
document.forms[0].onsubmit = function(e) {
e.preventDefault();
addBus(obj.company, obj.number, obj.route)
}
}
plnkr http://plnkr.co/edit/mLz2pNROV3cSCPmnE2S1?p=preview
You can use jQuery to create the new bus div and append it to it's container:
// get these from the form...
var newBusNumber = 123;
var newRoute = "Jefferson";
// create new bus div
var $busDiv = jQuery("<div></div>");
$busDiv.addClass("bus");
$busDiv.addClass("active");
// create img tag
var $img = jQuery("<img />");
$img.attr("src", "img/carta.png");
$img.attr("width", "100");
$img.attr("height", "4");
// create first paragraph tag
var $p1 = jQuery("<p></p>");
$p1.addClass("bus-number");
$p1.text(newBusNumber);
// create second paragraph tag
var $p2 = jQuery("<p></p>");
$p2.addClass("route");
$p2.text(newRoute);
// put the bus div pieces together
$busDiv.append($img);
$busDiv.append($p1);
$busDiv.append($p2);
// append the bus div to it's container
var $busContainer = jQuery(".bus-container");
$busContainer.append($busDiv);
Use JQuery AJAX.After successfull callback append whatever you want .
I think you can just clone the required 'bus', and append it to the container, something like that.
function addBus() {
var id = document.querySelector('input[name="number"]').value; // the index of chosen bus;
var bus = document.querySelectorAll(".bus")[id]; // get chosen bus
var newBus = bus.cloneNode(true); // deep cloning of the existing 'bus'
document.querySelector('.bus-container').appendChild(newBus); // add to the container
}
first of all I'm sorry if this is a long code segment however, I'm trying to make a modal window which writes the thing you wrote in my user form and asks you to confirm it. I am currently in a class to learn Javascript and I'm not allowed to use innerHTML and I must write the "Firstname:" etc dynamically (the text for firstname) and am not allowed to just write it inside the popup window. I've gotten most stuff to work but the "Firstname:" "Lastname" etc comes up as "undefined" or (as you can see the thing I tried with just the first name in this case) comes up as "null".
Hopefully someone can shed some light on this subject for me, this is the HTML:
<form action="http://voyager.lnu.se/tekinet/kurser/dtt/wp_webbteknik/process_form.php" method="POST" id="userform" target="_blank">
<p id="formQuestion1">Förnamn</p>
<div id="error1"></div>
<input type="text" name="firstName" id="test"/>
<p id="formQuestion2">Efternamn</p>
<div id="error2"></div>
<input type="text" name="lastName" />
<p id="formQuestion3">Postnummer</p>
<div id="error3"></div>
<input type="text" name="postCode" id="codeText"/>
<p id="formQuestion4">E-post</p>
<div id="error4"></div>
<input type="text" name="eMail" />
<br />
<br />
<label id="model" class="formQuestion" for="priceModel">Prismodell</label>
<br />
<select name="Type" id="priceModel">
<option value="Låg" selected>Låg</option>
<option value="Medel">Medel</option>
<option value="Hög">Hög</option>
</select>
<br />
<br />
<br />
<input id="sendButton" type="submit" value="Genomför Köp" />
</form>
And here is the segment for the modal window (Javascript)
function popup(backgroundDiv) {
var popForm = document.getElementById("userform");
var myDiv = document.createElement("div");
myDiv.className = "popupWindow";
var priceModel = document.getElementById("priceModel");
// Knappar
var newButton = document.createElement("button");
var newerButton = document.createElement("button");
newButton.setAttribute("value", "Skicka");
newButton.innerHTML = "Skicka"; // Here I actually use innerHTML because I don't know
newerButton.innerHTML = "Stäng"; // any other way to set the text inside the button
newButton.className = "popupButton";
newerButton.className = "popupButton";
newButton.setAttribute("id", "Skicka");
newerButton.setAttribute("id", "Avbryt");
myDiv.appendChild(newButton);
myDiv.appendChild(newerButton);
// Information
var h1 = document.createElement("h1");
h1.setAttribute("id", "popuph1");
var h1Text = document.createTextNode("Vänligen kontrollera dina uppgifter");
var text = document.getElementById("formQuestion1");
var writeFname = text.nodeValue + popForm.elements.firstName.value;
var writeLname = document.getElementById("formQuestion2").value + popForm.elements.lastName.value;
var writeCode = document.getElementById("formQuestion3").value + popForm.elements.postCode.value;
var writeMail = document.getElementById("formQuestion4").value + popForm.elements.eMail.value;
var writePlan = document.getElementById("model").value + priceModel.value;
var p1 = document.createTextNode(writeFname);
var p2 = document.createTextNode(writeLname);
var p3 = document.createTextNode(writeCode);
var p4 = document.createTextNode(writeMail);
var p5 = document.createTextNode(writePlan);
h1.appendChild(h1Text);
myDiv.appendChild(h1);
myDiv.appendChild(p1);
myDiv.appendChild(document.createElement('br'));
myDiv.appendChild(p2);
myDiv.appendChild(document.createElement('br'));
myDiv.appendChild(p3);
myDiv.appendChild(document.createElement('br'));
myDiv.appendChild(p4);
myDiv.appendChild(document.createElement('br'));
myDiv.appendChild(p5);
document.body.appendChild(myDiv);
newButton.onclick = function () {
document.body.removeChild(myDiv);
document.body.removeChild(backgroundDiv);
return true;
};
If you don't want to use innerHTML then you can use those options, suppose you want value from this node <p id="formQuestion1">Förnamn</p>
Then your code would be
var dom = document.getElementById('formQuestion1');
1) var res = dom.innerText;
OR
2) var res = dom.textContent;
OR
3) var res = dom.firstChild.nodeValue;