Replace CHOOSE FILE with an image - javascript

Hi I am trying to replace the choose file button with an image. I am using javascript to create the button but when I am inspecting the website, it shows me a html script of the button which is of type= file.
To create it, I used:
input = createFileInput(handleFile);
input.elt.style["width"] = "40%";
input.elt.style["font-size"]="3vmin";
function handleFile(file) {
print(file);
if (file.type === 'image') {
imgFile = file.data;
img = createImg(file.data);
img.hide();
canvas.image(img, 0, 0, 224, 224);
image(img, 0, 0, width, height/2);
img.remove();
}
mode = 1;
tint = false;
}
Can anyone suggest how I can change the generic button with an image.

I think you can cheat and position an image over the input, then add a click handler to the image and pass it through to the input button below.
Is this what you are trying to achieve?
const input = document.querySelector("#avatar");
const button = document.querySelector("#button");
button.addEventListener('click', event => input.click(event));
.body {
font-family: sans-serif;
}
label {
display: inline-block;
padding: 1em 0;
}
.wrapper {
position: relative;
}
#avatar {
display: block;
height: 50px;
border: 1px solid #333;
}
#button {
position: absolute;
left: 1px;
top: 1px;
}
<div class="body">
<label for="avatar">Choose a profile picture:</label>
<div class="wrapper">
<input type="file" id="avatar" name="avatar">
<img id="button" src="https://via.placeholder.com/75x50/333333/ffffff?text=Avatar"></img>
</div>
</div>

Related

Updating SRC attribute of dynamically loaded image with jQuery

I am trying to dynamically load an image tag, and on the very next line, trying to change its SRC attribute. It is not working. Could it be because it does not allow enough 'time' for the image tag to load into a receptacle DIV (#Div_Extend_2), before its SRC attribute get changed? The whole image upload form is loaded dynamically, and if the image tag is included in the first dynamic inclusion, it works; I am able to change the SRC atribute of the image. But if the img tag is put there using load(), just before the change attribute statement: $("#IMG_wlpst_PREV").attr('src',"IMAGES/Apples_in_a_basket.JPG"); is executed, it doesn't work.
Please note, in the CSS I have put display: none; for the image, when its included as part of the POST_IMG_1.PHP file.
Thank you, all help appreciated!! Please stay safe in this coronavirus period..
The main HTML document is as follows:
<div id='DIV_MAINPOST'>
<div id="DV_post_type">
<div id="div_POST_TXT">TEXT</div>
<div id="div_POST_IMG">Image!</div>
</div>
<div id="DIV_ERROR"> </div>
<div id="Div_Extend_1"> </div>
</div>
Javascript:
$('#DIV_MAINPOST').click(function(e){
switch(e.target.id)
{ case "div_POST_TXT":
$('#Div_Extend_1').html("");
break;
case "div_POST_IMG":
$('#Div_Extend_1').load('POST_IMAGE_1.php');
break;
} });
$('#DIV_MAINPOST').on('submit','#FORM_img', function(e){
alert("formsubmit");
e.preventDefault();
var FD = new FormData(this);
var FIL = FD.get("file_");
var ERS = 0;
if(FIL.length===0)
{ ERS++;
$("#DIV_ERROR").html("Error: No file");
}else if(!((FIL.type=='image/jpeg' ) || (FIL.type=='image/jpg') || (FIL.type=='image/png') || (FIL.type=='image/bmp')))
{ ERS++;
$("#DIV_ERROR").html("Err: Not Image");
}else if(FIL.size > (6*1024*1024)) //> 4MB
{ ERS++;
$("#DIV_ERROR").html("Err: Too Large");
}
if(ERS==0)
{ $("#IMG_wlpst_PREV").show(); //case: 1 tag is present with POST_IMG_1.php, default css is display: none;
$("#Div_Extend_2").load('POST_IMAGE_2.php'); // case: 2 loading tag with this stmt
$("#IMG_wlpst_PREV").attr('src',"IMAGES/Apples_in_a_basket.JPG"); //updating its info
} });
});
POST_IMG_1.PHP
<FORM method='post' action='PHP/FILE_UPLOAD_CHECK.PHP' id="FORM_img" enctype='multipart/form-data'>
<INPUT type='file' name='file_' size='10'></INPUT>
<button type='submit' value='upload'>Upload</button>
</FORM>
<div id="Div_Extend_2">
<img id="IMG_wlpst_PREV"></img> //case 1:: img tag included in the same file (which is also load()'ed, works fine. SRC gets updated.
//case 2:: this tag is not present, but the "Div_Extend_2" div is still present in POST_IMG_1.php.
</div>
POST_IMG_2.PHP
<img id="IMG_wlpst_PREV"></img> //case 2::if loaded using $("#Div_Extend_2").load('POST_IMG_2.PHP'), doesn't work;
CSS
#DIV_MAINPOST
{ width: 310px;
background-color: grey;
display: flex;
flex-direction: column;
}
#DV_post_type
{ order: 1;
flex-direction: row;
display: flex;
}
#div_POST_TXT
{ order: 1;
width: 150px;
border: 2px solid black;
background-color: pink;
}
#div_POST_IMG
{ order: 2;
width: 150px;
border: 2px solid black;
background-color: pink;
}
#DIV_ERROR
{ order: 2;
border: 1px solid red;
width: 300px;
height: 30px;
color: red;
}
#Div_Extend_1
{ order: 3;
}
#IMG_wlpst_PREV
{ display: none; //case 1
width: 300px;
height: 300px;
}

Clear objects properties by button click

There are 5 boxes, which can be changed from 'white'<->'yellow' colors by mouse events (mouseover, mouseout and click). There is also a blue area with text displaying the level of the clicked box.
After clicking into the third box, I got 'hard level' text in blue area and 3 boxes color in yellow.
What I need is to return it to the default level ('easy level' and first box in yellow only) by clicking the reset button.
I have been trying do this like this , but it isn't working:
resetBtn = document.querySelector('#update');
and eventlistener:
resetBtn.addEventListener('click', highlightStars(`#star1`), true)
Here is an example:
window.addEventListener('DOMContentLoaded', changeStars, false);
const resetBtn = document.querySelector('#update');
/* Change level of the game depending on user choice */
function changeStars() {
/* Displaying level text inside blue box */
const updateAltText = currentLevelIndex => {
let levelText = document.querySelector('#level-text');
/* 'currentLevelIndex + 1' replaces event 'currentElement' */
levelText.textContent = document.querySelector(`#star${currentLevelIndex + 1}`).alt;
}
/* Captcha level number - default is 1 */
const getNumber = str => Number(str.match(/\d+/)[0]) || 1;
/* Star index is always one number lower than level number (indexing rules) */
const getStarIndex = event => getNumber(event.target.id) - 1;
let stars = document.querySelectorAll('.star');
const handleStarClick = event => {
/* FIRST - blocking possibility to change star behaviour by mouse events */
gameLevel.removeEventListener('mouseover', highlightStars);
gameLevel.removeEventListener('mouseout', highlightStars);
/* SECOND - making all needed star with yellow color */
const stars = document.querySelectorAll('.star');
for (let i = 0; i <= getStarIndex(event); i++) {
stars[i].classList.add('yellow');
}
};
const highlightStars = event => {
const starIndex = getStarIndex(event);
updateAltText(starIndex);
for (let i = 1; i <= starIndex; i++) {
const star = document.querySelector(`#star${i + 1}`);
star.classList.toggle('yellow');
}
};
// resetBtn.addEventListener('click', highlightStars(`#star1`), true);
resetBtn.addEventListener('click', updateAltText(0), true);
const gameLevel = document.querySelector('.game-level');
gameLevel.addEventListener("mouseover", highlightStars);
gameLevel.addEventListener("mouseout", highlightStars);
gameLevel.addEventListener('click', handleStarClick, {once: true});
}
.stars {
display: flex;
margin: 10px auto;
width: 500px;
}
input[type='image'] {
width: 60px;
height: 60px;
border: thin solid black;
}
.yellow {
background-color: yellow;
}
.game-level {
display: flex;
width: 300px;
height: 100%;
}
.level-block {
display: flex;
width: 200px;
margin-left: 10px;
justify-content: center;
align-items: center;
border: 1px solid hsl(217, 86%, 50%);
border-radius: 25px;
background-color: hsl(212, 29%, 80%);
}
.level-block > span {
font-size: 18px;
}
.reset {
width: 80px;
height: 80px;
}
<div class="stars">
<div class="game-level">
<input type="image" class="star yellow" id="star1" src="" width="60" alt="easy level">
<input type="image" class="star" id="star2" src="" width="60" alt="normal level">
<input type="image" class="star" id="star3" src="" width="60" alt="hard level">
<input type="image" class="star" id="star4" src="" width="60" alt="very hard level">
<input type="image" class="star" id="star5" src="" width="60" alt="impossible level">
</div>
<div class="level-block">
<span id="level-text">Easy level</span>
</div>
</div>
<input type="button" class="reset" id="update" value="RESET">
The following demo uses JavaScript for click events only, all mouse events (ie hover) are pure CSS. The reset behavior simply removes .active class on all buttons then adds .active class to the first button. Instead of the first button title being displayed after a reset -- the reset button title: "Game Reset" is displayed, it might be a little confusing for users if there's no confirmation of a reset. Other behavior is included in demo that is logical and consistent such as toggling, hovering to a temporary state and clicking for a persistent state etc. Details are commented in demo.
// Reference the form
const stars = document.forms.stars;
/*
Register the form to the click event -- when a click occurs anywhere on or within the form, callback function twinkle() is
called
*/
stars.onclick = twinkle;
/**
//A -- twinkle passes a reference to the Event Object... (e)
//B1 - Two Event Object properties are used to reference:
The tag the was clicked by user: event.target
The tag registered to the event: event.currentTarget
//B2 - The HTMLFormElement property: .elements collects all form
controls into a Live HTML Collection (aka NodeList)
//C -- ui.star is a Collection of form controls with [name=star]
The brackets [] and spread operator ... converts the
NodeList into an Array
//D -- Reference the message tag. If the clicked tag was the reset
button -- for...of loop iterates through each [name=star]
and removes the class .active from all [name=star]
//E1 - Next add .active class to the default button
//E2 - Set the legend.message text to the value of clicked button
[title] attribute...
~~~~~~~
//F -- ...But if a button.star was clicked, a check to verify if
clicked tag has the .active class -- then a for...of
loop identical to the one described in line D is used to
remove any .active class.
//G -- After there are no .active, the Boolean declared in line F
determines whether the clicked tag gets the .active class
and its [title] attribute displayed or not
*/
function twinkle(e) {
const active = e.target;
const ui = e.currentTarget.elements;
const starZ = [...ui.star];
const msg = document.querySelector(".message");
if (active.matches("#clear")) {
for (let star of starZ) {
star.classList.remove("active");
}
ui.star1.classList.add('active');
msg.textContent = active.title;
} else if (active.matches(".star")) {
let status = active.classList.contains("active");
for (let star of starZ) {
star.classList.remove("active");
}
if (!status) {
active.classList.add("active");
msg.textContent = active.title;
} else {
active.classList.remove("active");
msg.textContent = "";
}
}
return false;
}
:root {
font: 400 small-caps 2.5vw/1 Arial
}
.levels {
display: table;
width: 96%;
height: auto;
border: 1px solid hsl(217, 86%, 50%);
border-radius:4px;
}
.message {
display: table-caption;
width: 40vw;
height: 6vh;
margin: 0 auto 2vh;
padding: 0.5vh 0;
border: 1px solid hsl(217, 86%, 50%);
border-radius: 1.5rem;
background-color: hsla(212, 29%, 80%, 25%);
text-align: center;
font-size: 1.5rem;
color: #0078D7;
}
#clear {
float: right;
transform: rotate(45deg);
padding: 0;
border: none;
background: none;
font-size: 3.5rem;
cursor: pointer;
}
#clear:focus {
outline: 0;
}
/*
Flex is applied to the button.star'S parent tag so the order
property can be utilized.
*/
.flex {
display: flex;
justify-content: space-evenly;
align-items: center;
width: 70vw;
}
.star {
display: table-cell;
position: relative;
width: 16vw;
height: 24vh;
border: thin solid black;
background: #DDD;
font-size: 3.75rem;
text-align: center;
vertical-align: middle;
cursor: pointer;
}
/*
GSC (General Sibling Combinator: ~ ) provides highlighting across
multiple buttons.
Exp. 5 buttons: [-] [-] [X] ~ [>] ~ [>]
*/
.star.active,
.star:hover,
.star.active ~ .star,
.star:hover ~ .star {
background: gold;
}
/*
HTML layout has button.star in reverse order. Applying order to
each button rectifies the order by APPEARING in order while the
HTML structure remains reversed.
*/
#star1 {
order: 1;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
#star2 {
order: 2;
}
#star3 {
order: 3;
}
#star4 {
order: 4;
}
#star5 {
order: 5;
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
#star1:hover,
#star1.active {
color: #5BC0DE;
}
#star2:hover,
#star2.active {
color: #FF1C8D;
}
#star3:hover,
#star3.active {
color: #00D800;
}
#star4:hover,
#star4.active {
color: #0000D5;
}
#star5:hover,
#star5.active {
color: #D50000;
}
<form id="stars" action="">
<fieldset name="levels" class="levels">
<legend class="message">Novice</legend>
<button id="clear" type="reset" title="Game Reset">🔄</button>
<section class="flex">
<button id="star5" name='star' class="star" title="Master">🟐</button>
<button id="star4" name='star' class="star" title="Expert">🟌</button>
<button id="star3" name='star' class="star" title="Advanced">🟊</button>
<button id="star2" name='star' class="star" title="Intermediate">🟆</button>
<button id="star1" name='star' class="star active" title="Novice">🟂</button>
</section>
</fieldset>
</form>

Drag and Drop input for files not handling files

I've made a form where the user can upload a file and I wanted to add a drag and drop feature so I made it like this:
<small id="filename"></small>
<!-- <input id="thumbnail" type="file" name="thumbnail" class="input input-thumbnail form-control"> -->
<div class="dropzone" id="droparea">
<div class="input-container">
<input type="file" class="dropzone-input" id="thumbnail-input" name="thumbnail">
</div>
<div class="overlay">
<small class="overlay-text" id="overlay-text">Drag and Drop</small>
</div>
</div>
<script>
(function() {
let dropzone = document.getElementById('droparea');
let dropzonetext = document.getElementById('overlay-text');
let filenametext = document.getElementById('filename');
let fileImput = document.getElementById('thumbnail-input');
dropzone.ondrop = function(e) {
e.preventDefault();
this.className = 'dropzone';
dropzonetext.className = 'overlay';
fileImput.files[0] = e.target.files[0];
filenametext = fileImput.files[0].name
};
dropzone.ondragover = function() {
this.className = 'dropzone dragover';
dropzonetext.className = 'overlay dragover';
return false;
};
dropzone.ondragleave = function() {
this.className = 'dropzone';
dropzonetext.className = 'overlay';
return false;
};
}());
</script>
The expected behavior of this code is that the box changes color (controlled by css) whenever the user hovers over it when holding 1 or multiple files (I want to limit it to only accept 1 file). But this does not work.
Also whenever the file is dropped on the box the value of the input should become the file dropped by the user but this is not happening either.
Instead I'm getting this error in the console whenever I drop the file there:
Uncaught TypeError: Cannot read property '0' of undefined
at HTMLDivElement.dropzone.ondrop ((index):79)
dropzone.ondrop # (index):79
With line 79 being: fileImput.files[0] = e.target.files[0];
What is causing this problem?
Here is also the css for the drag and drop:
.dropzone-input{
opacity: 0;
-moz-opacity: 0;
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0)
width: 30vw;
height: 25vh;
z-index:0;
position: absolute;
color: #ccc;
line-height:25vh;
text-align: center;
}
.dragover{
border-color: black;
text-color: black;
}
.dropzone {
width: 30vw;
height: 25vh;
overflow: hidden;
position: relative;
border: 2px dashed #ccc;
}
.overlay {
width: 30vw;
height: 25vh;
position: absolute;
top: 0;
left: 0;
z-index:1;
line-height:25vh;
text-align: center;
}
.overlay-text{
color: darkgrey;
}
.overlay-text.dragover{
text-color: black;
}
**EDIT: **
Someone asked for a screenshot:
you can see the file selected is the one I dropped on the input
The result is that, e.target.files is null. Because you set event ondrop on dropzone, so e.target maybe any ele in dropzone where you drop (detail in the picture test on my local). But some elements don't have files property. The ele which have files property is the input. So you should try 1 option:
Option 1,set the ondrop event for only the input
Option 2, check the e.target .
if(e.target is input) use
fileImput.files[0] = e.target.files[0];
else use
fileImput.files[0] = e.target.parentElement.querySelector('#thumbnail-input').files[0];

hover in css have does no effect when element is hoverd

So I made a bunch of divs stacked on each other, and I want each div to change its background color whenever its hover, but that's not what happens
When I hover an item its background color should change to green,
but it doesn't work even that I wrote div.oldiv:hover{background-color: #48FF0D;}
The problem is probably in CSS code.
Here is a snippet :
body{
background-color: #48FF0D;
}
#bigdiv {
height: 90%;
width: 100%;
}
.oldiv {
height: 0.390625%;
width: 100%;}
div.oldiv:hover{
background-color: #48FF0D;
}
#bigdiv2 {
height: 0;
width: 100%;
}
.btn {
border: none;
color: white;
padding: 14px 28px;
cursor: pointer;
}
.uptodown {
background-color: #e7e7e7;
color: black;
}
.uptodown:hover {
background: #ddd;
}
.l{
float: right;
}
<body>
<script>
var b = "",k = "",a,q,d;
for(a = 0;a<=256;a++){
d =" <div id=\"du\" class=\"oldiv\" style=\"background-color: rgb("+a+","+a+","+a+");\"></div>";
q =" <div id=\"du\" class=\"oldiv\" style=\"background-color:rgb("+(256-a)+","+(256-a)+","+(256-a)+");\"></div>";
b = b+"\n"+d;
k = k+"\n"+q;
}
window.onload = function (){
document.getElementById("bigdiv").innerHTML = b;
document.getElementById("bigdiv2").innerHTML = k;
}
function utd(a){
var bigdiv = document.getElementById("bigdiv");
var bigdiv2 = document.getElementById("bigdiv2");
if(a == 0){
bigdiv.style.height = "0";
bigdiv2.style.height= "90%";
}else{
bigdiv.style.height = "90%";
bigdiv2.style.height= "0";
}
}
</script>
<div id="bigdiv">
</div>
<div id="bigdiv2">
</div>
<div>
<button class="btn uptodown" onclick="utd(0)">white to black</button>
<button class="btn uptodown l" onclick="utd(1)">black to white</button>
</div>
</body>
Don't word about all the Javascript, its just to generate elements and adding them to HTML
I have no idea what the purpose of this code is, but I think I have fixed it..... Whatever it is :P
Your #bigdiv and #bigdiv2 percentage height were not working because the height of the document wasn't 100%. So I just added html, body {height:100%;} to fix that.
/* code added START */
html, body {
height:100%;
}
div.oldiv:hover {
background-color: #48FF0D!important;
}
/* code added END */
body{
background-color: #48FF0D;
}
#bigdiv {
height: 90%;
width: 100%;
}
.oldiv {
height: 0.390625%;
width: 100%;
}
/* div.oldiv:hover{background-color: #48FF0D;} */
#bigdiv2 {
height: 0;
width: 100%;
}
.btn {
border: none;
color: white;
padding: 14px 28px;
cursor: pointer;
}
.uptodown {
background-color: #e7e7e7;
color: black;
}
.uptodown:hover {
background: #ddd;
}
.l {
float: right;
}
<script>
var b = "",k = "",a,q,d;
for(a = 0;a<=256;a++){
d =" <div id=\"du\" class=\"oldiv\" style=\"background-color: rgb("+a+","+a+","+a+");\"></div>";
q =" <div id=\"du\" class=\"oldiv\" style=\"background-color:rgb("+(256-a)+","+(256-a)+","+(256-a)+");\"></div>";
b = b+"\n"+d;
k = k+"\n"+q;
}
function utd(a) {
var bigdiv = document.getElementById("bigdiv");
var bigdiv2 = document.getElementById("bigdiv2");
if(a == 0) {
bigdiv.style.height = "0";
bigdiv2.style.height= "90%";
} else {
bigdiv.style.height = "90%";
bigdiv2.style.height= "0";
}
}
</script>
<div id="bigdiv">
<script>document.write(b);</script>
</div>
<div id="bigdiv2">
<script>document.write(k);</script>
</div>
<div>
<button class="btn uptodown" onclick="utd(0)">white to black</button>
<button class="btn uptodown l" onclick="utd(1)">black to white</button>
</div>
Well, there is no use of Javascript here. I'm not able to understand what problem you're facing but refer here : https://www.w3schools.com/cssref/sel_hover.asp
CSS already has property of hover and can be used like element:hover {your properties inside like whatever event has to be happened on hover}. There is no need to use JS here. Hope this helps.
UPDATE:
I would also suggest you to follow good practice of writing JS code and CSS code in a separate file not in a HTML file.

is there a way to reference a child node and get say an inherited background color?

I was doing some initial testing in jsFiddle as follows: https://jsfiddle.net/6pqxfy2o/
$(function(){
console.log("fired");
$("div").each(function(){
console.log($(this).attr("class"));
console.log($(this).css("background-color"))})
})
.color{
background-color:teal;
}
.dim{
width: 200px;
height: 200px;
}
.sub-dim{
width: 50px;
height:50px;
border: solid 1px white;
}
.ping {
background-color: cyan;
}
.ack {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dim color">
<div class="sub-dim ack">
</div>
<div class="sub-dim ping">
</div>
<div class="sub-dim">
</div>
</div>
This was showing that when running, it did not actually pass the inherited color into the child.
I am curious though how I can get the background color of the sub-dim which has no background color, such as: current background-color or nearest.
My end goal would be to say: When iterating over sub-dim to return [red, cyan,teal] or color codes. Based on the item I gave you, the div is transparent and the parent's color is showing through.
If the color is transparent, you can just set it to inherit and get the new computed color.
// Some browsers say "transparent" and some "rgba(0, 0, 0, 0)"
var transparent = (function() {
var backup = document.body.style.backgroundColor;
document.body.style.backgroundColor = 'transparent';
var bg = getComputedStyle(document.body).backgroundColor;
document.body.style.backgroundColor = backup;
return bg;
})();
[].forEach.call(document.getElementsByTagName("div"), function(el) {
var bg = getComputedStyle(el).backgroundColor;
if (bg === transparent) {
var backup = el.style.backgroundColor;
el.style.backgroundColor = 'inherit';
bg = getComputedStyle(el).backgroundColor;
el.style.backgroundColor = backup;
}
console.log(el.className, ":", bg);
});
.color {
background-color: teal;
}
.dim {
width: 200px;
height: 200px;
}
.sub-dim {
width: 50px;
height: 50px;
border: solid 1px white;
}
.ping {
background-color: cyan;
}
.ack {
background-color: red;
}
<div class="dim color">
<div class="sub-dim ack"></div>
<div class="sub-dim ping"></div>
<div class="sub-dim"></div>
</div>
I'm not sure I completely understand the problem, but you could try
.sub-dim.ack {
background-color: red;
}
or
.ack, .ack * {
background-color: red;
}
Obviosly try to be ore specific with which child elements you'd like to target.
This would likely be a lot easier in SASS.

Categories