Multiple instances of "add another photo" button - show div - javascript

I have a div that contains a file uploader. Next to this, there is an 'Add Photo' button.
This button once clicked should be hidden, and then reveal another file uploader div with another 'Add Photo' button, which will in turn hide/reveal another button & div upon click.
Anyone able to help? Apparently I cannot just copy the JS and repeat it to affect other ID's
const btn = document.getElementById('btnhide');
btn.addEventListener('click', () => {
btn.style.display = 'none';
// 👇️ show div
const box = document.getElementById('myDIV1');
box.style.display = 'block';
});
<div class="form-content block">
<div class="one">
<label>Photo Upload <em class="tooltip">*<span class="tooltiptext">Required</span></em></label>
</div>
<div class="two">
<input type="file" name="FileUpload" checktype="c1">
<p id="FileUpload_error" style="display: none;">Choose any file for this field.</p>
<p>Please make sure each photo is 20MB or less, thank you. <button id="btnhide" type="button">Add Photo</button></p>
</div></div>
<div class="form-content block" id="myDIV1" style="display:none;">
<div class="one">
<label>Photo Upload <em class="tooltip">*<span class="tooltiptext">Required</span></em></label>
</div>
<div class="two">
<input type="file" name="FileUpload1" checktype="c1">
<p id="FileUpload_error1" style="display: none;">Choose any file for this field.</p>
<p>Please make sure each photo is 20MB or less, thank you. <button id="btnhide1" type="button">Add Photo</button></p>
</div></div>
<div class="form-content block" id="myDIV2" style="display:none;">
<div class="one">
<label>Photo Upload</label>
</div>
<div class="two">
<input type="file" name="FileUpload2" checktype="c1">
<p id="FileUpload2_error" style="display:none;">Choose any file for this field.</p>
<p>Please make sure each photo is 20MB or less, thank you. <button id="btnhide2" type="button">Add Photo</button></p>
</div></div>

From the question comments:
I am following the [HTML] ... supplied ... as I am too inexperienced to
build from scratch.
So...without changing any HTML provided in the question...
...use Javascript to add a click event listener to each "Add Photo" button, that when clicked will navigate to its parent photo upload div, get the next photo upload div, display that, and finally hide itself (button only):
// get all buttons within divs having className "form-content button"
const btns = document.querySelectorAll("div.form-content button");
// interate over resulting button array
btns.forEach((btn, ii) => {
// add a click event listener to each one
btn.addEventListener("click", evt => {
// navigate up to the parent "form-content block" div
// then get the next sibling and assign to photoupload
// DIV.form-content+block > DIV.two > P > BUTTON
const photoupload = evt.target.parentNode.parentNode.parentNode.nextElementSibling;
// if the next sibling is also a "form-content block" div, i.e., this is not the last photoupload,
// display the next "form-content block" div
if ( "form-content block" === photoupload.className ) {
photoupload.style.display = "block";
}
// hide this "Add Photo" button
btn.style.display = "none";
});
// and hide last "Add Photo" button——to not perplex people
if ( btns.length - 1 === ii ) { btn.style.display = "none"; }
});
<div class="form-content block">
<div class="one">
<label>Photo Upload <em class="tooltip">*<span class="tooltiptext">Required</span></em></label>
</div>
<div class="two">
<input type="file" name="FileUpload" checktype="c1">
<p id="FileUpload_error" style="display: none;">Choose any file for this field.</p>
<p>Please make sure each photo is 20MB or less, thank you. <button id="btnhide" type="button">Add Photo</button></p>
</div></div>
<div class="form-content block" id="myDIV1" style="display:none;">
<div class="one">
<label>Photo Upload <em class="tooltip">*<span class="tooltiptext">Required</span></em></label>
</div>
<div class="two">
<input type="file" name="FileUpload1" checktype="c1">
<p id="FileUpload_error1" style="display: none;">Choose any file for this field.</p>
<p>Please make sure each photo is 20MB or less, thank you. <button id="btnhide1" type="button">Add Photo</button></p>
</div></div>
<div class="form-content block" id="myDIV2" style="display:none;">
<div class="one">
<label>Photo Upload</label>
</div>
<div class="two">
<input type="file" name="FileUpload2" checktype="c1">
<p id="FileUpload2_error" style="display:none;">Choose any file for this field.</p>
<p>Please make sure each photo is 20MB or less, thank you. <button id="btnhide2" type="button">Add Photo</button></p>
</div></div>
Using Javascript functions and properties: querySelectorAll(), forEach(),
addEventListener(), event.target, parentNode, nextElementSibling, and className.

Related

Is there a way target an element without it's class or id

I have a show more button I want to expand a div with it, I can put the button in the div and target it's parent but I don't want it to be on top of the div which I want to expand and if I put it in the end the button hides with the text, I am gonna have more than one div, and I can keep the button outside the div and target the div using it's class but the reason I am gonna have more than one div the first div will expand not matter which button I click, and I don't wanna give each div an unique class or Id and I don't want to place the button in the div I already mentioned the reason, so is there a way to directly target the div or to place button in the div and still have it to be shown on the bottom without it being hidden
CODE
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon">
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content </p>
</div>
<button id="showmore" onclick=" this.parentElement.style.maxHeight = 'none'"> show more </button>
Someone told me to target the show more button from its Id then target it's upper sibling but it doesn't work.
At very first you named the Button opening tag with camelcase (first letter uppercase), the closing tag is lowercase.
Second I changed the "showmore" id to class. And please see the script what I made for you.
You can remove the class of the buttons also if you using getElementsByTag("button").
const buttons = document.getElementsByClassName("showmore");
console.log(buttons);
Array.from(buttons).forEach(button => button.addEventListener("click", (e)=> {
e.preventDefault();
const collapse = button.previousElementSibling; //https://www.w3schools.com/jsref/prop_node_previoussibling.asp
collapse.style.maxHeight = collapse.style.maxHeight == '0px' ? '200px' : '0px';
}));
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon" >
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content
</p>
</div>
<button class="showmore"> show more </button>
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon" >
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content
</p>
</div>
<button class="showmore"> show more </button>
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon" >
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content
</p>
</div>
<button class="showmore"> show more </button>

JavaScript show/hide divs on button click - multiple per page

I am trying to develop a page where there would be multiple divs, each of these divs have a button of which would show a "dropdown" style div below it when clicked.
Currently I have some code which when one button is clicked, it shows all of the "dropdown" styled divs on the page instead of just the one in the same container as the button.
I would like this to be done in pure JavaScript without jquery, any help would be appreciated, thank you!
HTML
<div class="fullResultsContainer">
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog()"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog()"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
</div>
JS
function mobileActivityLog() {
var btn = document.getElementsByClassName("mobileShowActivityFeedBtn");
var activity = document.getElementsByClassName("mobileDropDown");
for(var i=0; i<btn.length; i++) {
for(var j=0; i<activity.length; j++) {
if(activity[j].style.display == "none") {
activity[j].style.display = "flex"
} else {
activity[j].style.display = "none"
}
}
}
}
I think the easiest way is to send a parameter to the method and getElementById with a concatenated string with the parameter.
<div class="fullResultsContainer">
<div class="resultContainer">
<div class="resultRow">
<div class="resultMenu">
<button onclick="mobileActivityLog(1)"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown-1">
<p> This is the content I want to show on button click</p>
</div>
</div>
<div class="resultContainer">
<div class="resultRow">
<div class="resultMenu">
<button onclick="mobileActivityLog(2)"> Show activity feed </button>
</div>
</div>
<div id="mobileDropDown-2">
<p> This is the content I want to show on button click</p>
</div>
</div>
</div>
JS
function mobileActivityLog(index) {
var activity = document.getElementsById("mobileDropDown-" + index);
if(activity.style.display == "none") {
activity.style.display = "flex"
} else {
activity.style.display = "none"
}
}
One of the best possible ways to achieve this is to pass the current context using 'call' in the HTML. Use this context to target the required result container(here 'mobileDropDown' container).
function mobileActivityLog () {
var _this = this;
var activity = _this.closest('.resultContainer').querySelector(".mobileDropDown");
activity.classList.toggle('hide');
}
.hide {
display: none;
}
<div class="fullResultsContainer">
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog.call(this)"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog.call(this)"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
</div>

Eventlistener on button to display div

Need to display a div when the user clicks the button.
//html-code
<div class="col-md-4">
<h4 class="service-heading">Sociala Medier</h4>
<p class="text-muted">first line of text.</p>
<div class="info-text" style="display:none">
<p class="text-muted">Second line of text.</p>
</div>
<button class="info-button"><span>Läs mer </span></button>
</div>
//js-code
document.getElementByClassName("info-button").addEventListener("click", function(){
document.getElementByClassName('info-text').style.display = "block";
});
Any advice how I can get this to work? Also tested with onclick but that doesn't work either.
You're passing elements classes to the .getElementById function. In short, you could change your HTML to this:
<div class="col-md-4">
<h4 class="service-heading">Sociala Medier</h4>
<p class="text-muted">first line of text.</p>
<div id="info-text" style="display:none">
<p class="text-muted">Second line of text.</p>
</div>
<button id="info-button"><span>Läs mer </span></button>
</div>
And it would work
It's actually "getElementsByClassName" you missed the s and it gets a collection so you need to be specific on which one you are targeting. Given your code, you want the first/only element
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
https://jsfiddle.net/cbye0ph9/
document.getElementsByClassName("info-button")[0].addEventListener("click", function(){
document.getElementsByClassName('info-text')[0].style.display = "block";
});

Select parent ID always returns undefined

I am working on an application, where there is a requirement of uploading an image in the modal, and show the image in a preview div on close of the modal. I am having difficulty accessing the ID of the parent, as it always returns undefined. I am not able to figure out why this is happening. This is what I have tried so far. I am posting the necessary JS and HTML. I have a total of 4 modals each having a different ID, and functionality will work same for all 4 modals.
var $contactPhotos = $contactForm.find(".koh-contact-photo");
$contactPhotos.each(function() {
var $photoInput = $(this).find("input[type=file]");
function readURL(input) {
if (input.files && input.files[0]) {
var photoPreview = $photoInput.parent().find(".preview");
photoPreview.html("");
var reader = new FileReader();
reader.onload = function(e) {
var img = $("<img />");
img.attr("style", "height:41px;");
img.attr("src", e.target.result);
photoPreview.append(img);
}
reader.readAsDataURL(input.files[0]);
}
}
<div class="koh-contact-photo">
<span><fmt:message key='photo1' /></span> <label id="upload-1" class="button-default"><fmt:message
key='photo.upload' /></label>
<div class="preview"></div>
<button type="button" class="koh-photo-remove" style="background:#FFF;border:1px solid #77777A;">
<span class="icon" data-icon="&#xe605"></span> <span
class="label"><fmt:message key='photo.remove.text' /></span>
</button>
<!-- The Modal -->
<div id="myModal1" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">Ă—</span>
<h3 class="modal-title"> Upload Photo 1 </h3>
<div class="modal-inner">
<span>Browse for a photo</span> <label style="margin-bottom:20px;" class="button-default browse" for="photo1">BROWSE</label><input id="photo1" type="file" name="photo1" data-parsley-filesize="3" data-parsley-filetype="image/jpeg, image/png, image/gif, image/bmp"
data-parsley-trigger="change" />
<hr class="modal-hr" />
<div class="guidelines-modal">
<p> GENERAL GUIDELINES </p>
<p> Supported files are: .jpg, .gif, .png, .bmp </p>
<p> Maximum File Size: 3MB</p>
<p style="margin-bottom:10px;"> For best results: upload at 400 x 300</p>
<p> Note: images are automatically resized</p>
</div>
<div class="koh-contact-captcha modal-hr">
<!--div class="g-recaptcha" data-sitekey=<fmt:message key='kohlerSterling.google.captcha.key' />></div-->
<!--div class="g-recaptcha" id="recaptcha1"></div-->
<div id="recaptcha3" class="captcha"></div>
<div class="error-message">
<span><fmt:message key='required.field.text' /></span>
</div>
</div>
<div class="terms-modal">
<div class="checkbox">
<input type="checkbox" id="terms-condns" />
<label style="font-family:Helvetica Neue LT Pro Roman !important;font-size:12px !important;color:#000 !important;font-weight:400 !important;" for="terms-condns">I agree to the <a class="modal-anchor" href="#">Terms and Conditions</a></label>
</div>
</div>
<hr class="modal-hr" />
<div class="modal-buttons">
<label class="button-default-modal" style="margin-right:20px;">CANCEL</label>
<label class="input-button-modal">UPLOAD</label>
</div>
</div>
</div>
<input type="hidden" id="captchaKey" value="<fmt:message key='google.recaptcha.site.key'/>">
</div>
</div>
When I click on the upload button, I want to select the div with class "preview". Any help is appreciated.
.find() will get elements which are descendants of selected element.
Without looking too deep in code I think this can be part that you can improve
var photoPreview = $photoInput.parent().find(".preview"); line.
If $photoInput has a parent div with class name "preview" , you can select it with
$photoInput.parent(".preview");

Closing spoiler when clicking another spoiler

I have the following problem, I would like to create a few spoilers. This has worked so far, but I would like that if a spoiler is open and one clicks on another, the opened again closes.
<button title="Click to show/hide content" type="button" onclick="if(document.getElementById('spoiler') .style.display=='none') {document.getElementById('spoiler') .style.display=''}else{document.getElementById('spoiler') .style.display='none'}">Show/hide</button>
<div id="spoiler" style="display:none">
Content
</div>
<br><br>
<button title="Click to show/hide content" type="button" onclick="if(document.getElementById('spoiler2') .style.display=='none') {document.getElementById('spoiler2') .style.display=''}else{document.getElementById('spoiler2') .style.display='none'}">Show/hide</button>
<div id="spoiler2" style="display:none">
Content2
</div>
Assign a common class to all spoilers and on click hide the contents of all the spoilers using the class name and simply show only the one you want to show:
I have created a function for this like so:
<script>
function showSpoiler(spoilerId)
{
var spoilers = document.getElementsByClassName('spoilers');
for(var i=0;i<spoilers.length; i++)
{
spoilers[i].style.display = "none";
}
document.getElementById(spoilerId).style.display = "block";
}
</script>
<button title="Click to show/hide content" type="button" onclick="showSpoiler('spoiler');">Show/hide</button>
<div id="spoiler" class="spoilers" style="display:none">
Content
</div>
<br><br>
<button title="Click to show/hide content" type="button" onclick="showSpoiler('spoiler2');">Show/hide</button>
<div id="spoiler2" class="spoilers" style="display:none">
Content2
</div>
spoilers is the common class which needs to be hidden before showing the specific one.
Remember
getElementsByClassName() gives out an array that is why the for loop is in place.
To make it easier for you to start, I'll give you an example made for Event Listener for Radio buttons.
code:
document.getElementById("type_test").addEventListener("click", functio_test);
document.getElementById("type_test1").addEventListener("click", functio_test);
function functio_test(){
var x = document.querySelector('input[name="type_test"]:checked').value;
//var x = document.forms[0].elements.type_test.value;
if(x == "ola"){
alert("Ola José");
document.getElementById('disp_0').style.display = 'block';
document.getElementById('disp_1').style.display = 'none';
}
else if(x == "adeus"){
alert("Adeus José");
document.getElementById('disp_1').style.display = 'block';
document.getElementById('disp_0').style.display = 'none';
}
else {
alert("Continua José");
}
}
<div id="select_0">
<br> <input id = "type_test" type="radio" name="type_test" value="ola"> ola
<input id = "type_test1" type="radio" name="type_test" value="adeus"> adeus <br/> <br><br/>
</div>
<div id="disp_0" style="display:none">
<input type="text" name="lastname" value="ola Jose" ><br><br/>
</div>
<div id="disp_1" style="display:none">
<input type="text" name="lastname1" value="Adeus Jose" ><br><br/>
</div>
I hope the post helps you.
you can use classes to accomplish this (class="spoilers")
<button title="Click to show/hide content" type="button" onclick="toggleSpoiler('spoiler')"> Show/hide </button>
<div id="spoiler" style="display:none" class="spoilers">
Content
</div>
<br><br>
<button title="Click to show/hide content" type="button" onclick="toggleSpoiler('spoiler2')"> Show/hide </button>
<div id="spoiler2" style="display:none" class="spoilers">
Content2
</div>
<script>
function toggleSpoiler(id) {
var spoilers = document.getElementsByClassName("spoilers");
for(var i = 0; i < spoilers.length; i++) {
if (spoilers[i].id != id) {
spoilers[i].style.display = "none";
}
}
if(document.getElementById(id).style.display=='none') {
document.getElementById(id).style.display='';
} else {
document.getElementById(id).style.display='none';
}
}
</script>
The way I would do this would be to create two additional classes and add an additional div to use the parent/child association to determine which spoiler (in relation to the button) needs to be displayed.
Starting off with the classes, let's call them
.spoiler
and
.active
The idea is to make the .spoiler class hide and the .active class show, like so:
.spoiler {
display:none;
}
.spoiler.active {
display:block;
}
All spoiler elements would have .spoiler as a class and only the currently active spoiler would have the .active class, now let's create our new div which will bundle the spoilers and their buttons to have a common parent.
<div class="spoiler-item">
<button title="Click to show/hide content">
Show/Hide
</button>
<div class="spoiler">
Content
</div>
</div>
<div class="spoiler-item">
<button title="Click to show/hide content">
Show/Hide
</button>
<div class="spoiler">
Content2
</div>
</div>
Now we can use the relative "spoiler-item" class when a button is pressed to determine which spoiler is related to the button being pressed and also remove the "active" class from all other "spoiler" elements to make sure only one spoiler is shown at a time.
I recommend using jQuery for this, due to time constraints I'm not going to be able to do it in pure JS.
$(document).ready(function() {
$('.spoiler-item button').click(function(e) {
if($(this).parent('.spoiler-item').find('.spoiler').hasClass('active')) { // If the item we've selected is already active
$(this).parent('.spoiler-item').find('.spoiler').removeClass('active');
return;
}
$('.spoiler.active').removeClass('active'); // Close all open spoilers
$(this).parent('.spoiler-item').find('.spoiler').addClass('active'); // Open relative spoiler
});
});
See JSFiddle for working answer: https://jsfiddle.net/vvm4xe0m

Categories

Resources