A bizarre glitch when animating a flex box-based progress bar - javascript

I am trying to learn flexbox by implementing a progress bar.
Everything works fine until i try to animate the thing with jquery...
Animate does not seem to work well for the right half after the width is set to at least 75%.
Also it's like the green bar is set to a very big width since it actually takes about a second to come back from 100%+.
I'm not sure if the cause is me not knowing flexbox very well or jQuery freaking out for some reason...
Is this a known issue? Did I do something wrong? Here is my page's code.
This is my code:
button {
height: 50px;
margin: 10px;
width: 50px;
}
.b9k-progress {
border: solid black 2px;
flex-direction: row;
display: flex;
height: 50px;
margin: 10px;
padding: 5px;
}
.b9k-left,
.b9k-right {
height: inherit;
padding: 0;
margin: 0;
}
.b9k-left {
background-color: green;
opacity: 1;
}
.b9k-right {
background: orangered;
flex-grow: 1;
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<div style="width: 80%;margin: 20px 10% ;">
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "0"},2000);'>ZERO</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "20%"},2000);'>25%
</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "50%"},2000);'>50%
</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "75%"},2000);'>75%
</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "100%"},2000);'>100%
</button>
</div>
<div id="the-progress-bar" class="b9k-progress">
<div class="b9k-left"></div>
<div class="b9k-right"></div>
</div>
Is this a known issue? did I do something wrong?

That is because when you are using CSS flexbox in conjunction with percentage based widths, you are forcing the browser to make multiple passes when trying to determine the final width of the element. This causes the bar to initially overshoot its width to >100%, before jQuery properly animates it to the target value.
Solution 1: Use CSS transitions
You don't even need to use jQuery's animate function at all. It can be cumbersome to work with and has catch-alls that people don't know (such as using .stop(true, true) to clear the queue, which you are not using). What you're trying to achieve can be done purely using CSS transitions alone:
$(function() {
$('.button').on('click', function() {
$('#the-progress-bar > .b9k-left').width($(this).data('target-width'));
});
});
button {
height: 50px;
margin: 10px;
width: 50px;
}
.b9k-progress {
border: solid black 2px;
flex-direction: row;
display: flex;
height: 50px;
margin: 10px;
padding: 5px;
}
.b9k-left,
.b9k-right {
height: inherit;
padding: 0;
margin: 0;
/* Enable transition of width */
transition: width 2s ease-in-out;
}
.b9k-left {
background-color: green;
opacity: 1;
/* Give the width a starting value */
width: 0;
}
.b9k-right {
background: orangered;
flex-grow: 1;
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<div style="width: 80%;margin: 20px 10% ;">
<button class="button" data-target-width="0">ZERO</button>
<button class="button" data-target-width="25%">25%
</button>
<button class="button" data-target-width="50%">50%
</button>
<button class="button" data-target-width="75%">75%
</button>
<button class="button" data-target-width="100%">100%
</button>
</div>
<div id="the-progress-bar" class="b9k-progress">
<div class="b9k-left"></div>
<div class="b9k-right"></div>
</div>
Solution 2: Don't use flexbox
A way around this is to actually just remove the use of CSS flexbox, and instead assign the orange background to the parent element instead:
button {
height: 50px;
margin: 10px;
width: 50px;
}
.b9k-progress {
background-color: orangered;
border: solid black 2px;
box-shadow: inset 0 0 0 5px white;
height: 50px;
margin: 10px;
padding: 5px;
}
.b9k-left {
height: inherit;
padding: 0;
margin: 0;
}
.b9k-left {
background-color: green;
opacity: 1;
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<div style="width: 80%;margin: 20px 10% ;">
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "0"},2000);'>ZERO</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "20%"},2000);'>25%
</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "50%"},2000);'>50%
</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "75%"},2000);'>75%
</button>
<button onclick='$("#the-progress-bar>.b9k-left").animate({"width": "100%"},2000);'>100%
</button>
</div>
<div id="the-progress-bar" class="b9k-progress">
<div class="b9k-left"></div>
</div>

You can try this with CSS animations, by just switching the classes on the element:
<div id="the-progress-bar" class="b9k-progress">
<div class="the-progress-bar-progress"></div>
</div>
.the-progress-bar {
background-color: orangered;
}
.the-progress-bar-progress {
position: relative;
width: 100%; height: 100%;
background-color: green;
transition: transform 2s;
transform: scaleX(0);
transform-origin: 0 0;
}
.the-progress-bar-progress--25perc { transform: scaleX(.25); }
.the-progress-bar-progress--50perc { transform: scaleX(.5); }
.the-progress-bar-progress--75perc { transform: scaleX(.75); }
.the-progress-bar-progress--100perc { transform: scaleX(1); }
And you can use this example function to simply change the class applied to the progress:
function changeProgress(e) {
var progressBar = document.getElementById('the-progress-bar');
progressBar.classList = 'b9k-progress';
var targetClass = e.target.getAttribute('data-progressClass');
if(targetClass && targetClass != '') {
progressBar.classList.add(targetClass);
};
};
<button onclick='changeProgres();' data-progressClass="">ZERO</button>
<button onclick='changeProgres();' data-progressClass="the-progress-bar-progress--25perc">25%</button>
<button onclick='changeProgres();' data-progressClass="the-progress-bar-progress--50perc">50%</button>
or
function changeProgress(progressClass__string) {
var targetClass = progressClass__string || '';
document.getElementById('the-progress-bar').classList = 'b9k-progress ' + progressClass__string;
};
<button onclick="changeProgres();">ZERO</button>
<button onclick="changeProgres('the-progress-bar-progress--25perc');">25%</button>
<button onclick="changeProgres('the-progress-bar-progress--50perc');">50%</button>

Related

Make dynamic fontsize using javascript to fit into a button

I have a button of fixed size and various chunks of text. The length of the texts is different. How can I make the size of the text font change dynamically according to its length in order to fit the button boundaries properly? Thank you.
Well, depends. Is the height fix as well? If both height and width are fixed, you will have to calculate the fontsize via javascript.
In most of the cases two or three if conditions should be absolutely sufficient for the specific usecase.
function font_size_adjust () {
// Grab the string
var string = $('#button_text').text()
// Get the length in characters of the string
var string_size = string.length
// Build variable to change attribute
var font_size = 0
// Define logic for resizing, adapt this to your personal needs
if (string_size < 60) {
fontsize = '2vw';
} else if (string_size > 60) {
fontsize = '4vw';
} else {}
// Change fontsize
$('#button_text').css('font-size', fontsize)
}
// Call the function where- and whenever needed:
font_size_adjust();
// Example stuff
$('#toggle_small').click(function () {
$('#button_text').text('Now I am small again!')
font_size_adjust();
})
$('#toggle_big').click(function () {
$('#button_text').text('Now I am large again! Lets get this rollin! rollin! rollin! rollin!')
font_size_adjust();
})
#ctn {
display: flex;
float: left;
}
#button {
width: 45vw;
background-color: lightblue;
padding: 10px;
border-radius: 25px;
margin-right: 1vw;
font-family: Varela Round;
color: #FFF;
background: linear-gradient(126deg, rgba(143,61,217,1) 12%, rgba(109,35,177,1) 43%, rgba(101,34,162,1) 72%);
}
#ctn_toggle {
display: flex;
float: left;
}
.toggle {
background-color: lightblue;
font-size: 3vw;
padding: 10px;
border-radius: 25px;
width: 11vw;
text-align: center;
margin-right: 2vw;
font-family: Varela Round;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Varela+Round&display=swap" rel="stylesheet">
<html>
<body>
<div id="ctn">
<div id="button">
<p id="button_text">Make me small and big all day long this is so exciting! Let's go broooh!</p>
</div>
</div>
<div id="ctn_toggle">
<div id="toggle_small" class="toggle">
<p id="button_small">Click me to shrink!</p>
</div>
<div id="toggle_big" class="toggle">
<p id="button_big">Click me to expand!</p>
</div>
</div>
</body>
</html>
Otherwise, these are the options... :
#ctn {
display: flex;
float: left;
}
#button {
width: 20vw;
background-color: lightblue;
padding: 10px;
border-radius: 25px;
margin-right: 1vw;
}
#button_text {
font-size: 4vw;
}
#button2 {
width: 20vw;
background-color: lightblue;
padding: 10px;
border-radius: 25px;
margin-right: 1vw;
}
#button_text2 {
}
#button3 {
width: 20vw;
height: 10vh;
background-color: lightblue;
padding: 10px;
border-radius: 25px;
margin-right: 1vw;
}
#button_text3 {
font-size: 4vw;
}
#button4 {
width: 20vw;
height: 10vh;
background-color: lightblue;
padding: 10px;
border-radius: 25px;
}
#button_text4 {
}
<html>
<body>
<div id="ctn">
<div id="button">
<p id="button_text">Fix button width and fix font-size</p>
</div>
<div id="button2">
<p id="button_text2">Fix button width and no specific font-size</p>
</div>
<div id="button3">
<p id="button_text3">Fix button width, fix button height and fix font-size</p>
</div>
<div id="button4">
<p id="button_text4">Fix button width, fix button height and no font-size</p>
</div>
</div>
</body>
</html>

Is there a way to jump from a section into another section with Vanilla JavaScript?

I have two sections one over the other.
What I want to do is that when I click the button, the first section display: none with a small transition and the second one appears. I need to do that with vanilla JavaScript as I'm learning it.
My goal is to be able to create a login when the password is entered, the person is moved to the second section. (this is just for Front end, nothing backend).
Here is the code below:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Login Background */
#first{
position: absolute;
width: 100%;
height: 100vh;
background-color: #464159;
z-index: 1;
}
/* Login */
.login-container{
position: absolute;
top: 50%;
right: 50%;
transform: translate(50%, -100%);
display: flex;
align-items: center;
justify-content: center;
}
.logo{
justify-content: center;
margin-right: 20px;
}
.logo img{
width: 180px;
height: auto;
}
.user{
display: flex;
flex-direction: column;
}
.w8u{
color: white;
font-size: 15px;
margin: 0 0 10px 0;
}
.submit{
flex: 1;
margin: 30px 0 0 10px;
}
/* Menu */
#second{
position: absolute;
width: 100%;
height: 100vh;
background-color: orangered;
z-index: -1;
}
<body>
<section id="first">
<div class="login-container">
<!-- Logo User -->
<div class="logo">
<img src="w-logo.jpg" alt="User">
</div>
<!-- User Name -->
<div class="user">
<div class="w8u">
<h3>User</h3>
</div>
<div>
<input class="input" type="password" placeholder="Enter your password" required>
</div>
</div>
<!-- Submit Button -->
<button id="btn-submit" class="submit" type="submit" onclick="">GO!</button>
</section>
<section id="second">
</section>
<script src="app.js"></script>
</body>
Yes, you can change CSS of elements using JavaScript:
function login(){
document.getElementById("first").style.display="none";
document.getElementById("second").style.display="block";
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Login Background */
#first{
position: absolute;
width: 100%;
height: 100vh;
background-color: #464159;
z-index: 1;
}
/* Login */
.login-container{
position: absolute;
top: 50%;
right: 50%;
transform: translate(50%, -100%);
display: flex;
align-items: center;
justify-content: center;
}
.logo{
justify-content: center;
margin-right: 20px;
}
.logo img{
width: 180px;
height: auto;
}
.user{
display: flex;
flex-direction: column;
}
.w8u{
color: white;
font-size: 15px;
margin: 0 0 10px 0;
}
.submit{
flex: 1;
margin: 30px 0 0 10px;
}
/* Menu */
#second{
position: absolute;
width: 100%;
height: 100vh;
background-color: orangered;
z-index: -1;
}
<body>
<section id="first">
<div class="login-container">
<!-- Logo User -->
<div class="logo">
<img src="w-logo.jpg" alt="User">
</div>
<!-- User Name -->
<div class="user">
<div class="w8u">
<h3>User</h3>
</div>
<div>
<input class="input" type="password" placeholder="Enter your password" required>
</div>
</div>
<!-- Submit Button -->
<button id="btn-submit" class="submit" type="submit" onclick="login()">GO!</button>
</section>
<section id="second">
Section 2
</section>
<script>
</script>
</body>
Short Answer:
You can solve your issue by using a common pattern of styling transitions and toggling classes in JavaScript.
/* Get Screen Container */
let context = document.querySelector("main.screen-container");
/* Helper Methods */
// Utility
const ele = context.querySelector.bind(context),
eles = context.querySelectorAll.bind(context);
// Action
const showScreen = inactiveScreen => {
const screens = eles(".screen");
screens.forEach(screen => screen.classList.remove("active-screen"));
inactiveScreen.classList.add("active-screen");
}
// Elements
const login_button = ele("#loginBtn"),
logout_button = ele("#logoutBtn"),
login_screen = ele("#login"),
loggedIn_screen = ele("#loggedIn");
// Add Event Listeners and Handlers
login_button.addEventListener("click", () => showScreen(loggedIn_screen));
logout_button.addEventListener("click", () => showScreen(login_screen));
.full-width-full-height {
width: 100%;
height: 100%;
}
.no-overflow {
overflow: hidden;
}
.inputs-container {
display: flex;
flex-direction: column;
justify-content: center;
height: 200px;
padding: 5px;
border: 5px black solid;
}
.inputs-container.inputs {
padding: 10px;
}
.screen#login {
display: flex;
justify-content: center;
}
.screen#loggedIn {
background: rgba(0,0,0,.5);
border: 5px solid rgba(0,0,0,.3);
text-align: center;
}
highlight {
color: rgb(0,100,0);
text-shadow: 3px 3px 10px rgb(0,200,0);
}
.screen-container {
height: 100%;
width: 100%;
overflow: hidden;
padding: 0px;
margin: 0px;
}
main section {
position: absolute;
height: 0px;
width: 0px;
opacity: 0;
transition: all .3s ease-in-out;
}
main section.active-screen {
height: 100%;
width: 100%;
opacity: 1;
}
<body class="full-width-full-height no-overflow">
<main class="screen-container full-width-full-height">
<section id="login" class="screen active-screen">
<div class="inputs-container">
<div class="inputs"><label>Username:</label><input type="text" id="username" placeholder="admin" /></div>
<div class="inputs"><label>Password:</label><input type="password" id="password" /></div>
<button id="loginBtn">login</button>
</div>
</section>
<section id="loggedIn" class="screen">
<h3>User Successfully <highlight>Logged In</highlight></h3>
<button id="logoutBtn">logout</button>
</section>
</main>
</body>
Explanation of Answer:
In your question you're asking for help in the following:
Using Sections as Different Screens in an Application
Change Screens on an Event such as click
Transition between Screens when the Screen Changes
Something like this isn't an atypical need and, in fact, just looking at the above you can see the resemblance between what you're looking for and common things like a carousel or tab navigation.
Since this is the case there is a pretty common pattern when designing markup based around these types of requirements and this pattern is used in frameworks like BootStrap, DataTables, JQuery, etc.
The Mark-Up Pattern:
Create a Container
Provide a class to define this type of container ( screen-container )
Create Visual Elements
In your case Section Elements dubbed Screens
Provide a class to define these specific elements
In your case something like screen
You will likely also want to provide an ID for each of these Visual Elements based on their Content.
In your case something like login and loggedIn
Create a class that will serve as the active Visual Element
In your case something like active-screen
Incorporating the above you end up with a basic outline:
<main class="screen-container">
<section id="login" class="screen active-screen"></section>
<section id="loggedIn" class="screen"></section>
</main>
Example:
html, body, main, .screen-container {
height: 100%;
width: 100%;
}
.screen-container
.screen {
padding: 3px;
background: rgba(24,24,24, .3);
border: 3px solid black;
width: 100px;
height: 100px;
}
.screen-container
.screen.active-screen {
border-color: green;
}
<main class="screen-container">
<section id="login" class="screen active-screen">login</section>
<section id="loggedIn" class="screen">logged in</section>
</main>
Styling:
In your initial question you say that you want to use the display property to hide and show your screens, however, you also state that you would like to have the screens transition from one to another.
Transitioning is definitely possible through the aptly named CSS transition property ( More info on MDN ).
The problem is that the display property is not able to be animated. If an element is configured to display: none; the page is immediately repainted with that element removed.
This means that you need to use a different property, and we typically would use opacity or visibility. Here are the differences between these three:
display: none;
immediately collapses the element
removes the element from view.
There's no transition allowed.
visibility: hidden;
Does not collapse the element
The space it occupied is blank.
removes the element from view
Transitions are allowed
The element will still pop out of sight.
opacity: 0;
Does not collapse the element
The space it occupied is blank.
removes the element from view
Transitions are allowed.
The element will fade until it is not visible.
Here is an example of the different way these properties affect the layout of the page:
const context = document.querySelector("#examples");
const ele = context.querySelector.bind(context),
hide = section => section.classList.toggle("hide"),
onClickHide = (btn, section) => btn.addEventListener("click", () => hide(section));
opacity = ele(".opacity"),
opacity_button = ele("#oBtn"),
visibility = ele(".visibility"),
visibility_button = ele("#vBtn"),
display = ele(".display"),
display_button = ele("#dBtn"),
toggle_button = ele("#tBtn");
onClickHide(opacity_button, opacity);
onClickHide(visibility_button, visibility);
onClickHide(display_button, display);
toggle_button
.addEventListener("click", function() {
hide(opacity);
hide(visibility);
hide(display);
});
html,
body,
#examples {
width: 100%;
height: 100%;
box-sizing: content-box;
margin: 0px;
padding: 0px;
}
#examples section {
display: flex;
flex-direction: column;
width: 100px;
height: 100px;
border: 5px solid black;
margin: 5px;
transition: all .5s ease-in-out;
}
#examples section.hide {
border-radius: 100px;
}
#examples section.opacity {
background-color: blue;
color: white;
}
#examples section.opacity.hide {
opacity: 0;
}
#examples section.visibility {
background-color: purple;
color: white;
}
#examples section.visibility.hide {
visibility: hidden;
}
#examples section.display {
display: block;
background-color: red;
color: white;
}
#examples section.display.hide {
color: black;
display: none;
}
<main id="examples">
<section class="opacity">opacity <button id="oBtn">hide</button></section>
<hr />
<section class="visibility">visibility <button id="vBtn">hide</button></section>
<hr />
<section class="display">display <button id="dBtn">hide</button></section>
<hr/>
<button id="tBtn">Toggle All</button>
</main>
Note: In the above there are actually two properties transitioning - opacity, visibility, or display - and border-radius. You should notice firstly how in the display example the border-radius change isn't seen at all, and secondly how the display example is the only one that collapses the element so that it no longer takes up space.
Applying Transitions:
By combining opacity: 0; with height: 0px; width: 0px; we can remove the element visually from the page while also removing any impact it has on other elements - meaning that it won't take up space and is transitionable.
setInterval(function() {
const screens = [
document.querySelector(".screen.active-screen"),
document.querySelector(".screen:not(.active-screen)")
];
screens[0].classList.toggle("active-screen");
screens[0].ontransitionend = () => {
screens[1].classList.toggle("active-screen");
screens[0].ontransitionend = undefined;
}
}, 1000)
html,
body,
main,
.screen-container {
height: 100%;
width: 100%;
}
.screen-container .screen {
transition: all .3s ease-in-out;
opacity: 0;
height: 0px;
width: 0px;
}
.screen-container .screen.active-screen {
background: rgba(24, 24, 24, .3);
border: 3px solid black;
padding: 3px;
border-color: green;
width: 100px;
height: 100px;
opacity: 1;
}
<main class="screen-container">
<section id="login" class="screen active-screen">login</section>
<section id="loggedIn" class="screen">logged in</section>
</main>
JavaScript
The final piece of the puzzle is the JavaScript mechanics of the Screens.
Any Programmer wants to make the switch as easy as possible, and this is done typically by providing a function that allows for quick reassignment of the class active-screen by removing it from the current active screen and applying it to the desired visual element.
One thing to take into account is that you want your queries for elements to be as specific as possible. Meaning that instead of document.querySelector you want to provide the smallest context of where to find your Visual Elements. a.e.
/* Get Screen Container */
let context = document.querySelector("main.screen-container");
/* Helper Methods */
// Utility
const ele = context.querySelector.bind(context),
eles = context.querySelectorAll.bind(context);
This prevents code collision where other code in your Application's JavaScript, Styling, or Mark-Up may utilize a screen or active-screen class that isn't relevant to what you're doing here.
Note: This is actually a problem in BootStrap currently. It searches for the active class in it's Tab architecture. This is such a generic class name that other libraries utilize it and it can cause a giant headache to get things to work properly. Writing explicit patching because you didn't think through your design fully is something I'd just as soon spare you from, so try to keep interactivity with other code in mind.
Lastly we write our function ( showScreen ) that allow for quick, easy switching between screens:
// Action
const showScreen = inactiveScreen => {
const screens = eles(".screen");
screens.forEach(screen => screen.classList.remove("active-screen"));
inactiveScreen.classList.add("active-screen");
}
And believe it or not, that's pretty much it!
All that's left to do is apply this functionality to your button click events and it works just as it should:
Result:
/* Get Screen Container */
let context = document.querySelector("main.screen-container");
/* Helper Methods */
// Utility
const ele = context.querySelector.bind(context),
eles = context.querySelectorAll.bind(context);
// Action
const showScreen = inactiveScreen => {
const screens = eles(".screen");
screens.forEach(screen => screen.classList.remove("active-screen"));
inactiveScreen.classList.add("active-screen");
}
// Elements
const login_button = ele("#loginBtn"),
logout_button = ele("#logoutBtn"),
login_screen = ele("#login"),
loggedIn_screen = ele("#loggedIn");
// Add Event Listeners and Handlers
login_button.addEventListener("click", () => showScreen(loggedIn_screen));
logout_button.addEventListener("click", () => showScreen(login_screen));
.full-width-full-height {
width: 100%;
height: 100%;
}
.no-overflow {
overflow: hidden;
}
.inputs-container {
display: flex;
flex-direction: column;
justify-content: center;
height: 200px;
padding: 5px;
border: 5px black solid;
}
.inputs-container.inputs {
padding: 10px;
}
.screen#login {
display: flex;
justify-content: center;
}
.screen#loggedIn {
background: rgba(0,0,0,.5);
border: 5px solid rgba(0,0,0,.3);
text-align: center;
}
highlight {
color: rgb(0,100,0);
text-shadow: 3px 3px 10px rgb(0,200,0);
}
.screen-container {
height: 100%;
width: 100%;
overflow: hidden;
padding: 0px;
margin: 0px;
}
main section {
position: absolute;
height: 0px;
width: 0px;
opacity: 0;
transition: all .3s ease-in-out;
}
main section.active-screen {
height: 100%;
width: 100%;
opacity: 1;
}
<body class="full-width-full-height no-overflow">
<main class="screen-container full-width-full-height">
<section id="login" class="screen active-screen">
<div class="inputs-container">
<div class="inputs"><label>Username:</label><input type="text" id="username" placeholder="admin" /></div>
<div class="inputs"><label>Password:</label><input type="password" id="password" /></div>
<button id="loginBtn">login</button>
</div>
</section>
<section id="loggedIn" class="screen">
<h3>User Successfully <highlight>Logged In</highlight></h3>
<button id="logoutBtn">logout</button>
</section>
</main>
</body>
Conclusion:
I hope this helps and gives you some insight into how this pattern is used! It's not a difficult thing to learn, but it's incredibly useful!
Good luck and Happy Coding!

How do I give elements with the same class name to perform the same function in javascript?

I have multiple elements with the same class name and want them to perform the same javascript function but output their unique "inner.Text" specific
to the element i clicked. Right Now i know i need an [index] and a loop
but I just don't know how to implement that at the moment since im a novice in javascript.
spent 3 hours trying to figure it out
const myButton = document.querySelectorAll('.clipboard-icon');
const myInp = document.querySelectorAll('.snippetcode');
myButton.forEach(ree =>
ree.addEventListener('click', copyElementText));
function copyElementText(id) {
var text = myInp.innerText;
var elem = document.createElement("textarea");
document.body.appendChild(elem);
elem.value = text;
elem.select();
document.execCommand("copy");
document.body.removeChild(elem);
console.log('clicked');
}
console.log(myButton);
console.log(myInp);
/*everything works fine if the script was changed to affect only ONE class name but I cant figure out how to make them work for more than one
*/
.snippet1 {
border: solid rgb(55, 63, 184) 3px;
}
.snippet_holder {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
padding: 0 3.5rem;
margin: 0 0 1rem 0;
position: relative;
}
.buttons {
width: 170px;
height: 40px;
border: 0;
padding: 0;
font-size: 1rem;
color: #fff;
border-radius: 10px;
}
.snippet_holder:hover .clipboard-icon {
display: block;
position: absolute;
top: 15px;
right: 65px;
background: rgb(51, 153, 136);
margin: 0;
width: 30px;
padding: 0;
height: 30px;
}
.clipboard-icon {
display: none;
}
.clipboard-icon img {
width: inherit;
height: inherit;
position: relative;
}
.clipboard-icon pre {
display: none;
}
.snippetcode1 {
display: none;
}
.button1 {
-webkit-animation: rainbow 6.5s ease infinite;
animation: rainbow 6.5s ease infinite;
background-image: linear-gradient(124deg, #ff470f, #ff3860, #b86bff, #3273dc);
background-size: 800% 800%;
}
#keyframes rainbow {
0% {
background-position: 1% 80%;
}
50% {
background-position: 99% 20%;
}
100% {
background-position: 1% 80%;
}
0% {
background-position: 1% 80%;
}
50% {
background-position: 99% 20%;
}
100% {
background-position: 1% 80%;
}
}
main {
margin: 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
<html>
<body>
<main>
<div class="snippet_holder snippet_holder1">
<div class="clipboard-icon">
<pre>
<code class= "snippetcode">
1st class text copieddddd
</code>
</pre>
<img src="https://www.shareicon.net/data/128x128/2016/04/27/756265_clipboard_512x512.png">
</div>
<button type="button" class="buttons button1">button</button>
</div>
<div class="snippet_holder snippet_holder1">
<div class="clipboard-icon">
<pre>
<code class= "snippetcode">
22222nddd class text copieddddd
</code>
</pre>
<img src="https://www.shareicon.net/data/128x128/2016/04/27/756265_clipboard_512x512.png">
</div>
<button type="button" class="buttons button1">button</button>
</div>
<div class="snippet_holder snippet_holder1">
<div class="clipboard-icon">
<pre>
<code class= "snippetcode">
3rd class text copieddddd
</code>
</pre>
<img src="https://www.shareicon.net/data/128x128/2016/04/27/756265_clipboard_512x512.png">
</div>
<button type="button" class="buttons button1">button</button>
</div>
<div class="snippet_holder snippet_holder1">
<div class="clipboard-icon">
<pre>
<code class= "snippetcode">
4thhhhhhhhclass text copieddddd
</code>
</pre>
<img src="https://www.shareicon.net/data/128x128/2016/04/27/756265_clipboard_512x512.png">
</div>
<button type="button" class="buttons button1">button</button>
</div>
</main>
</body>
</html>
You've to query the .snippetcode related to the button pressed, so, it makes no sense to query the nodeList myInp, you can access to the right element using the currentTarget provided in the event object...
function copyElementText(event) {
var text = event.currentTarget.querySelector('.snippetcode').innerText;
var elem = document.createElement("textarea");
document.body.appendChild(elem);
elem.value = text;
elem.select();
document.execCommand("copy");
document.body.removeChild(elem);
console.log('clicked');
}

JavaScript adding classes on multiple modals

I'm kind of desperate. I'm trying to make the same modal as Behance has when you click on one of the little windows but I can't get my JavaScript to work. I'm not able to show "test2".
function modalActive(){
document.getElementsByClassName("window")[0].classList.add("modalActive")
};
function closeModal(){
document.getElementsByClassName("window")[0].classList.remove("modalActive")
};
.gallery-item {
width: 120px;
height: 120px;
border: 3px solid gray;
float: left;
margin-left: 10px;
}
.window {
display: none;
height: 500px;
width: 500px;
Background-color: gray;
z-index: 100000;
position: absolute;
margin: 0 auto;
}
.modalActive {
display: block !important;
}
<div class="gallery-item">
<button class="button" onclick="modalActive()">derp</button>
</div>
<div class="window">
<button class="close" onclick="closeModal()">×</button>
test1
</div>
<div class="gallery-item">
<button class="button" onclick="modalActive()">derp</button>
</div>
<div class="window">
<button class="close">×</button>
test2 - im not able to see this due to some error in my code/knowledge
</div>
You have to target a specific modal to open when clicking on the buttons. At the moment you are only ever finding the first modal and setting the modalActive class.
I have updated your code below to pass the modal id number when clicking on a button.
function modalActive(id){
document.getElementsByClassName("window-" + id)[0].classList.add("modalActive")
};
function closeModal(){
document.getElementsByClassName("modalActive")[0].classList.remove("modalActive")
};
.gallery-item {
width: 120px;
height: 120px;
border: 3px solid gray;
float: left;
margin-left: 10px;
}
.window {
display: none;
height: 500px;
width: 500px;
Background-color: gray;
z-index: 100000;
position: absolute;
margin: 0 auto;
}
.modalActive {
display: block !important;
}
<div class="gallery-item">
<button class="button" onclick="modalActive(1)">derp</button>
</div>
<div class="window window-1">
<button class="close" onclick="closeModal()">×</button>
test1
</div>
<div class="gallery-item">
<button class="button" onclick="modalActive(2)">derp</button>
</div>
<div class="window window-2">
<button class="close" onclick="closeModal()">×</button>
test2 - im not able to see this due to some error in my code/knowledge
</div>

Issue showing a selected id

I am having an issue getting tabs to open based on the selection I am choosing. In the snippet you will see 4 boxes. If you click on box 1, I am wanting #marketing1 to open below it and so on.
The method I am using is to get the specific id of the button selection (the 1,2,3,4 box) and then declare a variable to just get the number. Then to add that number to the id of #marketing to show the appropriate section. I am not sure what I am doing wrong. No errors are showing.
Ps - I am also trying to add an .active class to the #marketing-service for when one of the selection boxes is clicked on to show my the active class (it creates a down arrow under the box. Am I implementing the .active wrong to the :before and :after?
//For tabs to stay active
$('.marketing-service').click(function() {
$('.marketing-service.active').removeClass('active');
$(this).toggleClass('active');
//To get the service display box to show
var item_number = $(this).attr('id').replace('marketing-tab', '');
/* $('html, body').animate({
scrollTop: $("#service-display-box").offset().top
}, 1500);*/
$('#marketing'+item_number).show().siblings('.marketing-section-wrap').hide();
});
.marketing-section-wrap, .marketing-section-wrap-main {
width: 100%;
height: auto;
padding: 80px 0;
border-bottom: 1px solid #EBEBEB;
}
.marketing-section-wrap {
display: none;
}
#marketing-services {
width: 95%;
margin: 0 2.5%;
}
.marketing-service {
display: inline-block;
width: 22%;
margin: 0 1%;
height: 400px;
background: #F0F0F0;
position: relative;
cursor: pointer;
}
.marketing-service:first-child {
margin-left: 0;
}
.marketing-service:last-child {
margin-right: 0;
}
.marketing-service:hover {
background: rgba(0, 255, 170, .4);
z-index: 1;
}
/*-- Down Arrow for boxes --*/
.marketing-service:after.active, .marketing-service:before.active {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
}
.marketing-service:after.active {
border-width: 0px;
margin-left: 0px;
border-color: rgba(136, 183, 213, 0);
border-right-color: #88b7d5;
margin-top: -30px;
}
.marketing-service:before.active {
border-color: #FFF;
border-top-color: #88b7d5;
border-width: 36px;
margin-left: -36px;
margin-top: 0;
}
.marketing-service-wrap {
padding: 10%;
width: 80%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="marketing-services">
<div class="marketing-service" id="marketing-tab1">
<div class="marketing-service-wrap total-center">
<h2 class="marketing-service-title">1</h2>
</div>
</div>
<div class="marketing-service" id="marketing-tab2">
<div class="marketing-service-wrap total-center">
<h2 class="marketing-service-title">2</h2>
</div>
</div>
<div class="marketing-service" id="marketing-tab3">
<div class="marketing-service-wrap total-center">
<h2 class="marketing-service-title">3</h2>
</div>
</div>
<div class="marketing-service" id="marketing-tab4">
<div class="marketing-service-wrap total-center">
<h2 class="marketing-service-title">4</h2>
</div>
</div>
</div>
<div id="marketing1">
<div class="marketing-section-wrap">
1
</div>
</div>
<div id="marketing2">
<div class="marketing-section-wrap">
2
</div>
</div>
Quite simple just try $('#marketing'+item_number).children().show() because marketing-section-wrap is display:none;
first run this to hide all marketing-section-wrap
$('.marketing-section-wrap').hide();
then this will show only the one which corresponds to this click.
$('#marketing'+item_number).children().show();

Categories