I'm working on this piece of code, and, when you enter you name through the settings button, the code should save your name in the variable "inputname" so when you speak "hello" to the program, the program should output "Hello" + the name you entered, but for some reason it won't work. Why is that?
The code is attached below and the demo website is linked here: https://javascript-test-3.stcollier.repl.co/
function record() {
var recognition = new webkitSpeechRecognition();
recognition.lang = "en-GB";
recognition.start();
recognition.continuous = true;
recognition.onresult = function(event) {
let transcript = event.results[0][0].transcript;
var str = transcript;
let msg_hello = ['Hello ' + inputname, 'Hello!', 'Hey ' + inputname];
if (str.includes('hello')) {
document.getElementById("output").innerHTML = (msg_hello[Math.floor(Math.random() * msg_hello.length)]);
responsiveVoice.speak(msg_hello[Math.floor(Math.random() * msg_hello.length)]);
} else {
document.getElementById('output').innerHTML = "I don't know what you mean."
responsiveVoice.speak(msg_notunderstood[Math.floor(Math.random() * msg_notunderstood.length)]);
}
document.getElementById('speechToText').value = event.results[0][0].transcript;
}
}
//Mic Trigger Key
document.body.onkeyup = function(e) {
if (e.keyCode == 32) {
record()
}
}
//Modal
var modal = document.getElementById("myModal");
var btn = document.getElementById("myBtn");
var span = document.getElementsByClassName("close")[0];
btn.onclick = function() {
modal.style.display = "block";
}
span.onclick = function() {
modal.style.display = "none";
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
//Input
function saveName() {
var inputname = document.getElementById('savedName').value;
alert("You entered your name as " + inputname)
return false;
}
#output {
text-align: center;
font-family: 'Times New Roman', Times, serif;
font-size: 20px;
}
/* Modal Stuff */
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<label for="Speech Recognition">Speech Recognition</label>
<input type="text" name="" id="speechToText" placeholder="Speak Something" disabled="disabled">
<button onclick="record()">Record</button>
<p id="output"></p>
<button id="myBtn">Settings</button>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<input placeholder="Enter your name" type="text" size="12" id="savedName" />
<button onclick="return saveName();">Save</button><span title="We use your name for making your experience with Argon more personal." style="cursor:help;"> ?</span>
<script src="https://code.responsivevoice.org/responsivevoice.js?key=x9uXdCB8"></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="script.js"></script>
</body>
</html>
Thanks for any help.
When you define a variable (using var) inside a function, that confines that variable to that function only. Define inputname outside of the functions so other functions have access to it
var inputname
function record() {
....
if (!inputname) inputname = 'You'; // default
let msg_hello = ['Hello ' + inputname, ....
....
}
function saveName() {
inputname = document.getElementById('savedName').value;
...
Related
Hello lately i've been working with APIs to get the hang of them through the usual weather app project BUT i'm pretty much still a beginner in javascript and i was wondering how to add a background image that matches the weather report of the city selected by the user.
I wanted to create many classes in css, each called like the weather (ex: .clear, .clouds,.rain etc...) and then use a classList.add() method to change it each time depending on the openWeatherMap data. I tried adding something like document.getElementsByTagName("body")[0].classList.add(weatherValue); inside the .then promise but it doesn't work. Can somebody help me? If there's a much simpler way i'd like to hear about it too :) Thank you so much
var button = document.querySelector(".button");
var inputValue = document.querySelector(".inputValue");
var cityName = document.querySelector(".name");
var weather = document.querySelector(".weather");
var desc = document.querySelector(".desc");
var temp = document.querySelector(".temp");
var humi = document.querySelector(".humi");
button.addEventListener("click", function() {
fetch("https://api.openweathermap.org/data/2.5/weather?q="+inputValue.value+"&appid={myapikey}")
.then(response => response.json())
.then(data => {
var nameValue = data['name'];
var weatherValue = data['weather'][0]['main'];
var tempValue = data['main']['temp'];
var descValue = data['weather'][0]['description'];
var humiValue = data['main']['humidity'];
cityName.innerHTML = nameValue;
weather.innerHTML = weatherValue; // this gives "clear" "clouds" etc to <p> element
desc.innerHTML = descValue;
temp.innerHTML = "Temperature: " + tempValue;
humi.innerHTML = "Humidity: " + humiValue;
})
.catch(err => alert("Wrong city name!"))
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Nunito", sans-serif;
background-repeat: no-repeat;
background-size: cover;
}
.input {
text-align: center;
margin: 100px 0;
}
input[type="text"] {
height: 50px;
width: 600px;
background: #e7e7e7;
font-family: "Nunito", sans-serif;
font-weight: bold;
font-size: 20px;
border: none;
border-radius: 2px;
padding: 10px 10px;
}
input[type="submit"] {
height: 50px;
width: 100px;
background: #e7e7e7;
font-family: "Nunito", sans-serif;
font-weight: bold;
font-size: 20px;
border: none;
border-radius: 2px;
}
.display {
text-align: center;
}
.clear {
/* background image here */
}
.clouds {
/* another background image here */
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="weather_app.css">
</head>
<body>
<div class="input">
<input type="text" class="inputValue" placeholder="Enter a city">
<input type="submit" value="Submit" class="button">
</div>
<div class="display">
<h1 class="name"></h1>
<p class="weather"></p>
<p class="desc"></p>
<p class="temp"></p>
<p class="humi"></p>
</div>
<script src= "weather_app.js"></script>
</body>
</html>
I did a project like this not long ago, https://github.com/Kroplewski-M/Weather-App , I used the openWeater API. I did this:
function setBackground(weather) {
if (weather == "Rain") {
background.src = "./resources/rainy-weather.jpg";
} else if (weather == "Snow") {
background.src = "./resources/snowy-weather.jpg";
} else if (weather == "Clear") {
background.src = "./resources/sunny-weather.jpg";
} else if (weather == "Clouds") {
background.src = "./resources/cloudy-weather.jpg";
}
}
The openWeather API returns what condition the weather is so you can just if statement on what the condition is and set the background accordingly
I am looking for a simple way to hide the custom context menu unless over a button or element. Here is a simple example I coded up containing a custom context menu and a button I wish to have it attached to. I am thinking maybe there could be an event listener that looks out for an on hover over the element, or maybe a function that toggles it on or off when needed? Also i was wondering if the button or element wasn't defined with a class or ID is there still a way to know when you are over it maybe via coordinates (Not necessary just curious if possible)? The idea is there will be multiple elements that will require the context menu but the general space around the elements in the body should not show the custom menu.
function view() {
const contextMenu = document.getElementById('context-menu');
const scope = document.querySelector("body");
//body
var listLength = contextMenu.children.length;
for (i = 0; i < listLength; i++)
contextMenu.removeChild(contextMenu.children[0]);
contextMenuadd(contextMenu, "line 1 of context menu", 1);
contextMenuadd(contextMenu, "line 2 of context menu", 2);
contextMenuadd(contextMenu, "line 3 of context menu", 3);
contextMenuadd(contextMenu, "line 4 of context menu", 4);
scope.addEventListener("contextmenu", (event) => {
event.preventDefault();
const {
clientX: mouseX,
clientY: mouseY
} = event;
contextMenu.style.top = `${mouseY}px`;
contextMenu.style.left = `${mouseX}px`;
contextMenu.classList.add('visible');
contextMenu.style.display = 'block';
contextMenu.style.zIndex = 20000;
contextMenu.style.position = 'fixed';
contextMenu.style.width = "360px";
contextMenu.style.borderRadius = "5px";
});
scope.addEventListener("click", (e) => {
if (e.target.offsetParent != contextMenu) {
contextMenu.style.display = 'none';
}
});
};
document.addEventListener('DOMContentLoaded', view);
function contextMenuadd(contextMenu, menustring, count) {
var action = function(e) {
//menuLink;
let currentRow = $(event.target)[0].parentElement;
var index = parseInt(currentRow.row);
var value = currentRow.textContent;
en(href, '_self');
};
var menuitem = document.createElement('LI');
menuitem.addEventListener('click', action);
menuitem.classList.add("hotspot__item");
menuitem.innerHTML = '' + menustring + '';
menuitem.row = count;
contextMenu.appendChild(menuitem);
};
document.addEventListener('click', function(e) {
let inside = (e.target.closest('#container'));
if (!inside) {
let contextMenu = document.getElementById('contextMenuId');
contextMenu.setAttribute('style', 'display:none');
}
});
#context-menu {
position: fixed;
z-index: 10000;
width: 180px;
background: #ffaaaa;
border-radius: 5px;
display: none;
}
#context-menu.item {
padding: 2px 4px;
font-size: 12px;
color: #eee;
cursor: pointer;
border-radius: inherit;
}
<body id="allofit">
<header>
<h2>Context Menu Example</h2>
</header>
<!-- <gm:figure-group> -->
<div id='sdi_canvas1' style="width:400px; height:400px">
<button id="container"> this is data in my DIV</button>
</div>
<div id="context-menu" class="context-menu"
oncontextmenu="ShowMenu('contextMenu',event)" style="display:none">
<div class="item">Option 1</div>
<div class="item">Option 2</div>
</div>
</body>
Here's a fiddle for reference JSFiddle
You can add a class to all the elements that will show the custom
context menu.
And oncontextmenu, you check if the element contains the class then toggle the context menu accordingly.
Try this
document.addEventListener('DOMContentLoaded', () => {
const scope = document.querySelector("body");
const contextMenu = document.getElementById('context-menu');
scope.addEventListener("contextmenu", (event) => {
event.preventDefault();
if( event.target.classList.contains('has-content-menu') ||
event.target.closest('.has-content-menu') !== null
){
contextMenu.style.top = event.clientY + 'px';
contextMenu.style.left = event.clientX + 'px';
contextMenu.style.display = 'block';
}else{
contextMenu.style.display = 'none';
}
});
scope.addEventListener("click", (event) => {
contextMenu.style.display = 'none';
});
});
*, ::after, ::before {
box-sizing: border-box;
}
body, html {
height: 100%;
}
#context-menu {
position: fixed;
z-index: 10000;
width: 180px;
background: #ffaaaa;
border-radius: 5px;
display: none;
z-index: 20000;
}
#context-menu.item {
padding: 2px 4px;
font-size: 12px;
color: #eee;
cursor: pointer;
border-radius: inherit;
}
<button class="has-content-menu"> this is data in my DIV</button>
<div id="context-menu">
<div class="item">Option 1</div>
<div class="item">Option 2</div>
</div>
Have you tried using a 'mouseover' and 'mouseout' events?
Let me know if this what you looking for:
const menu = document.querySelector('.menu')
const btn = document.getElementById('btn');
btn.addEventListener('mouseover', () => {
menu.style.display = "block";
});
btn.addEventListener('mouseout', () => {
menu.style.display = "none";
})
.menu {
display: none;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<button id="btn">Hover me</button>
<ul class="menu">
<li>Test 1</li>
<li>Test 1</li>
</ul>
</body>
</html>
I have this program that allows the user to edit a div when the user double clicks it. I'm trying to only make the most recent double clicked div have a border. I'm doing this right now with the addClass method, I add the .selceted class with this function:
$(function () {
$("div").dblclick(function (e) {
clickedTD = event.target;
$(clickedTD).find(clickedTD).last.removeClass("selected").addClass("selected");
}
I'm trying to make the last selected div be deleted with this .find(clickedTD).last.removeClass("selected")
So that most recent double clicked div is the only one with the .selected class. But this didn't work and I'm unsure why.
Here is my full code:
var text;
var selectedText;
var blue = document.getElementById("blue");
var blue2 = document.getElementById("blue2");
var elementCounter = 0;
function addElement() {
var classN = event.target.id;
text = document.getElementById("input").value;
// create a new div element and give it a unique id
var newDiv = document.createElement("div");
newDiv.id = 'temp'+elementCounter;
newDiv.classList = "div";
elementCounter++
if (classN == "blue"){
newDiv.classList = "blue"
} else if (classN == "red"){
newDiv.classList = "red"
} else if (classN == "green"){
newDiv.classList = "green"
} else if (classN == "blue2"){
newDiv.classList = "blue2"
}
// and give it some content
var newContent = document.createTextNode(text);
// add the text node to the newly created div
newDiv.appendChild(newContent);
// add the newly created element and its content into the DOM
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
$(function() {
var currentlyDragged;
$("div").draggable({
drag: function (e) {
currentlyDragged = e.target.id
selectedText = event.target;
text = $(selectedText).html();
}
});
$(function () {
$("div").dblclick(function (e) {
clickedTD = event.target;
$(clickedTD).find(clickedTD).last.removeClass("selected").addClass("selected");
}
);
});
});
document.getElementById("input").value = " ";
}
#import url('https://fonts.googleapis.com/css2?family=Roboto:wght#300&display=swap');
import { library } from '#fortawesome/fontawesome-svg-core'
import { fas } from '#fortawesome/free-solid-svg-icons'
import { far } from '#fortawesome/free-regular-svg-icons'
import { fab } from '#fortawesome/free-brands-svg-icons'
// Add all icons to the library so you can use it in your page
library.add(fas, far, fab)
h1, body{
font-family: 'Roboto', sans-serif;
}
.selected {
border-style: dashed;
}
div {
text-align: center;
border: 1px solid #d3d3d3;
width: 150px;
height: 30px;
padding: 10px;
cursor: move;
z-index: 10;
background-color: white;
color: blue;
}
divWhite {
text-align: center;
border: 1px solid #d3d3d3;
width: 100px;
padding: 10px;
cursor: move;
z-index: 10;
background-color: white;
color: #fff;
}
.blue {
background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%);
color: white;
}
.red {
background: linear-gradient(87deg, #f5365c 0, #f56036 100%);
color: white;
}
.green {
background: linear-gradient(87deg, #2dce89 0, #2dcecc 100%);
color: white;
}
.blue2 {
background: linear-gradient(87deg, #11cdef 0, #1171ef 100%);
color: white;
}
.white {
background: white;
color: white;
}
button{
font-size: .875rem;
border: none;
border-radius: 3px;
height: 40px;
width: 90px;
text-align: center;
position: relative;
transition: all .15s ease;
letter-spacing: .025em;
text-transform: uppercase;
will-change: transform;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<link href="style.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body style="font-family: 'Roboto', sans-serif;">
<body id="container">
<header id="inputAssignments">
<h1 id="mulAsi">Input Your Assignments for the week:</h1>
<h1 style="display:none" id="oneAsi">Input Your Assignment:</h1>
<input id="input" type="text" value="text">
<button class="blue" id="blue" onclick="addElement()" >Make it Purple</button>
<button class="red" id="red" onclick="addElement()" >Make it Red</button>
<button class="green" id="green" onclick="addElement()" >Make it Green</button>
<button class="blue2" id="blue2" onclick="addElement()" >Make it Blue</button>
<button style="display:none" id="blue2" onclick="addElement();" >input</button>
<h1 height="30px"></h1>
</header>
</header>
<script src="script.js"></script>
</body>
</html>
What you want is ...
div dbclick
Remove selected class from div (actually... div.selcted)
Add selected class to div what you dbclicked.
input[type=text] change
set input[type=text].value to div.selcted.innerHTML
When you use jQuery event,
there are two ways to get $this
Let me show you how to solve this problem.
Regular Function
$('#elementId').on('click', function(){
//1. Remove selected class from div
$('div.selected').removeClass('selected');
//2. Add selected class to $this
const $this = $(this);
$this.addClass('selected')
});
Arrow Function
$('#elementId').on('click', (_event) => {
//1. Remove selected class from div
$('div.selected').removeClass('selected');
//2. Add selected class to $this
const $this = $(_event.currentTarget); // important!
$this.addClass('selected')
});
Finally, Change event of input[type=text]
I will skip arrow function this time.
$('#someInput').on('change', function(){
const value = $(this).val();
$('div.selcted').html(value);
});
DONE!
I recommend you to set id or class to your HTML DOM.
If you set event to ['div', 'input' ...], you will get side effect
Not use div, input
Use #element001(best) or div.myElement001
bye bye
The program I am creating is a meme generator. I have a div container set up with display:grid with a few tags inside of that which act as the top and bottom text for the meme. I'm trying to dynamically set the background image for the grid cell using plain vanilla JS. When I attach the link inside the CSS file it works perfectly, but using JS the background-image is never set when i check inside the browser. I put a big arrow so you can see where I am attempting to set the image
const imageLink = document.querySelector('#imageLink');
const topText = document.querySelector('#topText');
const bottomText = document.querySelector('#bottomText');
const memeDiv = document.querySelector('#meme');
//listener for submit
document.addEventListener("submit", function(e) {
e.preventDefault();
//if the user doesn't enter an image, or if they don't enter any text, don't generate the meme when they submit.
if (imageLink.value === "") {
return;
} else if (topText === "" && bottomText === "") {
return;
}
console.log(imageLink.value);
//create elements
var div = document.createElement("div");
//set attribute for div containing our memes
div.setAttribute("id", "meme");
//When the page loads apply the users photo to the background of the grid
window.addEventListener('DOMContentLoaded', function() {
memeDiv.style.backgroundImage = `url(${imageLink.value})`; // < -- -- -
});
//create text and remove button for the memes
const top = document.createElement("p"); //for top text
const bottom = document.createElement("p"); //for bottom text
const removeBtn = document.createElement("input");
//remove button attributes
removeBtn.setAttribute("id", "remove");
removeBtn.setAttribute("type", "image");
removeBtn.setAttribute("height", "200px");
removeBtn.setAttribute("width", "200px");
removeBtn.setAttribute(
"src",
"https://www.freeiconspng.com/uploads/x-png-33.png"
);
//set attributes for text
top.setAttribute("id", "top");
top.innerText = topText.value;
bottom.setAttribute("id", "bottom");
bottom.innerText = bottomText.value;
//put the top and bottom text with the remove button together with the same div
div.appendChild(top);
div.appendChild(bottom);
div.appendChild(removeBtn);
//append to the div
document.querySelector("#memeContainer").appendChild(div);
//reset
imageLink.value = "";
topText.value = "";
bottomText.value = "";
})
document.addEventListener("click", function(e) {
if (e.target.id === "remove") {
e.target.parentElement.remove();
} else {
return;
}
})
* {
margin: 0px;
}
#formContainer {
background-color: blue;
margin-bottom: 5px;
text-align: center;
}
h1 {
text-align: center;
background-color: blue;
margin: 0px;
}
#memeContainer {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 300px);
grid-gap: 5px;
}
#top,
#bottom,
#remove {
position: relative;
display: inline;
}
#top {
left: 225px;
z-index: 1;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#bottom {
top: 300px;
left: 225px;
z-index: 2;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#remove {
top: -150px;
left: 180px;
z-index: 3;
/* filter: opacity(1%); */
}
#remove:hover {
z-index: 3;
filter: opacity(25%);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meme Generator</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
<h1>MEME GENERATOR</h1>
<div id="formContainer">
<form>
<input id="imageLink" type="text" placeholder="please link to an image">
<input id="topText" type="text" placeholder="TOP TEXT">
<input id="bottomText" type="text" placeholder="BOTTOM TEXT">
<button type="submit">submit</button>
</form>
</div>
<div id="memeContainer"></div>
<script src="app.js"></script>
</body>
</html>
The DOMContentLoaded event is only called once whenever all HTML have been loaded. So you are only adding an event listener which never fires and thus nothing happens.
window.addEventListener('DOMContentLoaded', function() {
memeDiv.style.backgroundImage = `url(${imageLink.value})`;
});
Remove the event listener and correct the memeDiv variable name to div and your code will run.
div.style.backgroundImage = `url(${imageLink.value})`;
const imageLink = document.querySelector('#imageLink');
const topText = document.querySelector('#topText');
const bottomText = document.querySelector('#bottomText');
const memeDiv = document.querySelector('#meme');
//listener for submit
document.addEventListener("submit", function(e) {
e.preventDefault();
//if the user doesn't enter an image, or if they don't enter any text, don't generate the meme when they submit.
if (imageLink.value === "") {
return;
} else if (topText.value === "" && bottomText.value === "") {
return;
}
console.log(imageLink.value);
//create elements
var div = document.createElement("div");
//set attribute for div containing our memes
div.setAttribute("id", "meme");
//When the page loads apply the users photo to the background of the grid
div.style.backgroundImage = `url(${imageLink.value})`; // < -- -- -
//create text and remove button for the memes
const top = document.createElement("p"); //for top text
const bottom = document.createElement("p"); //for bottom text
const removeBtn = document.createElement("input");
//remove button attributes
removeBtn.setAttribute("id", "remove");
removeBtn.setAttribute("type", "image");
removeBtn.setAttribute("height", "200px");
removeBtn.setAttribute("width", "200px");
removeBtn.setAttribute(
"src",
"https://www.freeiconspng.com/uploads/x-png-33.png"
);
//set attributes for text
top.setAttribute("id", "top");
top.innerText = topText.value;
bottom.setAttribute("id", "bottom");
bottom.innerText = bottomText.value;
//put the top and bottom text with the remove button together with the same div
div.appendChild(top);
div.appendChild(bottom);
div.appendChild(removeBtn);
//append to the div
document.querySelector("#memeContainer").appendChild(div);
//reset
imageLink.value = "";
topText.value = "";
bottomText.value = "";
})
document.addEventListener("click", function(e) {
if (e.target.id === "remove") {
e.target.parentElement.remove();
} else {
return;
}
})
* {
margin: 0px;
}
#formContainer {
background-color: blue;
margin-bottom: 5px;
text-align: center;
}
h1 {
text-align: center;
background-color: blue;
margin: 0px;
}
#memeContainer {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 300px);
grid-gap: 5px;
}
#top,
#bottom,
#remove {
position: relative;
display: inline;
}
#top {
left: 225px;
z-index: 1;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#bottom {
top: 300px;
left: 225px;
z-index: 2;
font-family: Impact;
font-size: 40px;
/* color:white; */
}
#remove {
top: -150px;
left: 180px;
z-index: 3;
/* filter: opacity(1%); */
}
#remove:hover {
z-index: 3;
filter: opacity(25%);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meme Generator</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
<h1>MEME GENERATOR</h1>
<div id="formContainer">
<form>
<input id="imageLink" type="text" placeholder="please link to an image">
<input id="topText" type="text" placeholder="TOP TEXT">
<input id="bottomText" type="text" placeholder="BOTTOM TEXT">
<button type="submit">submit</button>
</form>
</div>
<div id="memeContainer"></div>
<script src="app.js"></script>
</body>
</html>
I am trying to open a window and process the file in the calling JavaScript. I can pass the file name using localStorage but if I return the file I can't get it right.
I can't use this solution due to restrictions of the system I am calling the JavaScript from:
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.click();
Can a file object be passed using localStorage or should I use another method?
My code is:
<!DOCTYPE html>
<html>
<script language="JavaScript">
function testInjectScript2(){
try {
var myhtmltext =
'<input type="file" id="uploadInput3" name=\"files[]" onchange=\'localStorage.setItem("myfile",document.getElementById("uploadInput3").files[0]);\' multiple />';
console.log("myhtmltext="+myhtmltext);
var newWin2 = window.open('',"_blank", "location=200,status=1,scrollbars=1, width=500,height=200");
newWin2.document.body.innerHTML = myhtmltext;
newWin2.addEventListener("unload", function (e) {
if(localStorage.getItem("myfile")) {
var f = localStorage.getItem("myfile");
alert ('in function.f='+f);
alert ('in function.f.name='+(f).name);
localStorage.removeItem("myfile");
}
});
} catch (err) {
alert(err);
}
}
</script>
<body>
<input type="button" text="testInjectScript2" onclick="testInjectScript2()" value="testInjectScript2" />
</body>
</html>
First of all, welcome to SO. If I get you right, you want to upload a file using a new window and get that file using localStorage onto your main page. This is a possible solution. However, please do also note that the maximum size of the localStorage can vary depending on the user-agent (more information here). Therefore it is not recommend to use this method. If you really want to do this, please have a look at the first snippet.
var read = document.getElementById("read-value"), open_win = document.getElementById("open-win"), win, p = document.getElementById("file-set");
open_win.addEventListener("click", function(){
win = window.open("", "", "width=200,height=100");
win.document.write(
'<input id="file-input" type="file"/>' +
'<script>' +
'var input = document.getElementById("file-input");' +
'input.addEventListener("change", function(){window.localStorage.setItem("file", input.files[0]);})'+
'<\/script>'
);
})
read.addEventListener("click", function(){
var file = window.localStorage.getItem("file");
if(file){
p.innerText = "file is set";
}else{
p.innerText = "file is not set";
}
})
<button id="open-win">Open window</button>
<br><br>
<!-- Check if file is set in localStorage -->
<button id="read-value">Check</button>
<p id="file-set" style="margin: 10px 0; font-family: monospace"></p>
<i style="display: block; margin-top: 20px">Note: This only works locally as SO snippets lack the 'allow same origin' flag. i.e. just copy the html and js into a local file to use it.</i>
However, why not use a more elegant solution:
Simply using a modal. When the input value changes you can simply close the modal and get the file value without all the hassle of a localStorage.
// Get the modal, open button and close button
var modal = document.getElementById('modal'),
btn = document.getElementById("open-modal"),
span = document.getElementById("close"),
input = document.getElementById("file-input"),
label = document.getElementById("input-label"), file;
// When the user clicks the button, open the modal
btn.addEventListener("click", function() {
modal.style.display = "block";
})
// When the user clicks on <span> (x), close the modal
span.addEventListener("click", function() {
modal.style.display = "none";
})
input.addEventListener("change", function(){
file = input.files[0];
modal.style.display = "none";
//Change value of the label for nice styling ;)
label.innerHTML = input.files[0].name;
//do something with your value
})
// When the user clicks anywhere outside of the modal, close it
window.addEventListener("click", function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
})
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 10px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
.modal h2 {
font-family: sans-serif;
font-weight: normal;
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
/* Input styles, added bonus */
.file-input {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.file-input + label {
font-size: 1.25em;
font-weight: 700;
padding: 10px 20px;
border: 1px solid #888;
display: inline-block;
cursor: pointer;
font-family: sans-serif;
}
.file-input:focus + label,
.file-input + label:hover {
background-color: #f7f7f7;
}
<!-- Trigger/Open The Modal -->
<button id="open-modal">Open Modal</button>
<!-- The Modal -->
<div id="modal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span id="close" class="close">×</span>
<h2><i>Upload a file?</i></h3>
<input id="file-input" name="file-input" class="file-input" type="file"/>
<label id="input-label" for="file-input">Upload a file</label>
</div>
</div>
Hope it helps! Let me know!
Cheers!