I want to hide the divi when I click the button and open it when I click it again. But I couldn't run the normally working code, what could be the reason?
The js code works when there is only one div, but it does not work due to this code I wrote, but I can't solve the problem.
Razor Page
#for (int i = 0; i < Model.quest.Count; i++)
{
<div class="row mt-12" >
<div class="col-md-1">
<input type="checkbox" id="questcb" asp-for="#Model.quest[i].check">
<span>#(i + 1) Soru</span>
</div>
<div class="col-md-9">
<textarea class="form-control" asp-for=#Model.quest[i].Question rows="3" id="question" hidden></textarea>
<label>#Model.quest[i].Question</label>
</div>
</div>
<div class="row mt-12">
<div class="col-md-1" hidden>
<button class="btn btn-outline-secondary" type="button" id="A" onclick="clickFunc(this.id)">A</button>
</div>
<div class="col-md-1" >
A)
</div>
<div class="col-md-11" hidden="hidden">
<input type="text" asp-for=#Model.quest[i].Answer1 class="form-control" placeholder="" id="answer"
aria-label="Example text with button addon" aria-describedby="button-addon1">
</div>
<div class="col-md-11" id="Amod_#i" style="display:inline-block">
#Model.quest[i].Answer1
</div>
<div class="col-md-2">
<button class="btn btn-primary" type="button" id="mod_#i" onclick="question(this.id)">Cevapları Görüntüle</button>
</div>
</div>
}
js code
let question = button => {
let element = document.getElementById(`A${button}`);
let buttonDOM = document.getElementById(`${button}`)
let hidden = element.getAttribute("hidden");
if (hidden) {
element.removeAttribute("hidden");
buttonDOM.innerText = "Cevapları Gizle";
}
else {
element.setAttribute("hidden", "hidden");
buttonDOM.innerText = "Cevapları Görüntüle";
}
}
</script>
If the id of div is unique in your code,your js should work.If it still doesn't work,you can try to find the div with the position of the button:
let question = button => {
let element = $("#" + button).parent().siblings(".col-md-11")[1];
let buttonDOM = document.getElementById(`${button}`);
if (element.hidden) {
element.removeAttribute("hidden");
buttonDOM.innerText = "Cevapları Gizle";
}
else {
element.setAttribute("hidden", "hidden");
buttonDOM.innerText = "Cevapları Görüntüle";
}
}
result:
Related
I'm creating a comment and reply system, but I can't get the reply button to display the input field for only the comment.
When the any reply button is clicked, all the input fields displays instead of just the one clicked
This is my javascript:
function reply() {
var doc;
doc=document.getElementsByClassName("sho") ;
for (var i = 0 ; i < doc.length; i++){
doc[i].style.display="block ";
}
}
$('.btn-reply').on("click", function () {
var parent_dom = $(this).parent();
var _input_child_dom = $(parent_dom).children("input");
var find_allInput = $('.reply-container').find("input");
if(find_allInput.length > 0 ){
for (var i = 0; i < find_allInput.length; i++) {
$(find_allInput[i]).css("display" , "none");
}
}
$(_input_child_dom).css("display" , "block");
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="reply-container">
<div class="reply">
<p>First reply</p>
<button class="btn btn-primary btn-reply">reply</button>
<input type="text" class="InputReply" style="display: none;">
</div>
<br>
<div class="reply">
<p>Second reply</p>
<button class="btn btn-primary btn-reply">reply</button>
<input type="text" class="InputReply" style="display: none;">
</div>
<br>
<div class="reply">
<p>Third reply</p>
<button class="btn btn-primary btn-reply">reply</button>
<input type="text" class="InputReply" style="display: none;">
</div>
</div>
Note: This is the idea of how you can achieve your requirement.
I am trying to learn some javascript in web programming. Starting with a simple school registration webpage: the webpage allows to dynamically create any number of grades by clicking "Grade+" button; under each grade, any number of students can be created by clicking "Student+" button. "Grade+" button works as expected, however clicking "Student+" button does not present the student information, not sure what is happening. Any help will be highly appreciated. Thanks in advance.
The reference codes:
<!DOCTYPE html>
<html>
<body>
<div>
<label>Registration</label>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div id="student">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idGradeRootCopy', false)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true)">Grade+</button>
</div>
</div>
<script>
var count = 0;
function addItem(id, index, root) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display='block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
original.insertBefore(clone, before);
}
}
</script>
</body>
</html>
If you open up the developer tools of your browsers and click the Student+ button you'll get an error message like:
Uncaught DOMException: Node.insertBefore: Child to insert before is
not a child of this node
So you're actually trying to put the cloned node into the wrong spot. Either way things are a bit confusing. Let's say you have clicked the Grade+ button three times and now you decide to click on Student+ of the first clone - how should it know where to put the student as there are three grades?
Well there's a fix of course. Each Student+ button is a child of an unique clone of the school <div> which you also gave an unique id yet (school1, school2,...). So if you pass the addItem() function a reference to the button you actually clicked, we can get it's parent div like:
clickedElement.parentNode.parentNode.parentNode
and add the cloned node using appendChild() instead of insertBefore().
Here's an example (just click on 'Run code snippet'):
var count = 0;
function addItem(id, index, root, clickedElement) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
clickedElement.parentNode.parentNode.parentNode.appendChild(clone);
}
}
<div>
<label>Registration</label>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div id="student">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idGradeRootCopy', false,this)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true,this)">Grade+</button>
</div>
</div>
Update
If you click on the Grade+ button, it will automatically also 'create' a student input field as it's div is part of the school div. So move it out of the school div and change it's display mode to none.
If you want the new student input field to appear right before the Student+ button, we indeed need to use .insertBefore().
Here's the modified example:
var count = 0;
function addItem(id, index, root, clickedElement) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
clickedElement.parentNode.insertBefore(clone, clickedElement);
}
}
<div>
<label>Registration</label>
<div id="student" style="display:none">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idStudentRootCopy', false,this)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true,this)">Grade+</button>
</div>
</div>
I made a JQuery function to check for empty required fields inside a closed custom dropdown.
If a required field is empty inside one of the dropdown and if the dropdown is currently closed I want the dropdown to open and if there are no empty values in the required fields I want the dropdown to close.
The problem is that the required fields aren't accessible if the dropdowns are closed and I tried to fix that problem with this function.
For some reason, it only checks for these input fields if the form is submitted at least once and the required fields are opened at least once.
find(':input[required]') doesn't give any output if the dropdown isn't opened at least once, once u open and close the dropdown the function works.
This is the function:
function dropdown_required() {
var required = 0;
$('#visible_fields').find(':input[required]').each(function () {
if (!this.value) {
for (var i = 1; i < 15; i++) {
$('.form_' + i).find(':input[required]').each(function () {
$(this).prop('required', false);
});
}
required++;
}
});
if (required == 0) {
for (var i = 1; i < 15; i++) {
var empty = 0;
$('.form_' + i).find(':input[required]').each(function ()
{
if(!this.value) {
empty++;
}
});
if (empty !== 0) {
if ($(".arrow_" + i).hasClass("rotate_2")) {
$(".arrow_" + i).addClass("rotate_1").removeClass("rotate_2");
$(".form_" + i).fadeToggle();
}
} else if ($(".arrow_" + i).hasClass("rotate_1")) {
$(".arrow_" + i).addClass("rotate_2").removeClass("rotate_1");
$(".form_" + i).fadeToggle();
}
}
}
}
This is the html:
<form method="POST" autocomplete="off" enctype="multipart/form-data" target="_self"
action="/contacten/leveranciers/iframe{{ ($leverancier == null ? '' : '/' . $leverancier->cot_id) }}">
{{ csrf_field() }}
<div id="visible_fields">
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label for="organisatie">Organisatie</label>
<input type="text" name="organisatie" id="organisatie" blocked=",;()/" hk="a"
value="{{ ($leverancier == null ? old('organisatie') : $leverancier->cot_organisatie) }}"
class="form-control inputblocked">
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="postcode">Postcode</label>
<input type="text" name="postcode" id="postcode" filter="a-zA-Z0-9" maxlength="6"
value="{{ ($leverancier == null ? old('postcode') : $leverancier->cot_postcode) }}"
class="form-control inputfilter filter_postcode">
</div>
</div>
</div>
//all visible input fields outside of the dropdowns
</div>
<label class="toggle_1">Controles<span class="arrow_1 glyphicon glyphicon-menu-left"
aria-hidden="true"></span></label>
<div class="form_1">
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label for="bkr">BKR</label>
<select name="bkr" class="form-control" required>
<option selected hidden></option>
<option value="10">BKR toetsing open</option>
<option value="11">BKR toetsing accoord</option>
<option value="12">Vrijgesteld van BKR toetsing</option>
</select>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="bkr_bestand">BKR bestand</label>
<input type="file" name="bkr_bestand" id="bkr_bestand"
data-default-file=""
class="form-control dropify">
<input type="hidden" name="verwijder_foto" class="verwijder_foto" value="0">
</div>
</div>
</div>
</div>
<div class="form-group">
<input type="hidden" id="input_iframe" name="input_iframe" value="">
<button type="submit" onclick="dropdown_required()"
class="btn btn-primary">Toevoegen </button>
</div>
</form>
</div>
</body>
</html>
Your function checks if your arrow element has the class rotate_2. The code you pasted has neither rotate_1 or rotate_2 and no else block, so the toggle never executes.
Problem demonstration:
// This group has empty mandatory elements
var empty = 1;
$('#validate').click(function() {
if (empty !== 0) {
console.log("I have empty elements!");
// From your comments, this might be backwards
if ($(".arrow_1").hasClass("rotate_2")) {
console.log("I'm going to show them");
$(".arrow_1").addClass("rotate_1").removeClass("rotate_2");
$(".form_1").fadeToggle();
}
// This is missing in the code
else {
console.log("I wasn't invited to the party");
}
// -------
} else if ($(".arrow_1").hasClass("rotate_1")) {
console.log("I'm out, I don't have empty elements...");
$(".arrow_1").addClass("rotate_2").removeClass("rotate_1");
$(".form_1").fadeToggle();
}
});
$('#simulate').click(function() {
// Simulates manually opening and closing
// In short, add rotate_2 class as if it's been toggled
$('.arrow_1').addClass('rotate_2');
console.log("Toggled manually");
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="toggle_1">Controles<span class="arrow_1 glyphicon glyphicon-menu-left"
aria-hidden="true"></span></label>
<div class="form_1">
<div>Some form elements</div>
</div>
<button id="validate">Validate</button>
<button id="simulate">Simulate</button>
Creating Dynamic new fields seems to clear the already existing fields
Also not trying to have multiple elements with the same id hence why i don't believe appendChild will work. Perhaps you can find a way to do that while creating different IDs?
Any help welcomed =)
var template;
var a = 1;
window.onload = function() {
template = document.querySelector("#wrapper").innerHTML;
document.querySelector("#more_fields").addEventListener("click", function(e) {
e.preventDefault(); // tell the browser to not send the form
document.getElementById('wrapper').innerHTML += template; // add next segment
document.querySelector("#wrapper > label:last-of-type").innerHTML = "Segment " + (++a) + ":";
});
}
.form-group {
display: inline
}
#wrapper > label {
margin: 0 0 10px 210px;
}
.segment {
display: inline-block;
margin: 0 0 1em
}
.form-group > label {
margin: 0 0 10px 20px;
}
.form-group > input {
width: 15%
}
<div class="container">
<h2>Form</h2>
<form>
<div id="room_fields">
<div class="content" id="wrapper">
<label style:>Segment 1:</label>
<div class="segment">
<div class="form-group">
<label>IN:</label>
<input name="seg-in[]" type="text">
</div>
<div class="form-group">
<label>OUT:</label>
<input name="seg-out[]" type="text">
</div>
<div class="form-group">
<label>Duration:</label>
<input name="seg-dur[]" type="text">
</div>
</div>
</div>
</div>
<br><br>
<div style="text-align: right;">
<button id="more_fields">+</button>
</div>
<br>
<br>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
innerHTML will not include the current value entered IIRC but it's still strange that doing += operation will remove the existing value.
However, insertAdjacentHTML() should work as expected.
var template;
var a = 1;
window.onload = function() {
template = document.querySelector("#wrapper").innerHTML;
document.querySelector("#more_fields").addEventListener("click", function(e) {
e.preventDefault(); // tell the browser to not send the form
document.getElementById('wrapper').insertAdjacentHTML('beforeend', template); // add next segment
document.querySelector("#wrapper > label:last-of-type").innerHTML = "Segment " + (++a) + ":";
});
}
.form-group {
display: inline
}
#wrapper > label {
margin: 0 0 10px 210px;
}
.segment {
display: inline-block;
margin: 0 0 1em
}
.form-group > label {
margin: 0 0 10px 20px;
}
.form-group > input {
width: 15%
}
<div class="container">
<h2>Form</h2>
<form>
<div id="room_fields">
<div class="content" id="wrapper">
<label style:>Segment 1:</label>
<div class="segment">
<div class="form-group">
<label>IN:</label>
<input name="seg-in[]" type="text">
</div>
<div class="form-group">
<label>OUT:</label>
<input name="seg-out[]" type="text">
</div>
<div class="form-group">
<label>Duration:</label>
<input name="seg-dur[]" type="text">
</div>
</div>
</div>
</div>
<br><br>
<div style="text-align: right;">
<button id="more_fields">+</button>
</div>
<br>
<br>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
Basically, my below code is not 100% correct, you should alter it by yourself following mine.
In the HTML, you can define a hidden div which is your wrapper. In its and nested element ids, you can set a pattern like '$$$'.
<div class="content" id="wrapper$$$" sytle="visibility: hidden;">
<label style:>Segment 1:</label>
<div class="segment">
<div class="form-group">
<label>IN:</label>
<input name="seg-in[]" type="text">
</div>
<div class="form-group">
<label>OUT:</label>
<input name="seg-out[]" type="text">
</div>
<div class="form-group">
<label>Duration:</label>
<input name="seg-dur[]" type="text">
</div>
</div>
</div>
In your javascript, declare a global variable named index and replace index value with '$$$'. It will be increased 1 when you add your template dynamically.
template = document.querySelector("#wrapper").innerHTML;
template = template.replace('$$$', index);
index ++;
...
Problem:
The problem here is with using innerHTML, because innerHTML will always override the HTML of your elements so previously typed values will be cleared, that's why you should use .appendChild().
And your logic for dynamic is correct, you just need to chnage the way you add new fields.
Solution:
I tried to rewrite your code so it uses appendChild() in a smart way using the #wrapper innerHTML as template and updating the id dynamically in the new appended fields.
var template = document.querySelector("#wrapper").innerHTML;
function addFields() {
var wrapper = document.createElement("div");
wrapper.innerHTML = template;
wrapper.querySelector("label:last-of-type").innerHTML = "Segment " + (++a) + ":";
document.getElementById('wrapper').appendChild(wrapper);
}
This code will create a new div everytime, wher we put the template HTML inside it, update the label dynamically referring the label inside our current wrapper div using wrapper.querySelector("label:last-of-type"), then finally append this new div to our element.
Demo:
Here's a working Demo snippet:
var template = document.querySelector("#wrapper").innerHTML;
var a = 1;
function addFields() {
var wrapper = document.createElement("div");
wrapper.innerHTML = template;
wrapper.querySelector("label:last-of-type").innerHTML = "Segment " + (++a) + ":";
document.getElementById('wrapper').appendChild(wrapper);
}
window.onload = function() {
document.querySelector("#more_fields").addEventListener("click", function(e) {
e.preventDefault();
addFields();
});
}
<div class="container">
<h2>Form</h2>
<form>
<div id="room_fields">
<div class="content" id="wrapper">
<label style:>Segment 1:</label>
<div class="segment">
<div class="form-group">
<label>IN:</label>
<input name="seg-in[]" type="text">
</div>
<div class="form-group">
<label>OUT:</label>
<input name="seg-out[]" type="text">
</div>
<div class="form-group">
<label>Duration:</label>
<input name="seg-dur[]" type="text">
</div>
</div>
</div>
</div>
<br><br>
<div style="text-align: right;">
<button id="more_fields">+</button>
</div>
<br>
<br>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
I have a form, I want to append a entire div every time a button is clicked. The code works but after few seconds the appended div automatically disappears. don't get any errors.
I am using jQuery 2.1.3. Here is my code in JS Fiddle:
https://jsfiddle.net/sathyabaman/jgdLtu4d/
My code:
<form method="POST" id="form_property" enctype="multipart/form-data">
<div class="row">
<div class="span4" id="image">
<h3><strong>4.</strong> <span>Add Images to your Property (Maximum : 6 Images)</span></h3>
<div id="clone_image" class="fileupload fileupload-new ">
<label class="control-label">Image file</label>
<div class="input-append">
<div class="uneditable-input"> <i class="icon-file fileupload-exists"></i>
<span class="fileupload-preview"></span>
</div> <span class="btn btn-file">
<span class="fileupload-new">Select file</span>
<span class="fileupload-exists">Change</span>
<input type="file" name="files1" accept="image/*" />
</span>
</div>
</div>
</div>
<!-- /.span4 -->
</div>
<!-- /.row -->
<br/> <a id="another_image" class="btn btn-primary btn-small list-your-property" href="">Add Another Image</a>
<br/>
<br/>
<input type="submit" name="submit" value=" Save images " class="btn btn-primary btn-large" style="float: left; width: 370px; height: 50px; margin-top: 10px">
</form>
jquery
$(document).ready(function(){
var count = 2;
$('#another_image').click (function(){
var clonedEl = $('#clone_image').first().clone()
clonedEl.find(':file').attr('name','files'+count)
if(count < 7){
if(count == 6){ $('#another_image').hide();}
$(clonedEl).appendTo("#image");
count++;
}
});
});
Thank you..
You need to prevent the default action of the anchor click, which is to navigate to the target page.
Since you have specified an empty href it reloads the same page that is why you can see the new element and then it appears to be disappearing.
$(document).ready(function () {
var count = 2;
$('#another_image').click(function (e) {
//e.preventDefault()
var clonedEl = $('#clone_image').first().clone()
clonedEl.find(':file').attr('name', 'files' + count)
if (count < 7) {
if (count == 6) {
$('#another_image').hide();
}
$(clonedEl).appendTo("#image");
count++;
}
});
});
Demo: Fiddle