I have a CSS script which has 5 buttons.
Clicking the first button should display a text on the same page in a fixed region (maybe by using frames or writing a hidden function and then doing show()).
If the second button is clicked, some other text should appear in the earlier region. Similarly for other buttons. What would be the most efficient way of doing this? (Achieving the fastest loading of the page).
Try this:
HTML
<div id="textcontainer"></div>
<button id="button1" onclick="setText(0);">Button 1</button>
<button id="button2" onclick="setText(1);">Button 2</button>
<button id="button3" onclick="setText(2);">Button 3</button>
<button id="button4" onclick="setText(3);">Button 4</button>
<button id="button5" onclick="setText(4);">Button 5</button>
Javascript:
var text = [
'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.',
'Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.',
'Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.',
'Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.',
'Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. Mauris eget neque at sem venenatis eleifend. Ut nonummy.'
];
function setText(index){
var box = document.getElementById('textcontainer');
box.innerHTML = text[index];
}
You can see this in action at: http://jsfiddle.net/Wnw7X/
I guess this?
<iframe name="content"></iframe>
Button 1
Button 2
And so on...
Then add some CSS to make them look like buttons (border, background, etc)
ok, here is a complete demo - copy all the code and paste your editor. and run.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript">
window.onload = function() {
var myArray = ['you click the first button', 'you click the second button', 'you click the third button', 'you click the fourth button', 'you click the fifth button'];
var one = document.getElementById('buttonOne');
var two = document.getElementById('buttonTwo');
var three = document.getElementById('buttonThree');
var four = document.getElementById('buttonFour');
var five = document.getElementById('buttonFive');
one.onclick = clickHandler;
two.onclick = clickHandler;
three.onclick = clickHandler;
four.onclick = clickHandler;
five.onclick = clickHandler;
function clickHandler(evt) {
//console.log(evt.target.id);
var header = document.getElementsByTagName('h1')[0];
if(evt.target.id === 'buttonOne') {
header.innerHTML = myArray[0];
console.log(myArray[0]);
console.log('click');
}
else if (evt.target.id === 'buttonTwo') {
header.innerHTML = myArray[1];
}
else if (evt.target.id === 'buttonThree') {
header.innerHTML = myArray[2];
}
else if (evt.target.id === 'buttonFour') {
header.innerHTML = myArray[3];
}
else if (evt.target.id === 'buttonFive') {
header.innerHTML = myArray[4];
}
}
}
</script>
</head>
<body>
<button id="buttonOne">One</button>
<button id="buttonTwo">Two</button>
<button id="buttonThree">Three</button>
<button id="buttonFour">Four</button>
<button id="buttonFive">Five</button>
<h1> </h1>
</body>
</html>
Related
I am trying to get the height on an element.
I want the parent div to adjust its height to the first paragraph of its children paragraph elements. Then a "Read More"/"Read Less" button expands the parent div to reveal all paragraphs or shrinks to only one paragraph.
I have experimented with useEffect, useLayoutEffect and componentDidMount in a class component and they all seem to need a setTimeout delay for the parent div to attain the perfect height.
Sorry if my code is fuzzy. I am new to React. :)
TIA
import styled from 'styled-components'
import React, { useRef, useLayoutEffect, useState } from 'react'
const CatIntroStyled = styled.div`
width: 1000px;
margin: 0 auto;
button{
display: block;
margin: 0 auto;
background: none;
}
button:focus{
outline: none;
}
`
const IntroText = styled.div`
height: ${({introStyle})=>{
if(introStyle.initIntroHeight === "auto") return "auto"
return introStyle.introExpanded ? introStyle.initIntroHeight+"px": introStyle.initFirstPara+"px";
}};
overflow: hidden;
transition: all 1s;
margin-bottom: 2rem
`
const formatIntro = (text, paraRef)=>{
let formatedText = text.replace(/<[^>]*>?/gm, "").replace(/\n\r/g, "")
let returnText = formatedText.split("\r\n").map((paragraph, key) => {
if(key===0) return <p ref={paraRef} key={key}>{paragraph}</p>;
return <p key={key}>{paragraph}</p>
})
return returnText
}
const CatIntro = ({title, text})=>{
const firstIntroPara = useRef();
const introRef = useRef();
const [intro, setIntro] = useState({
initFirstPara: 0,
initIntroHeight: "auto",
introExpanded: false
})
useLayoutEffect(()=>{
setTimeout(()=>{
setIntro({
...intro,
initIntroHeight: introRef.current.offsetHeight,
initFirstPara: firstIntroPara.current.offsetHeight,
})
}, 1000)
}, [])
return(
<CatIntroStyled>
<h1 className="globalTitleStyle">{title}</h1>
<IntroText ref={introRef} introStyle={intro}>
{formatIntro(text, firstIntroPara)}
</IntroText>
<button onClick={(e)=>{
setIntro({
...intro,
introExpanded: !intro.introExpanded
})
}}>{ intro.introExpanded ? "READ LESS": "READ MORE" }</button>
</CatIntroStyled>
)
}
export default CatIntro
Is there a more robust way of knowing when elements are truly painted on the screen?
TIA
Try using useLayoutEffect.
This runs synchronously immediately after React has performed all DOM mutations. This can be useful if you need to make DOM measurements (like getting the scroll position or other styles for an element).
Example
function App() {
const divRef = React.useRef(null);
React.useLayoutEffect(() => {
console.log(divRef.current.clientHeight)
}, [])
return (
<div ref={divRef} style={{ height: 100, width: 100, backgroundColor: 'red' }}/>
);
}
For this :- You need to change your class component to functional ones.
Maybe i don't fully understand why you need the height.
But if each child of the component is a paragraph, and you either want to show all the paragraphs when expanded, but only one paragraph when not expanded, you could do something like this:
import React, { useState } from "react";
export default function Expandable({ children, initial = false }) {
const [expanded, setExpanded] = useState(initial);
return (
<div>
{expanded ? children : [...children].slice(0,1)}
<button onClick={() => setExpanded(!expanded)}>{`Read ${
expanded ? "less" : "more"
}`}</button>
</div>
);
}
Then you could consume the component like this:
<Expandable>
<p>
egestas ultrices. Curabitur eget lorem eu augue pretium blandit at non
metus. Mauris a venenatis tellus, vel mollis leo. Vivamus nec
elementum neque, non mollis felis.
</p>
<p>
fringilla. Sed convallis sem sed diam vehicula egestas. In tincidunt
hendrerit elit, eu facilisis leo vulputate id. Sed rutrum imperdiet
convallis. Nam mi magna, lacinia vitae consequat vel, consequat eget
ex. Maecenas nec ex egestas, mattis orci sit amet, dictum sem. Sed id
tincidunt felis. Vivamus ipsum erat, sagittis sed consequat et,
molestie a risus. Quisque nec risus fringilla, pellentesque leo a,
venenatis leo.
</p>
<p>
est in varius pulvinar. Ut dignissim condimentum semper. Vestibulum
blandit purus vitae dapibus finibus. Nam iaculis metus orci, et
posuere lectus imperdiet at. Suspendisse non erat tortor.
</p>
<p>ullamcorper sagittis.</p>
</Expandable>
Edit:
You can get the height of the first paragraph like this.
Note: with this approach, you probably need to listen for a resize event and adjust the value of the height state.
import React, { useState, useEffect, useRef } from "react";
export default function Expandable({ children, initial = false }) {
const [expanded, setExpanded] = useState(initial);
const [firstParagraphHeight, setFirstParagraphHeight] = useState(0);
const ref = useRef(null);
useEffect(() => {
const height = ref.current.children[0].getBoundingClientRect().height;
setFirstParagraphHeight(height);
}, []);
return (
<>
<div
ref={ref}
style={{
overflow: "hidden",
maxHeight: expanded ? "none" : `${firstParagraphHeight}px`
}}
>
{children}
</div>
<button onClick={() => setExpanded(!expanded)}>{`Read ${
expanded ? "less" : "more"
}`}</button>
</>
);
}
I have a number of user stories on my website page. I don't want to show the entirety of each story if the user doesn't want to read it, so I show the first 2 lines and there is a Show more link to press to see the whole story. The user can then press the link again to See less. The issue comes when the user clicks the Show less link, the story condenses and shows 2 lines, but there is a momentary flicker of say 2 additional lines (can't quite make it out as its there for a few milliseconds). And it is this that I don't want.
This is my HTML and jQuery which is loaded via Ajax Request.
$(document).ready(function() {
$(".content").on("click", ".showMore a", function() {
var $this = $(this);
var content = $this.parent().prev()
var linkText = $this.text().toUpperCase();
if (linkText === "SHOW MORE") {
linkText = "Show less";
content.switchClass("hideContent", "showContent", 400);
} else {
linkText = "Show more";
content.switchClass("showContent", "hideContent", 400);
}
$this.text(linkText);
});
});
.hideContent {
overflow: hidden;
line-height: 1em;
height: 4em;
}
.showContent {
line-height: 1em;
height: auto;
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="hideContent" style="">
<div class="post-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id erat pharetra risus fermentum aliquam. Maecenas eu nisi posuere, rutrum orci et, imperdiet elit. Nulla tempor imperdiet sagittis. Aenean cursus justo ac enim lacinia vehicula. Etiam dictum
suscipit nibh, at iaculis velit lobortis vel. Duis pretium diam ut lectus mollis vehicula.</div>
<div class="post-action"><input type="button" value="Like" id="like_94" class="like"><span class="likesTotal" id="likes_94">0</span>
</div>
</div>
<div class="showMore"><a>Show more</a></div>
</div>
</div>
I hope that's what you wanted. You can do this easily by using .addClass and .removeClass
Also. if you content and stories display as exactly as the example in question then .parent() is not what you want you can call .prev() and it will work just find.
Simple Show and Hide
Using addClass and removeClass
Working Demo: https://jsfiddle.net/usmanmunir/cks8d067/
Run snippet below to see it working.
$(document).ready(function() {
$(".showMore").on("click", function() {
var $this = $(this);
var content = $this.prev()
var linkText = $this.text().toUpperCase();
if (linkText === "SHOW MORE") {
linkText = "Show less";
content.addClass("showContent").removeClass("hideContent");
} else {
content.addClass("hideContent").removeClass("showContent");
linkText = "Show more";
}
$this.text(linkText);
});
});
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent {
line-height: 1em;
height: auto;
}
.showMore {
cursor: pointer;
}
<div class="hideContent">
<div class="post-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id erat pharetra risus fermentum aliquam. Maecenas eu nisi posuere, rutrum orci et, imperdiet elit. Nulla tempor imperdiet sagittis. Aenean cursus justo ac enim lacinia vehicula. Etiam dictum
suscipit nibh, at iaculis velit lobortis vel. Duis pretium diam ut lectus mollis vehicula.</div>
<div class="post-action"><input type="button" value="Like" id="like_94" class="like"><span class="likesTotal" id="likes_94">0</span>
</div>
</div>
<div class="showMore"><a>Show more</a></div>
Accordion Effects
Using accordion effect we can use .animate and .css
To do the accordion effects we can use .animate and .css for height to show more or less of the story. We will use .siblings
Working Fiddle: https://jsfiddle.net/usmanmunir/ovgah34z/
$(document).ready(function() {
$(".content").on("click", '.showMore', function() {
var $this = $(this);
var content = $this.prev()
var linkText = $this.text().toUpperCase();
if (linkText === "SHOW MORE") {
linkText = "Show less";
$this.siblings('div').css('height', 'auto');
var currHeight = $this.siblings('div').height();
$this.siblings('div').css('height', '2em');
$this.siblings('div').animate({
height: currHeight
}, 500);
} else {
$this.siblings('div').animate({
height: '2em'
}, 500);
linkText = "Show more";
}
$this.text(linkText);
});
});
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent {
line-height: 1em;
height: auto;
}
.showMore {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="hideContent">
<div class="post-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id erat pharetra risus fermentum aliquam. Maecenas eu nisi posuere, rutrum orci et, imperdiet elit. Nulla tempor imperdiet sagittis. Aenean cursus justo ac enim lacinia vehicula. Etiam dictum
suscipit nibh, at iaculis velit lobortis vel. Duis pretium diam ut lectus mollis vehicula.</div>
<div class="post-action"><input type="button" value="Like" id="like_94" class="like"><span class="likesTotal" id="likes_94">0</span>
</div>
</div>
<div class="showMore"><a>Show more</a></div>
</div>
Let me know.
Here is an example of toggle inside a custom function .
If this is the result that you want .
Do not forget to mark my answer as the right answer!
Regards
function makeTheMagic(){
$("#extraContent").toggle();
let btnText= $("#btnAction").text() == "Show More!"?"Show Less!":"Show More!";
$("#btnAction").text(btnText);
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='card'>
<div class='card-body'>
<p class='alert-success'>
In my situation I want to show the first 2 sentences and then show the rest of the text with a toggle, but I couldn't find any examples of this. Did you have any examples of this? Thank you.
</p>
<p class='alert-danger' style='display:none' id='extraContent'>
I have a number of user stories on my website page. I don't want to show the entirety of each story if the user doesn't want to read it, so I show the first 2 lines and there is a Show more link to press to see the whole story. The user can then press the link again to See less. The issue comes when the user clicks the Show less link, the story condenses and shows 2 lines, but there is a momentary flicker of say 2 additional lines (can't quite make it out as its there for a few milliseconds). And it is this that I don't want.
</p>
<span class='btn btn-outline-success' onclick='makeTheMagic()' id='btnAction'>Show More!</span>
</div>
</div>
I am having troubles rendering a bordered area on top of the cover image on my web page. The contents of the bordered area display above the image but the border and background does not show up.
The borders are supposed to look like this:
I want the same experience for the cover photo so it covers half of the photo but also has the solid background.
Here is some of the relevant code below. If someone could give me some guidance as to how to properly layer these on top of each other that would be fantastic.
CompanyProfile.js:
class CompanyProfile extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<CoverPhoto/>
<div className="container-fluid page">
<ProfileHeader/>
ProfileHeader.js:
const ProfileHeader = (props) => {
return (
<div className="row border rounded-top p-2 bg-white" style={{marginTop: '5px'}}>
<div className="col-lg-2">
<img className="rounded-circle text-center" id="companyProfile" src={github}/>
<h5 className="mt-2" id="nameLabel">Github</h5>
</div>
<div className="col-lg-2">
<h6 className="mt-2" style={{marginBottom: '0px'}}><strong>Website</strong></h6>
<a className="" href="http://github.com" target="_blank">http://github.com</a>
<h6 className="mt-2" style={{marginBottom: '0px'}}><strong>Company Size</strong></h6>
<span className="">800 employees</span>
<h6 className="mt-2" style={{marginBottom: '0px'}}><strong>Year Founded</strong></h6>
<span className="">2008</span>
</div>
<div className="col-lg-8">
<h6 className="ml-3 mt-2" style={{marginBottom: '0px'}}><strong>About</strong></h6>
<p className="ml-3" style={{wordWrap: 'break-word'}}>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim dolor, bibendum non eros ut, aliquet tristique eros. Suspendisse potenti. Cras lobortis condimentum magna, ut vehicula turpis dapibus sit amet. Pellentesque hendrerit ultricies massa, a mattis purus rhoncus mollis. Mauris egestas leo id mauris euismod maximus. Proin feugiat tincidunt laoreet.</p>
</div>
</div>
)
}
CoverPhoto.js:
import React from 'react';
import coverPhoto from './images/coverphoto.jpg';
const CoverPhoto = () => {
return <img src={coverPhoto} style={{width: '100%', maxHeight: '400px'}}/>
}
export default CoverPhoto;
It might be an issue with z-index.
Try adding style={{ z-index: 9999 }} to the element that you want on top of the other. And see if that works.
if you add bootstrap cdn to you project just add clearfix class before this div
<div className="clearfix"/>
<div className="container-fluid page">
https://getbootstrap.com/docs/4.3/utilities/clearfix/
I want to target elements which have a visible scrollbar using only CSS. Is this possible without javascript?
For example, If I have 3 divs styled with overflow-y:auto, How do I change the styles for them only when their scrollbar has appeared?
CSS does not cover this selection. You need to use JavaScript.
With pure CSS I doubt it but it doesn't require a lot of javascript code either, look at this example:
document.querySelectorAll('*').forEach(el => {
if (el.offsetHeight > document.documentElement.offsetHeight) {
console.log('I am higher than my father: ', el);
el.classList.add('higher-class');
}
});
.higher-class {
color: red;
}
<div class="container" style="height:50px;">
<div class="some-child" style="height:100px;font-size: 5rem">
Higher element
</div>
</div>
check
offsetHeight property:
https://developer.mozilla.org/es/docs/Web/API/HTMLElement/offsetHeight
And the classList property:
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
It's not possible without javascript
However it only requires a single line of JS to toggle a CSS class on when the scrollbar is visible:
el.classList.toggle("scrollbarOn", el.scrollHeight > el.clientHeight)
Here's a demo:
//toggles a class on an element when the scrollbar is visible:
function updScrollClass(el) {
return el.classList.toggle("scrollbarOn", el.scrollHeight > el.clientHeight)
}
//changes the height of myDiv every second:
setInterval(function(){
var myDiv = document.getElementById('myDiv')
myDiv.classList.toggle('tall')
updScrollClass(myDiv)
},1000)
#myDiv{
width:150px;
height:200px;
overflow:auto;
}
#myDiv.tall{
height:300px;
}
.scrollbarOn{
background:yellow;
}
<div id='myDiv' class='tall'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis nisl in accumsan porta. Etiam in urna orci. Vestibulum elementum, velit ac vestibulum efficitur, est elit auctor massa, nec porta ante nunc eget tellus. Integer eu ligula felis.
</div>
I am using firefox 33.0 in Ubuntu 14.04. I have a website(localhost) with bootstrap 3 carousel. I have applied "animated pulse" (animate.min.css) class to my "img" in the "class=item" div and "animated fadeinleft" to my carousel-caption.
<div class="item">
<img src="images/2.jpg" class="img-responsive animated pulse">
<div class="container">
<div class="carousel-caption">
<h1 class="animated fadeinleft">Another example headline.</h1>
<p class="animated fadeinright">Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
</div>
</div>
</div>
There are 3 slides in total. For the first appearance of each slide, the image and carousel caption comes with the effect (animate.min.css). But after that the slides just comes and goes without any effect. This happens only in firefox. In Chrome 38.0.2125.104 it works as expected. Somebody please suggest a way to fix the issue.
If you look at the example on their site the classes are applied and if you want to trigger again you need to remove and add classes again. That is how CSS3 animation is restarted or triggered again by removing and adding classes again. You can read more about this here. In your case the classes are not removed and added again.
For Bootstrap you can use the slide.bs.carousel where you can add the classes again. I have added a data attribute [data-animation] to the elements for the respective animation.
<div class="active item">
<img src="http://lorempixel.com/1024/750" alt="Slide1" class="img-responsive animated pulse" data-animation="pulse" />
<div class="container">
<div class="carousel-caption">
<h1 class="animated fadeInLeft" data-animation="fadeInLeft">Another example headline.</h1>
<p class="animated fadeInRight" data-animation="fadeInRight">Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
</div>
</div>
</div>
JS code
function animateElement(obj, anim_) {
obj.addClass(anim_ + ' animated').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
$(this).removeClass();
});
}
$('#myCarousel').on('slide.bs.carousel', function (e) {
var current = $('.item').eq(parseInt($(e.relatedTarget).index()));
$('[data-animation]').removeClass();
$('[data-animation]', current).each(function () {
var $this = $(this);
var anim_ = $this.data('animation');
animateElement($this, anim_);
});
});
Fiddle Demo