How Do I Create A Button That Toggles States? - javascript

I want to create a button, that when clicked, changes its name and function. The button is called 'Expand', and when clicked it allows a div to expand. Once clicked, I want it to change its functionality and text to 'shrink', where it then shrinks a div.
let expandButton = document.createElement(`button`);
expandButton.setAttribute(`class`, `listButton`);
expandButton.textContent = `+`
if (expandButton.className == `listButton`) {
expandButton.addEventListener(`click`, (e) => {
expandButton.setAttribute(`class`, `listButtonClicked`);
})
}
if (expandButton.className == `listButtonClicked`) {
console.log(`active`);
expandButton.addEventListener(`click`, (e) => {
expandButton.setAttribute(`class`, `listButton`);
})
}
When the button is clicked, it only expands. Upon being clicked again, it doesn't do anything; the console.log line in the second area doesn't even register.

Yesterday, I wrote a very similar answer here. I've updated my code to include a "show less" button:
for (const el of document.getElementsByClassName('shorten')) {
const text = el.textContent;
const summary = text.substring(0, 70) + '... ';
el.textContent = summary;
const showmore = document.createElement('span');
showmore.textContent = 'Show more';
showmore.style.fontWeight = 'bold';
const showless = document.createElement('span');
showless.textContent = 'Show less';
showless.style.fontWeight = 'bold';
showmore.addEventListener('click', () => {
el.textContent = text;
el.append(showless);
});
showless.addEventListener('click', () => {
el.innerHTML = "";
el.textContent = summary;
el.append(showmore);
});
el.append(showmore);
}
/* just for demostration purposes. not actually needed */
.box {
width: 200px;
height: 100px;
background-color: lightgray;
overflow: auto;
margin: 10px;
display: inline-block;
}
<div class="box shorten">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ac elementum nunc. Cras vehicula, ante nec iaculis semper, mi justo ornare ipsum, ac sollicitudin tortor tellus at magna. In augue.
</div>
<div class="box shorten">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ac elementum nunc. Cras vehicula, ante nec iaculis semper, mi justo ornare ipsum, ac sollicitudin tortor tellus at magna. In augue.
</div>
<div class="shorten">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ac elementum nunc. Cras vehicula, ante nec iaculis semper, mi justo ornare ipsum, ac sollicitudin tortor tellus at magna. In augue.
</div>
It should also be noted that there is a <summary> tag that does something similar. However this will not work in your case because you want to dynamically shorten the page.

Related

Append a link when text overflowing parent

I'm using Ajax to get comments. Comment text is treated as max-height:90px by default. When importing comments, I want to attach a link if the text length is longer than the parent element.
The code below doesn't work well.
It works imperfectly.
All comments have a link or only the first one.
Is there any right way?
$( document ).on('click' , '.view_comments' , function(){
let id = $(this).attr("id");
let content = $("#comment-post-"+id).val();
let last_cmt = $("ul#canvas-comments-"+id+" li:last").val();
$.ajax({
type:"GET",
url: "http://192.168.10.21/v1/server1/comment/view_comment.php",
data:{ enclosure: content, cmt: last_cmt },
success:function(html){
const result = JSON.parse(html);
if( result.length > 0 ){
let comment = '';
for( const item of result ){
const comment_list = comment_object( item );
comment += comment_list.get_html();
}
$("ul#canvas-comments-"+id).append(comment);
/************************************************
* # if comment overflown div.wts-comment-text *
************************************************/
const hasElement = $('*').is($(".wts-comment-text"));
if( hasElement === true ){
const parent = document.querySelector('.wts-comment-text');
if( isOverflown( parent ) ){
const sub_id = $(parent).attr("data-value");
$("#comment-option"+sub_id).html("<a href='#' data-value='"+sub_id+"' class='view-comment-details'><span>More...<span></a>");
}
}
$(this).html('More Comments');
}else if( result.length === 0 ){
console.log("zero");
$(this).html('Comments 0');
}
},
error: function( xhr ){
console.log(xhr.status+' '+xhr.statusText);
}
});
return false;
});
function isOverflown(e){
return e.scrollHeight > e.clientHeight;
}
var comment_object = function(data){
const id = data['comment_id'];
const user_id = data['user_id'];
const username = data['username'];
const date = data['date'];
const comment = data['comment'];
return {
get_html: function(){
return "<li value='"+id+"' class='wts-comment'><div class='wts-comment-left'><span class='wts-comment-author'>"+username+"</span><span class='wts-comment-date'>"+date+"</span></div><div class='wts-comment-text-wrapper'><input type='hidden' name='comment_id' value='"+id+"' /><div class='wts-comment-wrapper'><div class='wts-comment-rating-container'><div class='wts-rating-inner-wrapper'><div class='wts-comment-rating'><div class='wts-comment-rating-value'></div></div></div><div id='commentTextBox"+id+"' class='wts-comment-text'><p>"+comment+"</p></div><div class='wts-comment-action-icons'><div id='comment-option"+id+"' class='wts-comment-action-renderer'><a href='#' data-value='"+id+"' data-action='n-ack' class='cwt-link-cr view-comment-details'><span class='n-ack'>펼쳐보기<span></a></div></div></div></li>";
}
};
};
Based on this SO answer. You can check if the text is bigger than your container and append more link to your HTML.
$(document).ready(function() {
$('.comments .text').each(function() {
if ($(this)[0].scrollHeight > $(this).innerHeight()) {
$(this).parent().append('more...');
}
});
$('.comments').on('click', '.more', function(e) {
e.preventDefault();
$(this).parent().find('.text').css('height', 'auto');
$(this).css('display', 'none');
});
});
.comments {
width: 500px;
line-height: 30px;
border: solid 1px #ccc;
font-size: 20px;
margin-bottom: 35px;
}
.text {
height: 90px;
overflow-y: hidden;
}
.more {
height: 30px;
text-decoration: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- First Comment -->
<div class="comments">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ullamcorper eleifend felis. Sed scelerisque tincidunt rutrum. Praesent efficitur nunc a mi vulputate, et lacinia leo mattis. Suspendisse nec dolor porttitor, egestas nisi et, egestas tellus.
</div>
</div>
<!-- Second Comment -->
<div class="comments">
<div class="text">
Lorem ipsum dolor sit amet.
</div>
</div>
<!-- Third Comment -->
<div class="comments">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ullamcorper eleifend felis. Sed scelerisque tincidunt rutrum. Praesent efficitur nunc a mi vulputate, et lacinia leo mattis. Suspendisse nec dolor porttitor, egestas nisi et, egestas tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ullamcorper eleifend felis. Sed scelerisque tincidunt rutrum. Praesent efficitur nunc a mi vulputate, et lacinia leo mattis. Suspendisse nec dolor porttitor, egestas nisi et, egestas tellus.
</div>
</div>
<!-- Fourth Comment -->
<div class="comments">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ullamcorper eleifend felis.
</div>
</div>

how to make a auto-scrolling horizontal scrollbar

I have a horizontal scrollable section in my page and i want its content to automatically scroll. i tried using the code for automatic vertical scroll but its not working.
code based from here how to make a scrollbar automatically move after sometime (JavaScript)
$(document).ready(function () {
var scrollHandler = null;
function autoScroll() {
clearInterval(scrollHandler);
scrollHandler = setInterval(function () {
var nextScroll = $('.menu').scrollLeft() + 20;
$('.menu').scrollLeft(nextScroll);
}, 1500);
}
autoScroll();
});
what do i need to do to make it work? i am a beginner so please explain. thanks.
Here you can see adapted code from the answer your code is based on.
$(document).ready(function() {
var scrollHandler = null;
function autoScroll () {
console.log("autoScroll");
clearInterval(scrollHandler);
scrollHandler = setInterval(function() {
var nextScroll = $('.scrolled').scrollLeft() + 20;
$('.scrolled').scrollLeft(nextScroll);
},500);
}
autoScroll();
});
.scrolled {
width: 50%;
height: auto;
overflow: scroll;
}
.inside {
width: 5000%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="scrolled">
<div class="inside" >
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur vitae diam non enim vestibulum interdum. Mauris dolor felis, sagittis at, luctus sed, aliquam non, tellus. Aliquam erat volutpat. Fusce consectetuer risus a nunc. Aliquam ornare wisi eu metus. Mauris tincidunt sem sed arcu. Fusce dui leo, imperdiet in, aliquam sit amet, feugiat eu, orci. Duis bibendum, lectus ut viverra rhoncus, dolor nunc faucibus libero, eget facilisis enim ipsum id lacus. Fusce dui leo, imperdiet in, aliquam sit amet, feugiat eu, orci.
</div>
</div>

Show more/less text with responsive behaviour [duplicate]

This question already has answers here:
Toggle Read More/Read Less using Javascript?
(4 answers)
Closed 1 year ago.
I am referring this solution. The Change I want is Read More button should come at the end of the line as shown in pic
on load it should be only two lines with show more button in second line at the end
on show more it should expand and show entire text
on show less it should shrink back to two lines with button at the end of the line
function myFunction() {
let text = document.getElementById('overflow_text')
let toggle = document.getElementById('toggle_text')
if (text.style.overflow == 'visible') {
toggle.innerHTML = '..more'
text.style.overflow = 'hidden'
text.style.textOverflow = 'ellipsis'
text.style.whiteSpace = 'nowrap'
} else {
toggle.innerHTML = 'less'
text.style.overflow = 'visible'
text.style.textOverflow = 'string'
text.style.whiteSpace = 'normal'
}
}
.myClass {
height: 150px;
width : 500px;
}
#overflow_text {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
#toggle_text {
cursor: pointer;
}
.button_span{
border: black;
border-width: 1px;
border-color: black;
border-style: solid;
}
<div class="container">
<div class="row">
<div class="col-md-6 myClass">
<p id='overflow_text'>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus imperdiet, nulla et dictum interdum, nisi lorem egestas vitae scelerisque enim ligula venenatis dolor. Maecenas nisl est, ultrices nec congue eget, auctor vitae massa. Fusce luctus
vestibulum augue ut aliquet. Nunc sagittis dictum nisi, sed ullamcorper ipsum dignissim ac. In at libero sed nunc venenatis imperdiet sed ornare turpis. Donec vitae dui eget tellus gravida venenatis. Integer fringilla congue eros non fermentum.
Sed dapibus pulvinar nibh tempor porta.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus imperdiet, nulla et dictum interdum, nisi lorem egestas vitae scelerisque enim ligula venenatis dolor. Maecenas nisl est, ultrices nec congue
eget, auctor vitae massa. Fusce luctus vestibulum augue ut aliquet. Nunc sagittis dictum nisi, sed ullamcorper ipsum dignissim ac. In at libero sed nunc venenatis imperdiet sed ornare turpis. Donec vitae dui eget tellus gravida venenatis. Integer
fringilla congue eros non fermentum. Sed dapibus pulvinar nibh tempor porta.</p>
<span onClick="myFunction()" id="toggle_text" class="button_span">more</span>
</div>
</div>
</div>
I suggest including the "..." in the button, because the text does not "know" when it has run out of space.
CSS:
#mainContent{
position:relative;
line-height:1em;
overflow:hidden;
}
.showContent{
height: 2em;
}
.hideContent{
height: auto;
}
#moreButton{
position:absolute;
bottom:0;
right:0;
cursor:pointer;
background:white;
padding-left:4px;
}
HTML:
<div class="showContent" id="mainContent">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s
<span id="moreButton" onclick="showMoreLess()">...more</span>
</div>
...and finally JS:
function showMoreLess(){
var mc = document.getElementById('mainContent');
var btn = document.getElementById('moreButton');
if (btn.innerHTML == '...more') {
mc.className = 'hideContent';
btn.innerHTML = '...less';
} else {
mc.className = 'showContent';
btn.innerHTML = '...more';
}
}
Please let me know if this helps!

Change div on each click using vanilla js

I have 2 divs div1 and div2. My goal is to make them change on each button click
<div>
<button onclick="changeText();" id="changeText" data-text="Enjoy!">Hello!</button>
<div id="div1" style="display:block">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ipsum leo,
scelerisque at dapibus ac, consectetur vel ipsum.
</div>
<div id="div2" style="display:none">Cras suscipit ullamcorper elit vitae sodales. Sed euismod felis molestie lorem
gravida a venenatis risus sollicitudin. Proin accumsan lorem in est adipiscing faucibus.
</div>
</div>
My js-code that right now works but i can see that it is completely wrong written.
var button = document.getElementById("changeText");
button.addEventListener(
"click",
function () {
if (document.getElementById("div1").style.display == "block") {
document.getElementById("div1").style.display = "none";
document.getElementById("div2").style.display = "block";
} else {
document.getElementById("div2").style.display = "none";
document.getElementById("div1").style.display = "block"
}
},
false
);
What can I do to make this code look and work better?
It will at least look a little better if you create variables of the two divs;
const div1 = document.getElementById("div1");
const div2 = document.getElementById("div2");
If I understand your question correctly, you can achieve this by toggling between style.display: none and style.display: block on your elements with each click of the button. For example, something like:
function toggleDisplay(el) {
el.style.display = el.style.display === 'none' ? 'block' : 'none';
}
const divEl1 = document.querySelector('#div1');
const divEl2 = document.querySelector('#div2');
document.querySelector('div').addEventListener('click', event => {
if (event.target.tagName === 'BUTTON') {
toggleDisplay(divEl1);
toggleDisplay(divEl2);
}
});
<div>
<button id="changeText" data-text="Enjoy!">Hello!</button>
<div id="div1" style="display:block">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ipsum leo, scelerisque at dapibus ac, consectetur vel ipsum.
</div>
<div id="div2" style="display:none">Cras suscipit ullamcorper elit vitae sodales. Sed euismod felis molestie lorem gravida a venenatis risus sollicitudin. Proin accumsan lorem in est adipiscing faucibus.
</div>
</div>
My suggestion:
var divs = document.querySelectorAll('.text');
changeText.onclick = () => divs.forEach(div => div.classList.toggle('hidden'));
.hidden {
display: none;
}
<div>
<button id="changeText" data-text="Enjoy!">Hello!</button>
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ipsum leo, scelerisque at dapibus ac, consectetur vel ipsum.
</div>
<div class="text hidden">
Cras suscipit ullamcorper elit vitae sodales. Sed euismod felis molestie lorem gravida a venenatis risus sollicitudin. Proin accumsan lorem in est adipiscing faucibus.
</div>
</div>
Alternatively:
div_2.style.display = "none";
changeText.onclick = () => {
div_2.style.display == "none" ? (div_1.style.display = "none", div_2.style.display = "block") : (div_1.style.display = "block", div_2.style.display = "none")
};
<div>
<button id="changeText" data-text="Enjoy!">Hello!</button>
<div id="div_1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ipsum leo, scelerisque at dapibus ac, consectetur vel ipsum.
</div>
<div id="div_2">
Cras suscipit ullamcorper elit vitae sodales. Sed euismod felis molestie lorem gravida a venenatis risus sollicitudin. Proin accumsan lorem in est adipiscing faucibus.
</div>
</div>
Create a CSS class that hides content, and toggle that class:
let divs = document.querySelectorAll(".text");
document.getElementById("changeText").addEventListener("click", () => {
for (let div of divs) div.classList.toggle("hidden");
});
.hidden { display: none }
<div>
<button id="changeText">Hello!</button>
<div class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ipsum leo,
scelerisque at dapibus ac, consectetur vel ipsum.
</div>
<div class="text hidden">Cras suscipit ullamcorper elit vitae sodales. Sed euismod felis molestie lorem
gravida a venenatis risus sollicitudin. Proin accumsan lorem in est adipiscing faucibus.
</div>
</div>
Some comments on your code:
It defines two click handlers: one with addEventListener, but another one with the HTML attribute onclick. The latter references a function you did not provide.
data-text="Enjoy!" is not used
id="div1": don't create a sort of enumerated id attributes. This is almost always a wrong choice. Instead give such a group of elements a common CSS class, and then use a DOM method to get all of them in a node list.
I recommend saving the elements in variables and using classes to hide the element using the classList.toggle () method.
CSS
.hidden{display:none;}
HTML
<div>
<button onclick="changeText();" id="changeText" data-text="Enjoy!">Hello!</button>
<div id="div1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ipsum leo, scelerisque at dapibus ac, consectetur vel ipsum.
</div>
<div id="div2" class="hidden">
Cras suscipit ullamcorper elit vitae sodales. Sed euismod felis molestie lorem gravida a venenatis risus sollicitudin. Proin accumsan lorem in est adipiscing faucibus.
</div>
</div>
JS
var button = document.getElementById("changeText");
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
button.addEventListener("click",function () {
div1.classList.toggle('hidden');
div2.classList.toggle('hidden');
});

jQuery change css on a specified element

I need something that will change the style of a div when you scroll to a specific element
Example:
In my header i have the texts:
1) Home
2) Text2
3) Text3
4) Text4
When on top i want the "Home" to be white and all the others blue
When on paragraph 1 i want the "Text2" white and all the other blue
When on paragraph 2 i want the "Text3" white and all the other blue
When on paragraph 3 i want the "Text4" white and all the other blue
When below "Text4" i want the "Home" to be white and all the others blue
PS: "Text2","Text3" and "Text4" will have nothing else in betwheen
I'd go with waypoints or with skrollr. There are plenty of tutorials about skrollr so dont worry.
You can do something like this
Use scroll() to listen scroll event
Get the scroll top value by using scrollTop()
DEMO :
$(window).scroll(function() {
$('#div2').css('color', $(this).scrollTop() > 390 ? 'red' : 'blue');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id=main style="height:1000px">
<div id=div2 style="margin-top:500px">element</div>
</div>
This toggles the color of any header text at the point a matching element comes into view (or leaves) :
Demo
$(function() {
var gate = $(window),
bar = $('header'),
title = bar.find('span'),
element = $('.element'),
viewin, viewout;
gate.on('load resize', function() {
viewin = []; viewout = [];
element.each(function() {
var placement = $(this).offset().top-gate.height(),
dimension = $(this).outerHeight();
viewin.push(placement);
viewout.push(placement+dimension);
});
})
.scroll(function() {
var location = gate.scrollTop();
element.each(function(i) {
var option = title.eq(i), white = option.hasClass('white');
if (location > viewin[i] && location <= viewout[i]) {
if (!white) option.addClass('white');
}
else if (white) option.removeClass('white');
});
});
});
Comments below are no longer very relevant because they are discussing an earlier stage.
Animating colors does not work unless you include a library for animating colors.
jQuery does not animate colors by default.
So for color-animation you must include library like JQuery UI, but it is large for just using color-animation.
Instead i would suggest you to use Bitstorm:ColorLibrary, it's just 2.7kb in size.
JSFiddle : DEMO
$(document).ready(function(){
var top = document.getElementById("css_text").scrollHeight; // top position of '#css_text'
alert("Top position of #CSS_TEXT : " + top);
var calcu = top - 20;
$(window).scroll( function(){
var pos = $(window).scrollTop();
if(pos >= calcu)
{
$("#css_text").animate({"color":"red","opacity":"1"},2000);
}
});
});
#css_text
{
opacity:0;
color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://www.bitstorm.org/jquery/color-animation/jquery.animate-colors-min.js"></script>
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
<pre id="css_text"><code>
#header h1 a {
display: block;
width: 300px;
height: 80px;
}
</code></pre>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
<li>Vestibulum auctor dapibus neque.</li>
</ul>
Check the following jquery functions
scroll
scrollTop
offset
each
attr
Your code could look something like that:
( function( $ ) {
$(window).scroll(function(e){
var home = $('#home');
var switchPosition = $(window).scrollTop() + parseInt(home.css("top"))+30;
$('.text').each(function(){
if ( switchPosition > $(this).offset().top &&
$(this).attr('data-color') !== home.attr('data-color') ) {
home.css({color: $(this).attr('data-color')});
home.attr('data-color', $(this).attr('data-color') );
}
});
});
} )( jQuery );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="home" style="font-weight: bold; color: blue; position: fixed; top: 20px; left: 20px;">HOME</div>
<div style="color: white; position: fixed; top: 170px; left: 20px;">scroll down...</div>
<div class="text" data-color="blue" style="background: #999; height: 500px"> </div>
<div class="text" data-color="red" style="background: #666; height: 500px"> </div>
<div class="text" data-color="white" style="background: #333; height: 1000px"> </div>

Categories

Resources