What is the easiest way to trigger a background-color change through a keydown event? At the moment I have it where when you press a key it makes a sound but I want to have it change the background color to something every time I push a key.
Here is my JS:-
function play(id){
var audio = document.getElementById(id);
audio.play();
}
function removeTransition(e) {
if (e.propertyName !== 'transform') return;
e.target.classList.remove('playing');
}
function playSound(e) {
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
if (!audio) return;
key.classList.add('playing');
audio.currentTime = 0;
audio.play();
}
const keys = Array.from(document.querySelectorAll('.key'));
keys.forEach(key => key.addEventListener('transitionend', removeTransition));
window.addEventListener('keydown', playSound);
Thank You!
HTML:
<div id="box"></div>
CSS:
#box {
height: 200px;
width: 200px;
background-color:red;
}
JS:
document.addEventListener("keydown", changeBg);
function changeBg() {
document.getElementById("box").style.backgroundColor = "green";
}
Related
At the moment i am using hardcoded height point to trigger visible ScrollToTop Button.
i would love to get solution to be triggered when passing viewport height.
const { scrollDirection } = useScrollDirection()
const { scrollPosition } = useScrollPosition()
const [isVisible, setIsVisible] = useState(false)
const toggleVisible = () => {
if (scrollPosition === 0) {
setIsVisible(false)
}
**if (scrollPosition > 800) {
setIsVisible(true)
} else if (scrollPosition <= 799) {
setIsVisible(false)
}**
}
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
})
}
window.addEventListener("scroll", toggleVisible)
you can use window.innerHeight
const toggleVisible = () => {
const viewportHeight = window.innerHeight;
if (scrollPosition === 0) {
setIsVisible(false)
}
**if (scrollPosition > viewportHeight) {
setIsVisible(true)
} else if (scrollPosition <= viewportHeight) {
setIsVisible(false)
}**
}
You can do this by using Intersection Observer (IO)
First you create an element that is just below the viewport initially. And whenever this element comes into view, show the button.
This requires one dummy element which you observe, for the demo I set the html element to position: relative for it to work. Maybe you can use a different element structure, based on your html. Important thing is that you have one element you can observe and trigger the element depending on when it comes into view.
let options = {
rootMargin: '0px',
threshold: 0.1 // when at least 10% of the element is visible we show the button
}
const callback = (entries, observer) => {
const btn = document.querySelector('#scroll-top');
entries.forEach(entry => {
if (entry.intersectionRatio > 0.1) {
// if we are past our 0.1 threshold we show the button
btn.classList.add('visible')
} else {
// otherwise we hide the button
btn.classList.remove('visible')
}
});
};
const observer = new IntersectionObserver(callback, options);
const target = document.querySelector('#button-trigger');
observer.observe(target);
.dummy-viewport {
min-height: 400vh;
}
html {
position: relative;
}
#button-trigger {
position: absolute;
top: 100vh;
left: 10px;
height: calc(100% - 100vh);
/* for demo purposes, don't show the element on the finished site*/
width: 2rem;
outline: 1px solid rebeccapurple;
writing-mode: vertical-rl;
text-orientation: mixed;
}
p {
padding: 0;
margin: 0;
}
#scroll-top {
position: fixed;
bottom: 40px;
right: 10px;
opacity: 0;
transition: .5s opacity;
}
#scroll-top.visible {
opacity: 1
}
<div class="dummy-viewport">
<p> Scroll down ↓ </p>
<button id="scroll-top" type="button"> Scroll to top </button>
</div>
<div id="button-trigger">
<p> When I am visible, I show the button </p>
</div>
I want to double the height of the div every time it is clicked.
I am thinking to apply a additional CSS class to a div when ever I click a button. The CSS concept will be like:
#divToBeDoubled {
height: 100px;
&.doubleHeight{
height: selfHeight*2
}
}
How can I achieve this by using Reactjs and SCSS?
I think if you want to change a css value with the component state, you need to move the property you want to change in you component or use JSS...
to move the property in the render, you can do this :
class MyComponent extends React.Component{
state = {
divHeight : 100
}
doubleSize = ()=>{
this.setState({ divHeight : this.state.divHeight * 2 })
}
render() {
const style = {
height: this.state.divHeight
};
return (
<div style={style} onClick={this.doubleSize}>Content</div>
);
}
}
If using sass. You can use this, and toggle class in JSX onclick event.
$height: 100px;
.normal {
height: $height;
}
.double {
height: $height * 2;
}
I'm not sure if "sticky" is the term for this, but is there a way to make the scrollbar from overflow:auto stay visible?
I have a rather large table that I want to be scrollable horizontally; however, the table is fairly tall as well, so when the page loads the horizontal scrollbar is not within the viewport of the browser, so it's rather hard to tell that the table is scrollable at all.
<div style = 'width:900px;overflow:auto'>
<table>
<!-- Very large table here -->
</table>
</div>
The scroll bar appears below the table, but unfortunately the table is so tall you can't see it unless you scroll down.
I'd like to have the horizontal scrollbar stay visible even if the table goes off the screen, maybe fixed to the bottom of the viewport. Ideally I'd like to do it using only CSS or a minimal amount of javascript.
Here is a script for that http://jsfiddle.net/TBnqw/2288/
$(function($){
var scrollbar = $('<div id="fixed-scrollbar"><div></div></div>').appendTo($(document.body));
scrollbar.hide().css({
overflowX:'auto',
position:'fixed',
width:'100%',
bottom:0
});
var fakecontent = scrollbar.find('div');
function top(e) {
return e.offset().top;
}
function bottom(e) {
return e.offset().top + e.height();
}
var active = $([]);
function find_active() {
scrollbar.show();
var active = $([]);
$('.fixed-scrollbar').each(function() {
if (top($(this)) < top(scrollbar) && bottom($(this)) > bottom(scrollbar)) {
fakecontent.width($(this).get(0).scrollWidth);
fakecontent.height(1);
active = $(this);
}
});
fit(active);
return active;
}
function fit(active) {
if (!active.length) return scrollbar.hide();
scrollbar.css({left: active.offset().left, width:active.width()});
fakecontent.width($(this).get(0).scrollWidth);
fakecontent.height(1);
delete lastScroll;
}
function onscroll(){
var oldactive = active;
active = find_active();
if (oldactive.not(active).length) {
oldactive.unbind('scroll', update);
}
if (active.not(oldactive).length) {
active.scroll(update);
}
update();
}
var lastScroll;
function scroll() {
if (!active.length) return;
if (scrollbar.scrollLeft() === lastScroll) return;
lastScroll = scrollbar.scrollLeft();
active.scrollLeft(lastScroll);
}
function update() {
if (!active.length) return;
if (active.scrollLeft() === lastScroll) return;
lastScroll = active.scrollLeft();
scrollbar.scrollLeft(lastScroll);
}
scrollbar.scroll(scroll);
onscroll();
$(window).scroll(onscroll);
$(window).resize(onscroll);
});
It is a quick test rather than a complete generic plugin, but is a good start, I think
Here's my take, #user2451227's is almost perfect, but didn't work with nested overflowed elements and had a number of performance issues, so I rewrote it:
$(function($){
var fixedBarTemplate = '<div class="fixed-scrollbar"><div></div></div>';
var fixedBarCSS = { display: 'none', overflowX: 'scroll', position: 'fixed', width: '100%', bottom: 0 };
$('.fixed-scrollbar-container').each(function() {
var $container = $(this);
var $bar = $(fixedBarTemplate).appendTo($container).css(fixedBarCSS);
$bar.scroll(function() {
$container.scrollLeft($bar.scrollLeft());
});
$bar.data("status", "off");
});
var fixSize = function() {
$('.fixed-scrollbar').each(function() {
var $bar = $(this);
var $container = $bar.parent();
$bar.children('div').height(1).width($container[0].scrollWidth);
$bar.width($container.width()).scrollLeft($container.scrollLeft());
});
$(window).trigger("scroll.fixedbar");
};
$(window).on("load.fixedbar resize.fixedbar", function() {
fixSize();
});
var scrollTimeout = null;
$(window).on("scroll.fixedbar", function() {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function() {
$('.fixed-scrollbar-container').each(function() {
var $container = $(this);
var $bar = $container.children('.fixed-scrollbar');
if($bar.length && ($container[0].scrollWidth > $container.width())) {
var containerOffset = {top: $container.offset().top, bottom: $container.offset().top + $container.height() };
var windowOffset = {top: $(window).scrollTop(), bottom: $(window).scrollTop() + $(window).height() };
if((containerOffset.top > windowOffset.bottom) || (windowOffset.bottom > containerOffset.bottom)) {
if($bar.data("status") == "on") {
$bar.hide().data("status", "off");
}
} else {
if($bar.data("status") == "off") {
$bar.show().data("status", "on");
$bar.scrollLeft($container.scrollLeft());
}
}
} else {
if($bar.data("status") == "on") {
$bar.hide().data("status", "off");
}
}
});
}, 50);
});
$(window).trigger("scroll.fixedbar");
});
Usage: Add the class fixed-scrollbar-container to your horizontally overflowed element, then include this code. If the container is updated or changes in size, run $(window).trigger("resize.fixedbar"); to update the bar.
Demo: http://jsfiddle.net/8zoks7wz/1/
#Mahn - I made a small update to the following function:
$('.fixed-scrollbar-container').each(function() {
var container = jQuery(this);
if (container[0].offsetWidth < container[0].scrollWidth) {
var bar = jQuery(fixedBarTemplate).appendTo(container).css(fixedBarCSS);
bar.scroll(function() {
container.scrollLeft(bar.scrollLeft());
});
bar.data("status", "off");
}
});
The if statement looks if the container offsetWidth is smaller than the scrollWidth. Else you will also get a fixed scrollbar if the content happens to be smaller than the container. I did not like having a disfunctional scrollbar, hence this edit.
How about restricting the height of the containing div so it stays within the body? You could then have the table scroll within that div.
Working jsfiddle here: http://jsfiddle.net/fybLK/
html, body {height: 100%; margin: 0; padding: 0;}
div {
width:500px;
max-height: 100%;
overflow:auto;
background: steelblue;}
table {
width: 1000px;
height: 1000px;
color: #fff;}
Here, I've set the html and body to 100% height so that the containing div can be sized.
I would like to highlight a div when it's clicked.
Heres the example: www.spidex.org
On this website if you hover any of the navigation buttons a div on the top of the page is highlighted.
You may use jQuery for achieving this.
get jQuery here.
now consider that you have a div that you want to highlight on mouseover called item.
do this by adding an overlay div.
div.overlay{
opacity:0;
background:#000;
width:100%;
height:100%;
position:absolute;
top:50px;left:0;
}
then use jquery
jQuery(document).ready(function($){
$('.item').mouseover(function(){
$('.overlay').css({opacity:0.3});
});
});
You can change the appearance of elements when hovered using the :hover pseudo-class.
For example
div:hover {
color: red;
}
Secondly, you can change the text color via using the color property and the background color using the background-color property.
Both are shown below:
div:hover {
color: black;
background-color: white;
}
In your given example, when you hover over the primary navigation items in the super-header, then the body dims. I agree with your analysis that this is managed with some cover div of the body.
One cross-browser approach (using jQuery in this example) you might consider would be the following:
EXAMPLE HTML:
<div class="header">
Some Link
</div>
<div class="body">
<div class="body-content">
[ CONTENT HTML ]
</div>
<div class="body-cover"></div>
</div>
EXAMPLE CSS:
.body {
position: relative; /* container needs position */
}
.body-cover {
position: absolute;
top: 0px;
left: 0px;
background-color: blue;
/*
you could use a sligtly transparent background here,
or tween your opacity in your javascript
*/
}
EXAMPLE JavaScript:
// on dom ready
jQuery(function ($) {
// closures
var $links = $('.header a');
var $body = $('.body');
var $content = $body.find('.body-content');
var $cover = $body.find('.body-cover');
var sCoverHiddenCssClassName = 'body-cover-hidden';
var sCoverTweeningCssClassName = 'body-cover-tweening';
var sCoverShowingCssClassName = 'body-cover-showing';
// closure methods
var fMouseOver = function () {
// check to see if hidden (not already tweening or showing)
if ($cover.hasClass(sCoverHiddenCssClassName)) {
// check content, may have changed.
$cover.css({
height: $content.outerHeight(),
width: $content.outerWidth()
});
// animate or tween cover (do this however you want)
$cover
.removeClass(sCoverHiddenCssClassName)
.addClass(sCoverTweeningCssClassName)
.fadeIn(function () {
// when completed, mark as showing/visible
$cover
.removeClass(sCoverTweeningCssClassName)
.addClass(sCoverShowingCssClassName);
});
}
};
var fMouseOut = function () {
// check to see if visible (not already tweening or hidden)
if ($cover.hasClass(sCoverShowingCssClassName)) {
// animate or tween cover (do this however you want)
$cover
.removeClass(sCoverShowingCssClassName)
.addClass(sCoverTweeningCssClassName)
.fadeOut(function () {
// when completed, mark as showing/visible
$cover
.removeClass(sCoverTweeningCssClassName)
.addClass(sCoverHiddenCssClassName);
});
}
};
var fClick = function (e) {
// prevent default if needed for anchors or submit buttons
// e.preventDefault();
if ($cover.hasClass(sCoverHiddenCssClassName)) {
fMouseOver();
}
else if ($cover.hasClass(sCoverShowingCssClassName)) {
fMouseOut();
}
};
// init interaction
$cover.hide().addClass(sCoverHiddenCssClassName);
$links.each(function () {
// wire links
jQuery(this)
.mouseover(fMouseOver)
.mouseout(fMouseOut);//
//.click(fClick); // use click event if desired
});
});
JQuery UI is also gives an good option to quickly highlight div .
https://jqueryui.com/effect/
$( "#divId" ).effect( "highlight", 500 );
Fiddle: http://jsfiddle.net/wczTW/1/
Basically, I have a set of elements that I'm moving up and down. Think "Cover Flow" except vertical (Yuck, I know). It works great unless you hit up or down really quick, in which case it seems that the CSS transition starts before the last one finished and they begin to get too close together. I'm not even 100% sure that's what's going on, but if you play with the fiddle above for a couple seconds you should see what I'm talking about.
Relevant CSS:
.game {
position: absolute;
width: 150px;
height: 100px;
left: 200px;
margin-left: -125px;
background-color: gray;
border: 1px solid white;
-webkit-transition: all .2s ease-in-out;
-webkit-transform: scale(1);
overflow: hidden;
z-index: 10;
}
.selected {
transform-origin: 0 0;
border: 1px solid green;
-webkit-transition: all .2s ease-in-out;
-webkit-transform: scale(1.25);
z-index: 100;
}
Relevant Javascript:
$(document).ready(function () {
keyDown = false;
lTop = ($(window).height() / 2) - 50;
$('.game').each(function () {
$(this).css('top', lTop);
lTop += 120;
});
});
$(document).keydown(function (e) {
if (!keyDown) {
if (e.keyCode == 40) { //down
var selected = $('.selected');
var next = selected.next()
if (next.length) {
selected.removeClass('selected');
next.addClass('selected');
$('.game').css('top', function (i, v) {
return (parseFloat(v) - 120) + 'px';
});
}
keyDown = true;
} else if (e.keyCode == 38) { //up
var selected = $('.selected');
var next = selected.prev()
if (next.length) {
selected.removeClass('selected');
next.addClass('selected');
$('.game').css('top', function (i, v) {
return (parseFloat(v) + 120) + 'px';
});
}
keyDown = true;
}
}
});
$(document).keyup(function (e) {
keyDown = false;
});
Is there a simple way to queue CSS transitions? Or block input until the current transition is done?
edit: I think I would much prefer just aborting the animation and moving it immediately, if possible. The two options above would be bad user experience I think.
What's happening is that the keypresses are happening before the top CSS value has updated to its new value, so the v variable is not what you're expecting. One way to fix would be to use setTimeout() to prevent keypresses until the animation is done, but the better way would be to use another way to calculate the top value. I'm putting together a fiddle for you.
FIDDLE HERE http://jsfiddle.net/wczTW/2/
Here's your new javascript:
var currentTop, lTop, keyDown;
$(document).ready(function () {
keyDown = false;
currentTop = lTop = ($(window).height() / 2) - 50;
console.log(lTop);
$('.game').each(function () {
$(this).css('top', lTop);
lTop += 120;
});
});
var index = 0;
$(document).keydown(function (e) {
var selected = $('.selected');
if (!keyDown) {
if (e.keyCode == 40) { //down
var next = selected.next()
if (next.length) {
index++;
selected.removeClass('selected');
next.addClass('selected');
$('.game').css('top', function (i, v) {
return ((i * 120) - (index * 120) + currentTop) + 'px';
});
}
keyDown = true;
} else if (e.keyCode == 38) { //up
var next = selected.prev()
if (next.length) {
index--;
selected.removeClass('selected');
next.addClass('selected');
$('.game').css('top', function (i, v) {
return ((i * 120) - (index * 120) + currentTop) + 'px';
});
}
keyDown = true;
}
}
});
$(document).keyup(function (e) {
keyDown = false;
});
So what I changed is:
Added a new variable currentTop that is the value that we always want the .selected item to be at
Changed the $('.game').css() so that it doesn't use v to calculate the new top, it now calculates it based on the i variable (which is the index of that item) and a new index variable
Added the index variable, which keeps track of which index is currently selected. This works using index++ and index-- on keypress.