How to change content:url() using javascript - javascript

Hi I am trying to make a traffic light using an array of pictures.
I currently need to change the image path stated in css when a button is clicked so that the light's picture changes.
So in this case the content.url() line of each class needs to be change when function is called by the button. The method I'm currently using is incorrect but I think it may help to help you understand.
<style>
#rect{
height:550px;
width:180px;
border:1px solid #000;
}
.black1 {
position: relative;
top: 10px;
left: 10px;
content.url('black.png')
}
.black2 {
position: relative;
top: 20px;
left: 10px;
content.url('black.png')
}
.black3 {
position: relative;
top: 30px;
left: 10px;
content.url('black.png')
}
</style>
<Body>
<div id="rect">
<img class="black1" />
<img class="black2" />
<img class="black3" />
</div>
<script>
var x = ["black.png", "red.png", "orange.png",'green.png'];
var i = -1;
function change(){
i++;
if (i == 0){
document.getElementByClass('black1').src=x[1];
document.getElementByClass('black2').src=x[0];
document.getElementByClass('black3').src=x[0];
}
}
</script>
<button onclick = "change()">Change light</button>
</div>
</Body>
</html>

I would separate your css classes in red, orange/yellow, green. Then you can work with the classList function. Bellow you will find a simple working example. Feel free to improve it.
let i = -1;
function change() {
const tl = document.querySelectorAll('.light');
i++;
if (i == 0) {
tl[0].classList.add('red')
}
if (i == 1) {
tl[1].classList.add('yellow')
}
if (i == 2) {
tl[2].classList.add('green')
}
if (i == 3) {
tl[2].classList.remove('green');
tl[1].classList.remove('yellow');
tl[0].classList.remove('red');
i = -1;
}
}
#rect{
height:350px;
width:120px;
border:1px solid #000;
}
img {
height: 100px;
}
.light {
position: relative;
top: 10px;
left: 10px;
content: url(https://via.placeholder.com/150/000000);
}
.red {
content: url(https://via.placeholder.com/150/FF0000);
}
.yellow {
content: url(https://via.placeholder.com/150/FFFF00);
}
.green {
content: url(https://via.placeholder.com/150/008000);
}
<Body>
<div id="rect">
<img class="light" />
<img class="light" />
<img class="light" />
</div>
<script>
</script>
<button onclick = "change()">Change light</button>
</div>
</Body>
</html>

To make your program work, I would make it look something like this:
Get rid of content.url('black.png') in css
Set default urls to your img tags that would be "black.png"
Make working code:
const urls = ["black.png", "red.png", "orange.png",'green.png'];
let index = -1;
const imgs = ["black1", "black1", "black1"].map(className => document.getElementByClass(className));
function change(){
index++;
// will take rest of division,
// for example 4 % 3 === 1, 5 % 3 === 2, 6 % 3 === 0
const currentLight = index % 3;
imgs.forEach((image, i) => {
if (i === currentLight) {
// current image should be active and we map it correct light urls
// for example currentLight is 0, if will make it url[0] which is red
image.src = urls[currentLight + 1];
}
else {
// turn off the lights that are not equal to currentLight
image.src = urls[0];
}
});
}
change(); // initial call to turn the red light on. If not called all lights will be off
Hope this is the behaviour that you were looking for.
But I wrote that you need to get rid of content: url and your question is about changing it. Basically JavaScript cannot modify classes (unless you dynamically generate them with JS from string, but this is a terrible idea). If you really want to use content: url(does not mean you should), you need to create 3 classes .red, .orange and .green with respective urls and toggle those classes with JS like you would do with toggling src's.

Related

How to use getElementsByClassName() for adding both grids and display one after another?

I Have Tried to add grid-2 when we press a key, but it's not working as I expected.
When it is displaying grid-2 I want the grid to disappear (I don't know how to do).
(background):-
I have searched and found there is a visibility property in CSS, but don't know how to apply to the whole grid and undo the visibility property and make them visible.
I have tried to add the grid-2 by getElementById but both the grids are appearing at a time.
(don't know how to make them appear one after another).
let curr_div_on = 0,curr_div_off = 0;
const key = document.getElementsByClassName('keys');
function setPlayingOn() {
key[curr_div_on % 4].classList.add("playing");
curr_div_on = (curr_div_on + 1) % 4;
}
function setPlayingOff() {
key[curr_div_off % 4].classList.remove("playing");
curr_div_off = (curr_div_off + 1) % 4;
}
setInterval(setPlayingOn, 500);
setTimeout(() => setInterval(setPlayingOff, 500), 500);
document.addEventListener('keypress', function(){
if(curr_div_on ==1){
var element = document.getElementsByClassName("grid-2");
element.classList.add("grid");
}
})
.grid{
display: grid;
grid-template-columns: auto auto;
grid-gap:10px;
}
.key{
padding: 20px;
border: 1px solid;
background-color: #2196F3;
text-align:center;
}
.playing{
transform: scale(1,1);
border-color: #ffc600;
box-shadow: 0 0 1rem #ffc600;
}
<html>
<div class='grid'>
<div class='key'>ABCD</div>
<div class='key'>EFGH</div>
<div class='key'>IJKL</div>
<div class='key'>LMNO</div>
</div>
<div class='grid-2'>
<div class='button'>A</div>
<div class='button'>B</div>
<div class='button'>C</div>
<div class='button'>D</div>
</div>
</html>
I think the code is wrong in these two points:
const key = document.getElementsByClassName('keys'); --> The selector should be 'key'
var element = document.getElementsByClassName("grid-2"); --> The result is a list (DomTokenList), so you should take the first element (var element = document.getElementsByClassName("grid-2")[0];)

js vertical slider with arrows

The thing is that I need to make a vertical images slider,so that when i press arrow down/arrow up every image changes it's position (the highest one goes bottom,the previous take it's place)
what it should look like:
what i have got so far:
$(function(){
var $vsliderboxes = $('#vsliderboxes'),
$vslidernav = $('#vslidernav'),
boxHeight = $vsliderboxes.height(),
current_index = 0;
function clickslide(){
clearInterval(intervalTimer);
clearTimeout(timeoutTimer);
timeoutTimer = setTimeout(function () {
intervalTimer = window.setInterval(autoslide, 2000);
}, 2500);
var index = $(this).index();
current_index = index;
$vsliderboxes.children().stop().animate({
top : (boxHeight * index * -1)
}, 500);
}
function autoslide(){
current_index++;
if (current_index >= $vsliderboxes.children().children().length) {
current_index = 0;
}
$vslidernav.find('a').eq(current_index).trigger('click');
}
$vslidernav.find('a').click(clickslide);
var intervalTimer = window.setInterval(autoslide, 2000),
timeoutTimer = null;
});
#vslidernav ul {
list-style: none;
padding: 0;
}
#vslidernav ul a {
padding: 0;
cursor: pointer;
height: 50px;
}
#vslidernav ul a:active {
color: #9C9A99;
}
#vslidernav ul a li {
height: 50px;
}
#vslidernav ul .active li {
}
.#vslidernav ul a:active {
background: transparent;
color: #9C9A99;
}
.vslider {
display: inline-block;
}
#vslidernav {
float: left;
width: 100px;
z-index: 1;
height: 250px;
}
#vsliderboxes {
position : relative;
overflow : hidden;
}
#vsliderboxes div {
height: 250px;
width: 900px;
}
#vsliderboxs-inner {
position : relative;
width : 900px;
height : 250px;
}
<div class="vslider">
<div id="vslidernav">
<ul>
<a id="1">
<li><img src="img/arrtop.gif"></li>
</a>
<a id="2">
<li><img src="img/arrdown.gif"></li>
</a>
<a id="3">
<li></li>
</a>
</ul>
</div>
<div id="vsliderboxes">
<div id="vsliderboxs-inner">
<div id="box1" class="active"><img src="img/slide1.gif"></div>
<div id="box2" class="inactive"><img src="img/slide2.gif"></div>
<div id="box3" class="inactive"><img src="img/slide3.gif"></div>
</div>
</div>
</div>
thanks for any advice
I think, that it isn't possible to solve this issue like you try to.
Because, when you work with the "top" property, you can't take one image from the top and append it to the other end because appending the image, will move the other images to another place --> the top property wouldn't be correct any more.
I think the contributed sliders (e.g. http://www.jssor.com/demos/vertical-slider.slider) work with the transform CSS property.
transform: translate3d()
Try to research about this property.
Roko C. Buljan answered on this page: loop carousel jquery
He uses a scrollTop loop for your problem.
I've also written a simple slider some time ago. I have now implemented the Roku C. Buljan method. Feel free to look at my code on Bitbucket.
https://bitbucket.org/d-stone/jqueryslider
An excerpt may help you:
value = prev_or_next == 'next' ? self.globals.slide_height : 0;
last = $('#container').find('> div:last');
first = $('#container').find('> div:first');
if(prev_or_next == 'prev') { // click on "next"-button
first.before(last); // put last element before first
settings.elements.inner.scrollTop(self.globals.slide_height); // set the scrollTop to 1 slide-height
}
// animation itself:
$('#container').stop().animate({scrollTop: value}, {
duration: settings.slide_speed,
done: function() {
if(prev_or_next == 'next') {
// put first item after last
last.after(first);
}
}
});
I'd advise you to validate your HTML (W3C Validator). There are some errors inside.
Invalid HTML can be the reason for some CSS and Javascript Errors.

How to create a slideshow before showing the page?

I've been trying to find a way in order to create a slideshow and specify the timing between each picture. Then after the sequence, I want to display/reveal the home page.
I don't really have a lot of JavaScript experience so any help would be appreciated.
There are many ways to do it, here is one simple/basic example:
jQuery.fn.reverse = [].reverse; /* Just a helper */
var slideshowContainer = $('.slideshow');
var slideshowItems = slideshowContainer.find('.item').reverse();
var slideshowItemsTotal = slideshowItems.length;
slideshowItems.each(function(i) {
var thisItem = $(this);
setTimeout(function() {
thisItem.fadeOut(1000, function() {
thisItem.remove();
if( i+1==slideshowItemsTotal ) {
slideshowContainer.remove();
};
});
}, i*5000+4000);
});
* {
margin: 0 none;
box-sizing: border-box;
}
.slideshow {
position: fixed;
z-index: 10;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
}
.slideshow .item {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Page header</h1>
<p>Page content.</p>
<div class="slideshow">
<img class="item" src="http://placehold.it/800x600/00ff00/333" />
<img class="item" src="http://placehold.it/800x600/ff0000/111" />
</div>
Also on JSFiddle.
You should use setTimeout function to put timing between every function. Then change the pictures with functions to make it look like it is a slideshow.
Example: calls the function after 3 seconds to make an alert.
function myFunction() {
setTimeout(function(){ alert("Hello"); }, 3000);
}
You can find millions of examples on google for timing with JS.
Good luck

Create dynamic Rectangle collection in html using js

Hello All I am a beginner in html and js, and I am trying to create a webpage containing a rectangle collection in which when a new rectangle is created is placed beside the previous rectangle.
I have created a div element and trying to add newly created div (rectangle shape with background color different based on condition), but I am not able to get the desired result.
<html>
<head>
<title>parkIn</title>
<meta charset="utf-8" />
</head>
<style>
.ParkSlots {
border: solid 1px;
width: 60%;
height: 400px;
top: 50%;
left: 50%;
position: fixed;
transform: translate(-50%, -50%);
display: inline;
}
.row:before,
.row:after {
content: "";
display: table;
clear: both;
}
.col-1 {
width: 15%;
margin-left: 10px;
height: 350px;
padding: 2px;
}
</style>
<body onload="viewCreate()">
<div class="ParkSlots">
<div class="row" id="content">
</div>
</div>
</body>
<script language="javascript">
function viewCreate() {
for (int i = 0; i < 5; i++) {
if (i % 2 == 0) {
createGreenBox();
} else {
createRedBox();
}
}
}
function createRedBox() {
var = document.createElement('div');
div.className = 'col-1';
div.style.backgroundColor = 'red';
document.getElementById('content').appendChild(div);
}
function createGreenBox() {
var = document.createElement('div');
div.className = 'col-1';
div.style.backgroundColor = 'lightgreen';
document.getElementById('content').appendChild(div);
}
</script>
</html>
I want an output that looks something like this:
Just in glancing at your code, I see at least two typos:
for (int i = 0; i < 5; i++) { - in JS, int is not used in this way. Use var i = 0...
var = document.createElement('div'); - you're missing a variable name on this line in both create box functions. I assume, from the rest of the code you need var div = document.createElement('div');
The rest will be CSS. In your stylesheet you're applying the border to the outter most containing div, from you're example, you need to apply that to the .col-1 class. You'll also want to use display:inline-block on that class, and set widths and margins to play nicely with the border size. I took the liberty of creating a jsfiddle for you with my recommended changes.

after scrolling, detect when element returns to original position

I am trying to, sort of, emulate the effect here. Essentially, during scrolling, change the css (drop shadow), and when the element comes back to original position (remove shadow).
I am able to detect scroll, but not able to figure out how to detect the return to the original un-scrolled state.
HTML
<div id="container">
<ul>
<li id="one">el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li><li>el</li>
</ul>
</div>
CSS
html, body {
margin: 0;
padding: 0;
height: 100%;
}
#container {
height: 100px;
width: 500px;
border: 1px solid #000000;
overflow: scroll;
}
JS (with jquery)
var p = $('#one');
var position0 = p.position().top;
$('#container').scroll(function () {
if (p.position().top != position0) {
console.log('p.position: ' + p.position().top);
$('#container').css('background-color', 'pink');
}
});
JSFIDDLE: http://jsfiddle.net/nrao89m3/
PS: From console.log it doesn't seem to return to its original value at all.
Just add an else block:
var p = $('#one');
var position0 = p.position().top;
$('#container').scroll(function () {
if (p.position().top != position0) {
console.log('p.position: ' + p.position().top);
$('#container').css('background-color', 'pink');
} else {
$('#container').css('background-color', 'white');
}
});
http://jsfiddle.net/vyjbwne2/

Categories

Resources