For a school project, I'm coding a porfolio.
I want to use jQuery hide() and show() to have popups that appear after clicking on buttons.
Is there a way, with a single code, to make every HTML element with the class="vignette" and an id="bouton1" show a div with the same number in id (id=popup1).
I don't know if I'm clear, I'm a student in graphic design, and I'm not having a good time.
As far as I can understand from your question, you want to show a modal whose ID is the same number as the button's ID?
You can use this same logic to work with your modal instead
// This regex just gets the number part from the ID
const re = /bouton(\d+)/
$('button.vignette').click(e => {
const res = re.exec(e.target.id)
if(res) {
// "popup" + res[1] gives the popup id
$('#content').html("popup" + res[1])
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class = "vignette" id = "bouton1">B1</button>
<button class = "vignette" id = "bouton2">B1</button>
<button class = "vignette" id = "bouton3">B1</button>
<button class = "vignette" id = "bouton4">B1</button>
<div id = "content"></div>
You can create a function that will be added via addEventListener. Alternatively you can add an onclick attribute to the HTML elements whose click you want to handle.
let activeDiv;
function myClick() {
if (activeDiv) activeDiv.classList.add("invisible");
(activeDiv = document.getElementById(this.id.replace("bouton", "popup"))).classList.remove("invisible");
}
let buttons = document.getElementsByClassName("vignette");
for (let button of buttons) {
button.addEventListener("click", myClick);
}
.invisible {
display: none;
}
<input type="button" id="bouton1" class="vignette" value="First">
<input type="button" id="bouton2" class="vignette" value="Second">
<input type="button" id="bouton3" class="vignette" value="Third">
<input type="button" id="bouton4" class="vignette" value="Fourth">
<input type="button" id="bouton5" class="vignette" value="Fifth">
<input type="button" id="bouton6" class="vignette" value="Sixth">
<input type="button" id="bouton7" class="vignette" value="Seventh">
<input type="button" id="bouton8" class="vignette" value="Eigth">
<input type="button" id="bouton9" class="vignette" value="Ninth">
<div id="popup1" class="invisible">1</div>
<div id="popup2" class="invisible">2</div>
<div id="popup3" class="invisible">3</div>
<div id="popup4" class="invisible">4</div>
<div id="popup5" class="invisible">5</div>
<div id="popup6" class="invisible">6</div>
<div id="popup7" class="invisible">7</div>
<div id="popup8" class="invisible">8</div>
<div id="popup9" class="invisible">9</div>
suppose you have 10 buttons with class vignette then you code would be:
$.each( "button.vignette", function( i, obj) {
$(obj).attr( "id", i ).on('click',function(){
$('#popup'+i).toggle();
});
});
You can replace toggle() function with your code as desired.
Related
I am building a quiz page using javascript, and want the user to select from a multiple choice and then hit 'Go' to check their answer. Here is the html for the first question:
<p class="question">What is the name of Joey's bedtime penguin pal?</p>
<div class="radio">
<div>
<input type="radio" class="wrong" name="q1">Maurice
</div>
<div>
<input type="radio" class="wrong" name="q1">Clunkers
</div>
<div>
<input type="radio" class="right" name="q1">Hugsy
</div>
<div class="button">
<button type="button" class="go">Go</button>
</div>
<div>
<img src="images/hugsy.jpg" class="image" style="display: none;"
</div>
I have created a function which is called by the Go button which informs the user if they are right or not. Here is the javascript:
let go = document.querySelector('.go');
let correct = document.querySelector('.right');
let showPic = document.querySelector('img');
let remGo = document.querySelector('button');
let choices = document.querySelector('.radio');
let score = 0;
go.addEventListener('click', checkAnswer);
function checkAnswer() {
if (correct.checked) {
showPic.classList.remove('image');
remGo.remove();
choices.innerHTML = '<h2 style="color: green;">Correct!</h2>';
score++;
} else {
remGo.remove();
choices.innerHTML = '<h2 style="color: red;">Incorrect</h2>';
}
}
This code works the way I want it to but only for the first question. When I try to call the function again by clicking 'Go' on question 2 nothing happens.
Is there a way to call a function multiple times using different buttons?
document.querySelector('.go');
only selects the first matching element.
To select all elements with the .go class you need to use querySelectorAll
Then you'll need to assign your event listener to all elements returned.
Here is a minimal example:
let buttons = document.querySelectorAll('.go');
for (const button of buttons) {
button.addEventListener('click', checkAnswer);
}
function checkAnswer() {
console.log("checkingAnswer...")
}
<div class="button">
<button type="button" class="go">Go</button>
</div>
<div class="button">
<button type="button" class="go">Go</button>
</div>
<div class="button">
<button type="button" class="go">Go</button>
</div>
Thanks to those who helped. I have solved my issue now using jquery. This was the code I used:
$(".container").on("click", "button", function (e) {
var container = $(e.target).closest(".container");
if ($(container).find("input:checked").hasClass("right")) {
$(container).find("img").show();
$(container).find("button").remove();
$(container).find(".radio").html('<h2 style="color: green;">Correct!</h2>');
score++;
} else {
$(container).find(".radio").html('<h2 style="color: red;">Incorrect</h2>');
}
});
I have to pass variables to jQuery. There are two different approach as I see:
clean HTML, dirty jQuery:
<div class="itemContainer" data-id="1">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
$('.rename').click(function() {
var id = $(this).parent().attr('data-id');
});
$('.delete').click(function() {
var id = $(this).parent().attr('data-id');
});
PROs:
clean, not redundant HTML,
CONS:
not so clean jQuery,
if the DOM structure changes, its hard to detect the errors, and it has to be fixed at 2 places
clean jQuery, dirty HTML:
<div class="itemContainer">
Item information
<input type="button" class="rename" data-id="1">
<input type="button" class="delete" data-id="1">
</div>
$('.rename').click(function() {
var id = $(this).attr('data-id');
});
$('.delete').click(function() {
var id = $(this).attr('data-id');
});
PROs:
clean jQuery,
works even DOM structure changes
CONS:
not so clean, redundant HTML,
which one would you prefer to use?
Your first HTML structure is the better implementation as it avoids repetition of the same data-id attribute.
With regard to the jQuery, you can use a single event handler by separating the selectors with a comma (,), and you can use closest() to find the required parent element. This is more robust as you can then change the HTML structure within that parent however you require and it will not break the JS logic, so long as the clicked element is still a child node. Finally, note that you should use data() to get/set data attributes where possible, not attr(). Try this:
$('.rename, .delete').click(function() {
var id = $(this).closest('.itemContainer').data('id');
console.log(id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="itemContainer" data-id="1"> Item information
<input type="button" class="rename" value="Rename" />
<input type="button" class="delete" value="Delete" />
</div>
<div class="itemContainer" data-id="99"> Item information
<p>
Extra information...
<div class="another-child">
<input type="button" class="rename" value="Rename" />
<input type="button" class="delete" value="Delete" />
</div>
</p>
</div>
Put the selectors you want to add the listener to together in the selector string you use to add a .click listener to (separated by commas), and you don't need to repeat yourself at all:
$('.rename, .delete').click(function() {
var id = $(this).parent().attr('data-id');
console.log(id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="itemContainer" data-id="1">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
<div class="itemContainer" data-id="2">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
You can combine the click event for both the element using Multiple Selector. You can specify any number of selectors to combine into a single result. This multiple expression combinator is an efficient way to select disparate elements.
clean jQuery, Clean HTML:
$('.rename, .delete').click(function() {
var id = $(this).parent().attr('data-id');
console.log(id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="itemContainer" data-id="1">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
I would use event delegation and a single data-attribute. You don't need jQuery for it. Added a button for restructuring the DOM to demonstrate that the handler keeps working after it.
(() => {
const evtHandler = evt => {
const origin = evt.target;
console.clear();
if (origin.id === "redoDOM") { return restructure(); }
if (origin.parentNode.classList.contains("itemContainer")) {
console.log(`${origin.classList} data-id: ${origin.parentNode.dataset.id}`);
}
};
document.addEventListener("click", evtHandler);
function restructure() {
if (!document.querySelector("#BttnContainer")) {
let container = document.createElement("div");
container.id = "BttnContainer";
container.innerHTML = `
<p>
div.itemContainer elements are wrapped.
Check if the button handler still works
</p>`;
Array.from(document.querySelectorAll(".itemContainer"))
.forEach(v => container.appendChild(v));
document.body.insertBefore(container, document.body.firstChild);
} else {
console.log("Already wrapped");
}
}
})();
#BttnContainer {
color: green;
}
<p>Click buttons to show data-id value of the surrounding element</p>
<div class="itemContainer" data-id="1">
Item information (1)
<button class="rename">rename</button>
<button class="delete">delete</button>
</div>
<div class="itemContainer" data-id="2">
Item information (2)
<button class="rename">rename</button>
<button class="delete">delete</button>
</div>
<p>
Click to wrap buttons in a new element
<button id="redoDOM">Restructure</button>
</p>
I have an input field and a button next to it, what i want to do is whatever i type in the input field then click on the button next to it, the result gets displayed in another button, here is what i tried so far:
function add_keyword() {
var keyword_value = (document.getElementById("keyword").value);
var result = keyword_value;
document.getElementById("btnresult").value = result;
}
#btnresult{
display: none;
}
<button type="button" class="btn btn-default" name="clickbtn" value="Add Keyword" onclick="add_keyword()">Add</button>
<div class="input-group">
<input type="text" class="form-control" id="keyword" name="keywordbox"/>
</div>
<button type="button" id="btnresult" class="btn btn-default">input value should be here</button>
https://jsfiddle.net/sheriffderek/p2LoLcv3/
I think this is what you are describing...
Some simplified markup
<div class="parent">
<input type='button' value='Add' rel='action' /><br>
<input type='text' rel='text-input' />
</div>
<ul class='button-list' rel='button-list'>
<!-- you need to put the buttons somewhere, right? -->
</ul>
jQuery was one of the tags, so I used it
// just caching some thing that will be reused (I like using rel)
var $parent = $('.parent'); // whatever - to keep some scope
var $addButton = $parent.find('[rel="action"]');
var $textInput = $parent.find('[rel="text-input"]');
var $buttonList = $('[rel="button-list"]');
$addButton.on('click', function() { // on click...
var currentInputValue = $textInput.val(); // get the value from input...
$buttonList.append('<li><button>' + currentInputValue + '</button></li>'); // append a new button...
$textInput.val(''); // clear input
});
You're almost there, you have to unhide the button you've hidden in the first place, and not set a value for a button, but rather the innerHTML property. Since a button doesn't hold a value, but displays the content between the tags as text.
I've commented my changes:
function add_keyword() {
var keyword_value = (document.getElementById("keyword").value);
var result = keyword_value;
// Changed from .value to .innerHTML
document.getElementById("btnresult").innerHTML = result;
// Changed style from to 'block'
document.getElementById("btnresult").style.display = "block"
}
#btnresult{
display: none;
}
<button type="button" class="btn btn-default" name="clickbtn" value="Add Keyword" onclick="add_keyword()">Add</button>
<div class="input-group">
<input type="text" class="form-control" id="keyword" name="keywordbox"/>
</div>
<button type="button" id="btnresult" class="btn btn-default">input value should be here</button>
In addition, there are several aspects of your code that could use improvement, I described them below:
function add_keyword() {
// No need for parentheses around the document.getElement function.
var keyword_value = document.getElementById("keyword").value;
// There's no need to place the value in a new variable, it is useful to place the element you wish to replace in a variable, since we'll be re-using it's instance.
var btn = document.getElementById("btnresult");
btn.innerHTML = keyword_value;
btn.style.display = "block"
}
EDIT: Since OP's goal was to create a new button with the content, this is an updated version that generates a new button for every new input.
function add_keyword() {
var keyword_value = document.getElementById("keyword").value;
// Create a new button element.
var btn = document.createElement("button");
// Set it's content to the keyword from the input.
btn.innerHTML = keyword_value
// Append it to the body.
document.body.appendChild(btn);
}
<button type="button" class="btn btn-default" name="clickbtn" value="Add Keyword" onclick="add_keyword()">Add</button>
<div class="input-group">
<input type="text" class="form-control" id="keyword" name="keywordbox"/>
</div>
I have a form that has three separate divs within it.
<form method="post">
<div id = "f1">
<div class="label">Value 1:</div>
<input type="text" name="name"/>
<button id = "next1" type="button" onclick="checkValue()">Next</button>
</div>
<div id ="f2">
<div class="label">Value 2:</div><br>
<input type="text" name="name"/>
<button type="button" onclick="checkValue()">Next</button><br>
</div>
<div id ="f3">
<div class="label">Value 3:</div><br>
<input type="text" name="name"/>
<button type="button" onclick="checkValue()">Next</button><br>
</div>
</div>
</form>
In my javascript function. I have a fadein and fadeout attached to each div when the next button is pressed. When the "next1" button is pressed the first div will be faded out and the second div will fade in. I want to check the values inputted in the first div when the user presses the first next button. I know how to do this if i just passed in the whole form into my javascript function on the final submit button, but I would like to know how to do this after each next button is pressed.
I also will have more than one value in each of the divs (f1, f2, f3) but for simplicity I only included one value.
EDIT*: further explaintaion
If i did this by passing in the form into checkValue. I could just do an onsubmit = "checkValue()". And then in my JS file, I would just include checkValue(form) as its parameter. If i want to do a check after every single button is pressed, I am not sure how to do this or what to pass in as its parameter.
Simple mock up hopefully to get you one your way.
Fiddle: http://jsfiddle.net/AtheistP3ace/krr3tgLx/1/
HTML:
<form method="post">
<div id="f1" style="display: block;">
<div class="label">Value 1:</div>
<input type="text" name="name" />
<button id="next1" type="button" onclick="checkValue(this)">Next</button>
</div>
<div id="f2">
<div class="label">Value 2:</div>
<br>
<input type="text" name="name" />
<button type="button" onclick="checkValue(this)">Next</button>
<br>
</div>
<div id="f3">
<div class="label">Value 3:</div>
<br>
<input type="text" name="name" />
<button type="button" onclick="checkValue(this)">Next</button>
<br>
</div>
</div>
</form>
JS:
function checkValue (button) {
// Finds the sibling input of the button
var input = $(button).siblings('input');
// Gets input value
var value = input.val();
// Stops showing next div if no value
if (value == '') {
return false;
}
else {
// Finds the parent div holding button and input
var div = $(button).closest('div');
// Fades out current div
div.fadeOut();
// Gets next div and fades it in
div.next().fadeIn();
}
}
CSS:
form > div {
display: none;
}
From my assumptions this is what you are looking for :
Multipart form handler
Basically I wired up each button with a class
<button id = "next1" type="button" class="check-btn">Next</button>
Then I used Jquery to get all those buttons and find the parent div (based on your structure) and then get all the child inputs (can include selects etc). From here you can continue to tweak to perform a check on each type of input etc.
$(document).ready(function(){
$('.check-btn').on('click',function(){
var parent = $(this).parent('div');
var elems = parent.find('input');
alert(elems.length);
//DO checks here for each element
});
});
I am using twitter bootstrap in my rails app, and I am constructing a form with multiple radio button inputs. In order to manage the form data, I have created a hidden field whose value is updated via Javascript.
Sample code below for any given input:
<div class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn" id="ornamental_only_yes" name="ornamental_only" value="yes">Yes</button>
<button type="button" class="btn" id="ornamental_only_no" name="ornamental_only" value="no">No</button>
</div>
<input type="hidden" id="ornamental_only" name="ornamental_only" value="">
Here is the Javascript to manage this event:
<script>
var btns = ['ornamental_only_yes', 'ornamental_only_no'];
var input = document.getElementById('ornamental_only');
for(var i = 0; i < btns.length; i++) {
document.getElementById(btns[i]).addEventListener('click', function() {
input.value = this.value;
});
}
</script>
My question: Is there a way to abstract the Javascript code in such a way as to apply to multiple radio button inputs simultaneously? (For instance, if I had 3 repetitions of the code block above with different id's)
Let's assume this is your HTML with multiple sets of buttons:
<div class="btn-group" id="btn_group_1" data-toggle="buttons-radio">
<button type="button" class="btn" id="ornamental_only_yes" name="ornamental_only" value="yes">Yes</button>
<button type="button" class="btn" id="ornamental_only_no" name="ornamental_only" value="no">No</button>
</div>
<input type="hidden" id="hidden_1" name="ornamental_only" value="">
<div class="btn-group" id="btn_group_2" data-toggle="buttons-radio">
<button type="button" class="btn" id="awesome_only_yes" name="awesome_only" value="yes">Yes</button>
<button type="button" class="btn" id="awesome_only_no" name="awesome_only" value="no">No</button>
</div>
<input type="hidden" id="hidden_2" name="awesome_only" value="">
To dynamically listen for clicks on all button groups, you could do something like this (untested jQuery):
$('.btn-group .btn').on('click', function() {
var parentID = $(this).parent().attr('id');
$('#hidden_' + parentID.substr(parentID.length - 1)).val($(this).val());
});
This just targets the hidden input fields based on the number at the end of the id.
Try using this:
for(var i = 0; i <= btns.length; i++) {
Use jQuery.
var buttonObjs = $(".btn-group").find("button");
buttonObjs.click(function(){
$("#ornamental_only").val(this.value);
});
To apply this code to multiple blocks, all you need to do is assign a specific class to the btn-group element, something like,
<div class="btn-group js_radio_toggle">
In the js code just use,
var buttonObjs = $(".btn-group.js_radio_toggle").find("button");
now this code can be reused anywhere.
also in your js code. you can do this,
document.getElementsByClassName("js_radio_toggle").
But I would recommend you to use jQuery.