Toggle paragraph using link from another paragraph - javascript

I have similar code like this. Except for the fact that my JS file is external. The function myFunction() is called in the beginning of that file, like this:
document.addEventListener('DOMContentLoaded', function () {
myFunction()
})
But, it's not working - it's not showing the text from the second paragraph, when clicked on the word HERE from the first paragraph. I assume that maybe I should call the function somehow else. Any given ideas would be really helpful. Thanks.
P.S. Also, when clicked, the window should scroll to the newly opened paragraph.
function myFunction() {
var x = document.getElementById("myCollapsible2")
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
p{
background: #eee;
border: 1px solid #ccc;
margin: 20px 0;
padding: 30px;
}
.bs-example{
margin: 20px;
}
.link-color {
color: red;
}
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js">.</script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="bs-example">
<input type="button" class="btn btn-primary" data-toggle="collapse" data-target="#myCollapsible" value="Toggle Button">
<div id="myCollapsible" class="collapse"><p>This is a simple example of expanding and collapsing individual element via data attribute. <br>Click on the <b>Toggle Button</b> button to see the effect. If you click <a onclick="myFunction()" class="link-color" href="#">here</a>, you should see the other paragraph. </p></div>
<div id="myCollapsible2" class="collapse"><p>This is a simple example</p></div>
</div>
</body>
</html>

Since you are using bootstrap with popper, your function is unnecessary, just set the values according to the documentation. To scroll to the element, use the scrollIntoView method. I had to wrap it around a setTimeout, because the default method was executing afterwards, so when I called scroll the element wasn't visible yet.
function scrollTo2() {
var el = document.getElementById('myCollapsible2');
window.setTimeout(() => el.scrollIntoView(), 0);
}
p {
background: #eee;
border: 1px solid #ccc;
margin: 20px 0;
padding: 30px;
}
.bs-example {
margin: 20px;
}
.link-color {
color: red;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<div class="bs-example">
<input type="button" class="btn btn-primary" data-toggle="collapse"
data-target="#myCollapsible" value="Toggle Button">
<div id="myCollapsible" class="collapse show">
<p>This is a simple example of expanding and collapsing individual element
via data attribute.<br>Click on the <b>Toggle Button</b>
button to see the effect.
If you click <a onclick="scrollTo2()" data-toggle="collapse"
data-target="#myCollapsible2" class="link-color" href="#">here</a>,
you should see the other paragraph. </p>
<div id="myCollapsible2" class="collapse">
<p>This is a simple example</p>
</div>
</div>
</div>

Related

I can't add a close tag to a list element in javascript

I created a To-do List, but I can't add a close tag to a list element in js. When I add the marked 5 lines of code in js my code doesn't work and I can't add a new list. Can you help me? Why it doesn't work, I didn't understand. I'm missing something..
I created a To-do List, but I can't add a close tag to a list element in js. When I add the marked 5 lines of code in js my code doesn't work and I can't add a new list. Can you help me? Why it doesn't work, I didn't understand. I'm missing something..
let form = document.querySelector('#form');
let reset = document.querySelector('#reset');
let myList = document.querySelector('#myList');
let text = document.querySelector('#text');
let submit = document.querySelector('#submit');
submit.addEventListener('click', function(e) {
e.preventDefault();
let liDOM = document.createElement('li')
liDOM.className = 'list-group-item'
liDOM.innerHTML = `${text.value[0].toUpperCase()}${text.value.slice(1)}`;
myList.appendChild(liDOM);
// If I add this 5 code lines, it doesn't work. WHY?
var span = document.createElement('span');
var text = document.createElement('\u00D7');
span.className = 'close';
span.appendChild(text);
liDOM.appendChild(span);
});
myList.addEventListener('click', function(item) {
if (item.target.tagName = 'li') {
item.target.classList.toggle('checked');
}
})
let counter = 0;
function myFunction() {
while (counter < myList.childElementCount) {
myList.removeChild(myList.firstChild);
}
}
ul li.checked {
background: #888;
color: #fff;
text-decoration: line-through;
}
.close {
position: absolute;
right: 0;
top: 0;
padding: 12px 16px 12px 16px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To Do List</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="index.css">
</head>
<body>
<form id="form">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-6 col-md-8 mt-5">
<div class="card">
<div class="card-body">
<div class="input-group">
<input class="form-control" type="text" id="text" placeholder="What will you do today?">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="submit" id="submit">Ekle</button>
<button onclick="myFunction()" type="submit" id="reset" class="btn btn-outline-secondary">Sıfırla</button>
</div>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">My List</div>
<ul id="myList" class="list-group list-group-flush">
</ul>
</div>
</div>
</div>
</div>
</form>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
First of all good job, this was in nearly working condition and looks great.
There seemed to be a few minor problems with the implementation.
First, it is unusual/counterintuitive to have 2 different buttons each with type submit.
I would assume only first one should have type='submit'. The second one for presumably clearing the input should be type='button'. I also think they should have different styles to help warn the user that they have very different functionality.
Also, since the button has a submit functionality you don't need to also add an onclick functionality. It is very good to have an on submit functionality on the form and the single button with type='submit' as this allows the enter key to add a ToDo item.
Finally, the main focus of your problem was just that the text variable was already defined and you can't create an Element with the type × that is not an HTML type. See all the HTML elements on Mozilla Development search your favorite Search Engine for MDN Mozilla and within that search HTML for a list of current Legal HTML elements. It is very unlikely that an element will not be a word or abbreviation of some kind so that immediately tipped me off that: × was not an element tag that you can create they're more like (div, span, script, p, b, i). I think you meant for that to be the content of another span element that you wanted to create. Once you solved those 2 issues your code works!
I would just recommend that you append the × directly into the text because that's unfortunately the only element that doesn't fit. If not maybe you're going for a flex-box justify-content: space-between type thing where the × should always be on the right and the TODO on the left.
In that case you want the resulting HTML to be like:
<div style='display: flex; justify-content: space-between; align-items: center'>
<div>To Do text... I need to do stuff</div>
<button onclick='toggleComplete(12)'>×</button>
</div>
Keep in mind that for accessibility all clickable elements should really be buttons. If you need yo can cut back on the styling of this button and create a non-button-button class that resets all button specific styles to help you make it still look exactly how you want but work with screen readers.
let form = document.querySelector('#form');
let reset = document.querySelector('#reset');
let myList = document.querySelector('#myList');
let text = document.querySelector('#text');
let submit = document.querySelector('#submit');
submit.addEventListener('click', function(e) {
e.preventDefault();
let liDOM = document.createElement('li')
liDOM.className = 'list-group-item'
liDOM.innerText = `${text.value[0].toUpperCase()}${text.value.slice(1)}`;
myList.appendChild(liDOM);
// This was not working before because `text`
// was already defined above as `#text`
var newSpan = document.createElement('span');
// NOTE: for accessibility this must be a button.
const closer = document.createElement('span');
// this is probably what you meant to do... but
// note this needs some CSS love and the x itself doesn't work if you click
// on it so maybe just add it to the inner text instead:
// liDOM.innerText = `${text.value[0].toUpperCase()}${text.value.slice(1)} ×`;
closer.innerText = '×'
// perhaps add a special class here that gives it a red color
// perhaps only add the event listener to this button
newSpan.className = 'close';
newSpan.appendChild(closer);
liDOM.appendChild(newSpan);
});
myList.addEventListener('click', function(item) {
if (item.target.tagName = 'li') {
item.target.classList.toggle('checked');
}
})
let counter = 0;
function myFunction() {
while (counter < myList.childElementCount) {
myList.removeChild(myList.firstChild);
}
}
ul li.checked {
background: #888;
color: #fff;
text-decoration: line-through;
}
.close {
position: absolute;
right: 0;
top: 0;
padding: 12px 16px 12px 16px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To Do List</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="index.css">
</head>
<body>
<form id="form">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-6 col-md-8 mt-5">
<div class="card">
<div class="card-body">
<div class="input-group">
<input class="form-control" type="text" id="text" placeholder="What will you do today?">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="submit" id="submit">Ekle</button>
<button onclick="myFunction()" type="submit" id="reset" class="btn btn-outline-secondary">Sıfırla</button>
</div>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">My List</div>
<ul id="myList" class="list-group list-group-flush">
</ul>
</div>
</div>
</div>
</div>
</form>
<script type="text/javascript" src="index.js"></script>
</body>
</html>

Temporarily hiding HTML / Bootstrap elements is changing their widths

Newbie here, have mercy :D
So I have a div with two tables in it, which both include several Bootstrap buttons. I stretched them to 100% width so that they fill the whole table (which fill the whole div in return).
Whenever I click one of the buttons, I want to hide the tables and replace them by some other div that was hidden before. Also, a back button is appearing that should reverse that process.
Most of this works fine, however, after using the back button to get back to the initial state, the buttons aren't filling the whole width anymore. I'm not sure what could help, as I only touched the style of the tables, not their elements, and the tables still fill 100% width of their div as seen by the borders (see below).
I'm inlucing a minimal working example:
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="expires" content="3600">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" integrity="sha512-+4zCK9k+qNFUR5X+cKL9EIR+ZOhtIloNl9GIKS57V1MyNsYpYcUrUeQc9vNfzsWfV28IaLL3i96P9sdNyeRssA==" crossorigin="anonymous" />
<title>Hello!</title>
<style>
#options-div {
display: flex;
}
.action-divs, #back-button {
display: none;
}
.options-table {
table-layout: fixed;
border: 2px solid green;
width: 100%;
}
.btn-dark {
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<div class="row" id="options-div">
<div class="col-sm-2">
<button type="button" class="btn btn-dark" id="back-button">Back</button>
</div>
<div class="col-sm-8">
<table class="options-table">
<tr>
<td>
<button type="button" class="btn btn-dark btn-block" id="jet-button">Jet</button>
</td>
</tr>
</table>
<div class="action-divs" id="jet-div">
</div>
</div>
<div class="col-sm-2">
</div>
</div>
</div>
<script src="myscript.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</body>
</html>
for the markup. A div with a table with one button.
And the javascript:
var jetButton = document.querySelector("#jet-button");
jetButton === null || jetButton === void 0 ? void 0 : jetButton.addEventListener("click", handleJet);
var backButton = document.querySelector("#back-button");
backButton === null || backButton === void 0 ? void 0 : backButton.addEventListener("click", handleBack);
function handleJet() {
var optionsTables = document.querySelector(".options-table");
optionsTables.style.display = "none";
var jetDiv = document.querySelector("#jet-div");
jetDiv.style.display = "flex";
backButton.style.display = "flex";
}
function handleBack() {
var optionsTables = document.querySelector(".options-table");
optionsTables.style.display = "flex";
optionsTables.style.tableLayout = "fixed";
backButton.style.display = "none";
var jetDiv = document.querySelector("#jet-div");
jetDiv.style.display = "none";
}
Sorry for the TypeScript conversion stuff, hopefully it's readable enough. Basically on click of my button, I want to hide the table and display another div and the back button. On click of the back button, I want to hide the div and the back button again and re-display the initial table (with the button in it).
I already tried Bootstrap classes like btn-block, none did work though.
Thanks in advance!
The problem is when you add flex to the table element. Your button element will take the 100% width but after flex applied the td element is minimum to content
<table class="options-table">
<tr>
<td>
<button type="button" class="btn btn-dark btn-block" id="jet-button">Jet</button>
</td>
</tr>
</table>
you can try to use align-items: stretch; and always leave flex on the table.
Also, i would recommend to use classList to add and remove classes on the element instead of change styles directly.
MDN element classList

Why several clicks fire for each instance of a Class?

I have three tooltip buttons on a page. I can close any open tooltip by clicking anywhere outside buttons. And this is what I came across:
In the code below, when I click on any place on the page, the handler of this part of code is activated $(document).on('click', (event) => this.closeOnOutsideClick(event));
I can see in inspector, that function closeOnOutsideClick is fired three times - it makes three checks for each tooltip button present on the page. I cannot figure out what mechanism is responsible for that and why the check if (!$(event.target).closest(this.$elem)) is not performed only once? My code can be found here and also below: https://jsfiddle.net/bakrall/786cz40L/
This is a simplified version of a more complex code just to give example of my issue:
const selectors = {
tooltip: '.tooltip-container',
tooltipButton: '.tooltip-button',
tooltipMessage: '.tooltip-message'
}
class Tooltip {
constructor(tooltip) {
this.$elem = $(tooltip);
this.$tooltipButton = this.$elem.find(selectors.tooltipButton);
this.$tooltipMessage = this.$elem.find(selectors.tooltipMessage);
this.$tooltipMessageText = this.$tooltipButton.attr('data-tooltip-content');
this.bindUiEvents();
}
bindUiEvents() {
$(document).on('click', (event) => this.closeOnOutsideClick(event));
this.$tooltipButton.on('click', () => this.showTooltipMessage());
this.$tooltipButton.on('blur', () => this.hideTooltip());
}
showTooltipMessage() {
this.$tooltipMessage
.text(this.$tooltipMessageText)
.addClass('shown-message');
}
hideTooltip() {
this.$tooltipMessage
.text('')
.removeClass('shown-message');
}
closeOnOutsideClick(event) {
if (!$(event.target).closest(this.$elem)) {
this.hideTooltip();
}
}
}
//class in another file
const tooltip = $('.tooltip-container');
tooltip.each(function(index, item) {
new Tooltip(item);
})
.input-wrapper {
margin-bottom: 2em;
}
.tooltip-container {
position: relative;
display: inline-block;
}
.tooltip-message {
display: none;
position: absolute;
left: 100%;
top: 0;
width: 10em;
padding: 0.5rem;
background: #000;
color: #fff;
}
.tooltip-message.shown-message {
display: inline-block;
}
button {
width: 1.2em;
height: 1.2em;
border-radius: 50%;
border: 0;
background: #000;
font-family: serif;
font-weight: bold;
color: #fff;
}
button:focus {
outline: none;
box-shadow: 0 0 0 0.25rem skyBlue;
}
input {
display: block;
}
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title> </title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="tooltip.css">
</head>
<body>
<div class="input-wrapper">
<label for="name">
What's your name?
<span class="tooltip-container">
<button class="tooltip-button" type="button" aria-label="more info"
data-tooltip-content="This clarifies whatever needs clarifying">i</button>
<span class="tooltip-message" role="status"></span>
</span>
</label>
<input id="name" type="text"/>
</div>
<div class="input-wrapper">
<label for="age">
What's your age?
<span class="tooltip-container">
<button class="tooltip-button" type="button" aria-label="more info"
data-tooltip-content="This is to know how old you are">i</button>
<span class="tooltip-message" role="status"></span>
</span>
</label>
<input id="age" type="text"/>
</div>
<div class="input-wrapper">
<label for="nationality">
What's your nationality
<span class="tooltip-container">
<button class="tooltip-button" type="button" aria-label="more info"
data-tooltip-content="What country are you from?">i</button>
<span class="tooltip-message" role="status"></span>
</span>
</label>
<input id="nationality" type="text"/>
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous">
</script>
<script src="tooltip.js" async defer></script>
</body>
</html>
tooltip.each(function(index, item) {
new Tooltip(item);
})
Since you instantiate 3 Tooltips, you bind a separate event listener to the document each time. Each listener is getting triggered with each click. However, each of those listeners has a different this which is what allows each listener to tell if its Tooltip was clicked and if not, hide it.
If you want a single listener you could store a list of all your Tooltips and have the event listener iterate through the list of Tooltips, closing all Tooltips that were not clicked.
Your click event is firing on mutliple elements, because you specified just (document). Maybe you can be more specific:
$(document).on('click', '.input-wrapper', (event) => this.closeOnOutsideClick(event));

dojo fx.fadeIn/fx.fadeOut

Have simple question. Don't know why it's not working. Its should be red box that can fade in and fade out on click, but nothing happens. I'm trying to solve this problem for more then 2 days and i can't see the answer what I'm doing bad :/
<html>
<head>
<meta charset="utf-8">
<title>Tutorial: Hello Dojo!</title>
<link rel="stylesheet" type="text/css" href="/dojo/dojo.css" />
<link rel="stylesheet" type="text/css" href="/dijit/themes/tundra/tundra.css" />
<script src="dojo/dojo/dojo.js" data-dojo-config="async: true"></script>
<script type="text/javascript">
require(["dojo/_base/fx", "dojo/on", "dojo/dom", "dojo/domReady!"], function(fx, on, dom) {
var fadeOutButton = dom.byId("fadeOutButton"),
fadeInButton = dom.byId("fadeInButton"),
fadeTarget = dom.byId("fadeTarget");
on(fadeOutButton, "click", function(evt){
fx.fadeOut({ node: fadeTarget }).play();
});
on(fadeInButton, "click", function(evt){
fx.fadeIn({ node: fadeTarget }).play();
});
});
</script>
</head>
<body>
<button id="fadeOutButton">Fade block out</button>
<button id="fadeInButton">Fade block in</button>
<div id="fadeTarget" class="red-block" style="margin-left: 20px; height: 300px; width: 200px; background-color: red; margin-top: 20px; text-align: center">
A red block
</div>
</body>
</html>
Something with a syntax probably, but i don't know what

Why is the javascript not working on all referenced IDs

I'm working on a Joomla website. Now I need a slider to change when someone hovers over a text link. I'm using some javascript. It's working on the first div with the id=slider, but not on the second div with id=slider in the article. Can someone tell me why it's doing this?
I'm using the following code in a custom code module for Joomla.
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<title>Untitled Page</title>
<style type="text/css" media="screen">
<!--
.boxVisible {
background-color: #eee;
display: block;
padding: 5px;
float: left;
border: solid 1px #000040
}
.boxHidden {
display: none;
}
-->
</style>
<script type="text/javascript">
<!--
function showHide(slider) {
theBox = document.getElementById(slider);
if (theBox.className == "boxVisible") {
theBox.className = "boxHidden";
} else {
theBox.className = "boxVisible";
}
}
//-->
</script>
</head>
<body bgcolor="#ffffff">
<p>More</p>
</body>
</html>
This is my article:
<div id="slider" class="boxVisible">{loadposition slider1}</div>
<div id="slider" class="boxHidden">{loadposition slider2}</div>
<p><br /><br /><br /> {loadposition java}</p>
IDs must be unique identifiers. For multiple elements, use class names.
Id's should be unique on a page.
You could wrap your slider divs in a wrapper div and use that as basis for iterating through your sliders something like this.
HTML:
<div id="sliders">
<div class="boxVisible"></div>
<div class="boxHidden"></div>
</div>
Javascript:
function showHide2(slider) {
var sliders = document.getElementById(slider).getElementsByTagName("div");
for (s in sliders) {
if (sliders.hasOwnProperty(s)) {
if (sliders[s].className == "boxVisible") {
sliders[s].className = "boxHidden";
alert('changed visible');
} else if (sliders[s].className == "boxHidden") {
sliders[s].className = "boxVisible";
alert('changed hidden');
}
}
}
}
showHide2("sliders");
the dom elements can't have the same id's! if you give the same id to the multiple dom elements, javascript will take only the first one.

Categories