Newish to javascript, but I do't know why the below is not working. I am trying to use javascript to make a link become active after a button has become clicked.
The user clicks a button that updates the HTML, changes the class and adds a html link. The code works the first time -- the HTML is updated correctly. However if the user decides to un-click the button nothing happens.
Javascript:
function agree() {
let agreement = document.getElementById("agreement");
let agree = document.getElementById("agree");
agree.onclick = () => {
if (agree.value === true) {
agreement.innerHTML = `
<button id="agree" class="agree--no" value="false"></button>I agree
<div class="btn--no-schedule">
<a href="#" > No SCHEDULE </a>
</div> `
} else {
agreement.innerHTML = `
<button id="agree" class="agree--checked" value="true"><i class="fas fa-lg fa-check-square"></i></button>I agree
<div class="btn--agree-schedule">
<a href="http://google.com" > yes SCHEDULE </a>
</div> `
}
}
};
HTML
<div id="agreement">
<button id="agree" class="agree--no" value="false"></button>I agree
<div class="btn--no-schedule">
<a href="#" > SCHEDULE </a>
</div>
</div>
I also tried
<button onclick=“agree();” id="agree" class="agree--no" value="false"></button>
but get a type error agree() is not a function.
Any help would be appreciated
There are two errors here.
First, the click event is lost when you reset the agreement's innerHTML, second, agree.value is a string, and thus will never be "=== true".
There are multiple ways of fixing it. One way is changing the innerHTML part so the event isn't lost. Also, changing the condition to === 'true'
Like so:
HTML:
<div id="agreement">
<button id="agree" class="agree--no" value="false"></button>I agree
<div id="schedule-btn" class="btn--no-schedule">
<a href="#" > SCHEDULE </a>
</div>
</div>
JS:
function agree() {
const agreeBtn = document.getElementById("agree");
const scheduleBtn = document.getElementById("schedule-btn");
agreeBtn.onclick = () => {
if (agreeBtn.value === "true") {
agreeBtn.value = false;
scheduleBtn.innerHTML = `
<div class="btn--no-schedule">
<a href="#" > No SCHEDULE </a>
</div>
`;
} else {
agreeBtn.value = true;
scheduleBtn.innerHTML = `
<div class="btn--agree-schedule">
<a href="http://google.com" > yes SCHEDULE </a>
</div>
`;
}
};
}
Edit: I tried to alter your code as little as possible
Try this code:
function ChangeContent(checkbox) {
var el = document.getElementsByClassName("schedule-agreement")[0];
(checkbox.checked) ? el.innerText = "No SCHEDULE": el.innerText = "Yes SCHEDULE"
}
<div id="agreement">
<input type="checkbox" onchange="ChangeContent(this)"> I agree
<div>
SCHEDULE
</div>
</div>
Explanation:
First of all, add a change event listener to the input checkbox. Then, whenever it is run, check if it is checked. If it is, change the link's innerText to "No SCHEDULE", otherwise, change it to "Yes SCHEDULE".
If you need to use a button, then I would recommend adding a click event listener (or an onclick inline event listener), and changing the link innerText ONLY - not the whole HTML.
In that case, here's a separate demo:
var isChecked = false
function ChangeContent() {
isChecked = !(isChecked)
if (isChecked) {
document.getElementsByClassName("agree")[0].innerText = "✔️ I agree"
document.getElementsByClassName("schedule-agreement")[0].innerText = "No SCHEDULE"
} else {
document.getElementsByClassName("agree")[0].innerText = "❌ I agree"
document.getElementsByClassName("schedule-agreement")[0].innerText = "Yes SCHEDULE"
}
}
<div id="agreement">
<button class="agree" onclick="ChangeContent()">I agree</button>
<div class="btn--no-schedule">
SCHEDULE
</div>
</div>
Related
I have a clickable span element that is supposed to call a javascript function that toggles a dropdown. This is an amalgum of two w3schools examples linked here.
onclick with span element
clickable dropdowns with w3.css
My code is below, the HTML and JS are inline in the same HTML document. The CSS can be ignored, it is just renamed w3.css stuff (w3- to mxa-).
HTML
<div class="mxa-dropdown-click">
<span onclick="menu_click("page-menu")">
<span class="mxa-xlarge">☰</span>
</span>
<div id="page-menu"
class="mxa-dropdown-content mxa-bar-block mxa-border"
>
<a href="/entity/show/42" class="mxa-bar-item">
Show Entity
</a>
<a href="/record/add/prompt/42" class="mxa-bar-item">
Add Record
</a>
</div>
</div>
JS
function menu_click(menu_id) {
window.alert('i got to here');
var menu = document.getElementById(menu_id);
if (menu.className.indexOf("mxa-show") == -1) {
menu.className += "mxa-show";
} else {
menu.className = menu.className.replace("mxa-show", "");
}
}
I have edited an example from the w3schools site that to me looks essentially identical to my code but which does work.
<!DOCTYPE html>
<html>
<body>
<span id="demo" onclick="myFunction('demo')">Click me to change my text color.</span>
<script>
function myFunction(arg) {
window.alert('i got to here');
document.getElementById(arg).style.color = "blue";
}
</script>
</body>
</html>
I never 'get to here' in my code. What could I be doing wrong?
You are forming the onclick attribute with invalid syntax, change the inner double quotes to single quotes.
Change
<span onclick="menu_click("page-menu")">
To
<span onclick="menu_click('page-menu')">
OR: With double quotes inside the single quotes
<span onclick='menu_click("page-menu")'>
function menu_click(menu_id) {
window.alert('i got to here');
var menu = document.getElementById(menu_id);
if (menu.className.indexOf("mxa-show") == -1) {
menu.className += "mxa-show";
} else {
menu.className = menu.className.replace("mxa-show", "");
}
}
<div class="mxa-dropdown-click">
<span onclick="menu_click('page-menu')">
<span class="mxa-xlarge">☰</span>
</span>
<div id="page-menu"
class="mxa-dropdown-content mxa-bar-block mxa-border">
<a href="/entity/show/42" class="mxa-bar-item">
Show Entity
</a>
<a href="/record/add/prompt/42" class="mxa-bar-item">
Add Record
</a>
</div>
</div>
All are same except onclick quote .check your quotes on onclick call
onclick="menu_click('page-menu')"
function menu_click(menu_id) {
window.alert('i got to here');
var menu = document.getElementById(menu_id);
if (menu.className.indexOf("mxa-show") == -1) {
menu.className += "mxa-show";
} else {
menu.className = menu.className.replace("mxa-show", "");
}
}
<div class="mxa-dropdown-click">
<span onclick="menu_click('page-menu')">
<span class="mxa-xlarge">☰</span>
</span>
<div id="page-menu" class="mxa-dropdown-content mxa-bar-block mxa-border">
<a href="/entity/show/42" class="mxa-bar-item">
Show Entity
</a>
<a href="/record/add/prompt/42" class="mxa-bar-item">
Add Record
</a>
</div>
</div>
I noticed that you are calling function error. Just replace these line of code.
Hope it will help you.
<span onclick="menu_click('page-menu')">
<span class="mxa-xlarge">☰</span>
</span>
I have functioning code, but I am sure there is a way to write it cleaner.
My code is far from best practice I assume. Don't repeat yourself principle.
I have tried looking for this problem but can not find an answer.
Here are the expected result and my current code:
https://jsfiddle.net/9ednsp6x/
document.getElementById("BtnMoreTotalt").onclick = function() {MoreBtnTotalt()};
function MoreBtnTotalt() {
document.querySelector(".more-wrapper-totalt").classList.toggle("show");
}
I also wonder, if there is a way so I do not have to use specific id and classnames on every element? Could I only use class "more-wrapper" and skip the IDs?
Here you have your example with a re-usable button click handler.
To make it work, you have to:
Wrap all your groups of button/content in a wrapper div with a class
Change the CSS so it works over the wrappers class
Add the click event handler to every element of the class
Use the event to get the nearest wrapper
now you can change the class of it
// Query through all "a" elements that are inside a ".wrapper" element
document.querySelectorAll(".wrapper > a").forEach(b => {
// Add a click handler to each
b.onclick = (e) => {
// prevent the default action of an "a" element
e.preventDefault();
// get the closest wrapper from the event
let button = e.target;
let wrapper = button.closest(".wrapper");
// now change the class
wrapper.classList.toggle("show");
};
});
.wrapper > div {
visibility:hidden;
}
.wrapper.show > div {
visibility:visible
};
<div class="wrapper">
<div>test1</div>
Mer info
</div>
<div class="wrapper">
<div>test2</div>
Mer info
</div>
<div class="wrapper">
<div>test3</div>
Mer info
</div>
<div class="wrapper">
<div>test4</div>
Mer info
</div>
document.querySelectorAll(".more-button").forEach(element => {
element.onclick = (e) => {
const elm = document.getElementsByClassName(e.target.getAttribute("anchor"));
elm[0].classList.toggle("show");
};
});
.more-wrapper {
visibility:hidden;
}
.more-wrapper.show {visibility:visible};
<div class="more-wrapper more-wrapper-totalt">
<div>test1</div>
</div>
<a href="#" onClick="return false;">
<div anchor="more-wrapper-totalt" class="more-button">Mer info</div>
</a>
<div class="more-wrapper more-wrapper-kvant">
<div>test2</div>
</div>
<a href="#" onClick="return false;">
<div anchor="more-wrapper-kvant" class="more-button">Mer info</div>
</a>
<div class="more-wrapper more-wrapper-invb">
<div>test3</div>
</div>
<a href="#" onClick="return false;">
<div anchor="more-wrapper-invb" class="more-button">Mer info</div>
</a>
<div class="more-wrapper more-wrapper-barn">
<div>test4</div>
</div>
<a href="#" onClick="return false;">
<div anchor="more-wrapper-barn" class="more-button">Mer info</div>
</a>
You can add the className button with attribute after use this attr click event. It's like clone but i think you need this class another place.
I am trying to create a "quiz" page where a user can guess if an article is real or fake. I have data-info from my database that I am trying to compare with the data-info for a button clicked by the user to check if they are correct or not. For example, if the data-info of the article is true, and the user clicks the button with data-info true then alert " you're right" or whatever. Someone please help!!
function loadArticle(){
$.get("/api/article", function(response){
$(".header").html(response[0].Headline);
$("h1").attr("data-info", response[0].is_real);
$(".body" ).html('<a target="_blank" href="${response[0].web_address}"> ${response[0].web_address} </a>');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class = "row" id="answers">
<button data-info="false" type = "button" class = "fa-bounce fas fa-times col-xs-4 col-xs-offset-2" id="fake">
FAKE
</button>
<div class="col-xs-4"></div>
<button data-info="true" type = "button" class = "fa-bounce fas fa-check col-xs-4 col-xs-offset-2" id="real">
REAL
</button>
</div>
You can compare data-* with the jQuery method .data()
here is an example when you get the data from the api request and compare its value when you click on the "real" button for example:
<button id="real" data-info="true">
real
</button>
<button id="real" data-info="false">
fake
</button>
var dataToCompare;
function loadArticle(){
$.get("/api/article", function(response){
dataToCompare = response[0].is_real;
}
}
$('#real').click(function() {
var data = $(this).data('info');
if(data === dataToCompare) {
alert('yes');
}
})
I have a person component that looks something like this (very simplified):
person.component.html
<div *ngfor='let current of users'>
<p>{{current?.name}} <a (click)='more(current?.id)'>Click for more</a>
<span [id]='current?.id + "_info"'></span>
</p>
</div>
person.component.ts
export class Person {
constructor() { }
more(id: any){
let response = `more info <button class='btn btn-primary btn-sm' (click)="changeCurrent()">`;
$('#' + id + '_info').html(response);
}
change() {
console.log('hello world', this);
}
}
When I click the more button, more(id) fires and it shows more information about the person. So that's working.
But when I click the change button, change() never fires. I know there's a better way and jquery needs to go, but I'm just not finding an example yet.
Thanks,
Heh. I knew jQuery was the wrong way to go, but sometimes I get frustrated and just want to get something to work.
Duncan gave me the clue to what I finally came up with. I think it is close to the Angular way of thinking, so I'm adding it here.
A better description of the example I'm playing with: A veterinary clinic has multiple vets, and each vet has multiple patients. A web page displays a list of vets. Clicking on a vet's name displays a list of the patients, with a button next to the patient name to toggle the patient's status, Current /Not Current.
all-vets.component.ts
export class AllVetsComponent implements OnInit {
vets: any = [];
patients: any = [];
displayPatients: any = [];
patientsRetrieved: boolean = false;
constructor(private http: Httppatient) { }
ngOnInit() {
// hit a web api, parse the data into this.vets and this.patients
}
getAllPatients(vetID: number): any[] {
// hit web api and get just the patients for the vet id
}
getPatients(vetID: number): void {
this.patientsRetrieved = false;
this.displayPatients[vetID] = [];
this.displayPatients[vetID] = getAllPatients(vetID);
this.patientsRetrieved = true;
$('#' + vetID + '_patients').toggle(500); // yes, still jQuery, but used for animations
}
showPatients(): boolean{
return this.patientsRetrieved;
}
changeStatus(patientID: number): void{
// find the patient with that id and toggle the currentPatient value
// post the change back to the api so it can go in the db
}
}
all-vets.component.html
<div class='card' *ngFor='let vet of vets'>
<div class='card-header' role='tab' [id]='vet?.vet_id'>
<a (click)='getAllPatients(vet?.vet_id)'
class="collapsed"
data-toggle="collapse"
(href)='"#" + vet?.vet_id'
aria-expanded="false"
>
{{vet?.vet_first_name}} {{vet?.vet_last_name}}
</a>
</div>
<div [id]='vet?.vet_id + "_patients"'
class="collapse hide" role="tabpanel"
[attr.aria-labelledby]='vet?.vet_id' [attr.data-parent]='"#" + vet?.vet_id'>
<div class="card-body patient-display">
<div class='container-fluid'>
<div class='row patient-listing patient-listing-header'>
<span class='patient-name col'>Name</span>
<span class='current-patient col'>Change Status</span>
</div>
<ng-template ngIf='showPatients()'>
<div class='row patient-listing' *ngFor='let patient of patients'>
<span class='patient-name col ' [ngClass]="{'currentpatient': patient.current_patient === 1, 'notpatient': patient.current_patient !== 1}">
{{patient?.name}}
</span>
<span class='patient-owner col'>
{{patient?.owner}}
</span>
<button class='btn btn-primary btn-sm' (click)='changeStatus(patient?.name)'>
<span *ngIf='patient.current_patient'>
Current
</span>
<span *ngIf='!patient.current_patient'>
Not Current
</span>
</button>
</span>
</div>
</ng-template>
</div>
</div>
</div>
</div>
I've removed extraneous details and changed names to protect the innocent.
This works for me. The only non-angular piece is the jquery that displays the card body. I could use angular to just toggle classes, but I wanted to add the delay so it wasn't as abrupt. There's probably a way to do that as well; I just haven't learned it yet. Clicking the button correctly updates the button text and changes the style of the patient's name, and that's the general behavior I was after.
Todo:
replace the remaining jQuery toggle function
add aria-live and aria-announce to the right elements
add aria-role and other aria as appropriate
use all of the complicated real world data instead of the proof of concept stuff
Thanks Duncan!
You need to use angular to update the DOM. HTML inserted using jQuery won't have been compiled to use any of your angular directives.
<div *ngfor='let current of users'>
<p>{{current?.name}} <a (click)='more(current?.id)'>Click for more</a>
<span *ngIf="wantMore[current?.id]">
more info
<button class='btn btn-primary btn-sm' (click)="changeCurrent()">
</span>
</p>
</div>
Then in your code:
export class Person {
public wantMore = {};
constructor() { }
more(id: any){
this.wantMore[id] = true;
}
changeCurrent() {
console.log('hello world', this);
}
}
try this:
let response = `more info <button id='myIid' class='btn btn-primary btn-sm'>`;
$('#' + id + '_info').html(response);
var el = this.elementRef.nativeElement.querySelector('#myIid');
if(el) {
el.addEventListener('click', this.changeCurrent.bind(this));
}
Besides, i saw you invoke changeCurrent function, but called your function change...
I need to get comment id when clicking to report button (I want to get comment-6)
Now when I click 'report' it show a modal box with form.
<div class="comment-box medium-comment" id="comment-6">
<div class="photo-box">
<img src="img/samples/photo_1.jpg" alt="" class="photo rounded"/>
</div>
<div class="avatars">
<a href="#" title="">
<img src="img/samples/followers/1.jpg" alt=""/>dearskye
</a>
<span>commented on</span>
<a href="#" title="">
<img src="img/samples/followers/2.jpg" alt=""/>Antony12
</a>
</div>
<div class="comment rounded">
<div class="bg-tl"></div>
<div class="text">Happy golden days of yore
Happy golden days of yore Happy golden days
of yore</div>
<div class="buttons">
REPORT
</div>
</div>
<div class="cinfo">
2 дня назад
</div>
<div class="both"></div>
</div>
clicking to
REPORT
call jquery
jQuery('a.report').bind('click', function(event) {
showModalWindow('report-window');
});
and function is
function checkReportForm(form)
{
var result=true;
var select=jQuery("#report-window select");
var textarea=jQuery("#report-window textarea");
if(textarea.hasClass('default'))
{
//Save placeholder
textarea.data('placeholder', textarea.text());
textarea.toggleClass('default');
}
textarea.attr('class','rounded');
if(select.val()==0)
{
if(textarea.val()==''||textarea.val()==textarea.data('placeholder'))
{
result=false;
textarea.toggleClass("alert");
}
}
if(result)
{
closeModalWindow('report-window');
}
I tried to do it but nothing. I suppose it is possible otherwise will think to change code. I hope someone will help me.
You can use closest to get the closest element which cotains the required class and get its id. Try this.
jQuery('a.report').click(function() {
var $commentBox = $(this).closest(".comment-box");
var id = $commentBox.attr('id').replace('comment-', '');
alert(id);//It will alert the comment id
//Store the comment id in report window
$('#report-window').data('commentid', id);
});
Now use $('#report-window').data('commentid') to get the current comment id inside checkReportForm method.
If i understand you correctly, the following should fetch the comment id for you:
$(".report").click(function() {
var $box = $(this).parents(".comment-box");
var commentId = $box.attr("id").replace("comment-", "");
// commentId contains 6
// call showModalBox and do whatever you want
});
When this context is your report link:
var id = Number(this.parentNode.parentNode.id.substring(8));