Can't access the style using DOM [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
For some reason, the error keeps being thrown at me whenever I hover over the selected element. It seems like every time I use the .style property, it gives me this error. The problem is how I'm accessing the CSS element using .style. Is there another way of doing it?
Uncaught TypeError: Cannot read property 'style' of undefined
var image = document.getElementsByClassName("image");
var move = document.getElementsByClassName("link");
var description = document.getElementsByClassName("description");
for(var i = 0; i < move.length; i++){
move[i].addEventListener("click", function(){
if (move[i].style.marginLeft === "500px") {
move[i].style.marginLeft = "0";
} else {
move[i].style.marginLeft = "500px";
}
})
};
for(var i = 0; i<description.length;i++){
image[i].addEventListener("mouseover", function(){
description[i].style.visibility = visible;
description[i].style.opacity = 0;
var last = +new Date();
var tick = function(){
despcription[i].style.opacity = +despcription[i].style.opacity + (new Date() - last)/700;
last = +new Date();
if (+despcription[i].style.opacity < 1) {
(window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
}
};
tick();
});
}

You have a typo: despcription
despcription[i].style.opacity = +despcription[i].style.opacity + (new Date() - last)/700;
last = +new Date();
if (+despcription[i].style.opacity < 1) {
And I don't know if you are trying to do more than this, but are you attempting to fade in an image on hover? If so, then setting this in CSS works well:
EDIT: I updated the sample to show a title under the image when you hover over the image. The key is the ~ (sibling) selector right here:
.image:hover~.image-title {
opacity: 1;
}
It says when the user hovers over the image class, then select the sibling element with class of .image-title and set its opacity to 1.
.image {
background-image: url('https://amazingslider.com/wp-content/uploads/2012/12/dandelion.jpg');
height: 300px;
width: 300px;
background-size: cover;
background-position: center;
}
.image:hover~.image-title {
opacity: 1;
}
.image-title {
opacity: 0;
transition: opacity 1s ease;
display: inline-block;
width: 300px;
text-align: center;
margin: 0;
}
<h1>Hover Over Image</h1>
<div class="image"></div>
<h3 class="image-title">Image Title</h3>

Related

Transition on height using javascript style.height

In order to manipulate height property, so I use javascript not jquery then I got a problem.
The problem is that I cannot override the height back to zero once I have set to the scrollHeight of the element.
Here is my js code:
let isClosed = true;
var cals = document.getElementsByClassName('h-strench-box');
for (var i = 0; i < cals.length; i ++) {
cals[i].addEventListener('click', function(e) {
if (isClosed) {
this.classList.add('h-strench-box-out');
var content = this.querySelector('.h-strench-content');
content.style.height = content.scrollHeight + 'px';
isClosed = false;
} else {
if (this.classList.contains('h-strench-box-out')) {
this.classList.remove('h-strench-box-out');
// this.querySelector('.h-strench-content').style.height = '0';
// This not working
isClosed = true;
} else {
for (var j = 0; j < cals.length; j ++) {
cals[j].classList.remove('h-strench-box-out');
cals[j].querySelector('.h-strench-content').style.height = '0';
// This not working
}
this.classList.add('h-strench-box-out');
var content = this.querySelector('.h-strench-content');
content.style.height = content.scrollHeight + 'px';
}
}
});
}
css
.h-strench-content {
height: 0;
padding: 0;
display: none;
overflow: hidden;
transition: height 0.4s ease-in;
}
.h-strench-box-out .h-strench-content {
display: block;
}
.h-strench-btn {
transition: transform 0.3s ease-out;
}
.h-strench-btn::before {
content: '\f13a';
font-family: "Font Awesome 5 Free";
font-size: 27px;
font-weight: 600;
}
One more question. How can I change the height value(B) not element.style (A). Please compare the picture below. Please help thank you!
First step: make sure your querySelector calls are returning the correct elements. It will always return the first element that matches the selector.
As for the css: Height A is inline css, meaning it will always have priority over height B unless height B is marked !important. In order to revert to height B, height A must be removed entirely via remove property or simply set to null.
var obj = document.getElementById('name');
obj.style.removeProperty('height');
// if you want to return the old value...
// var oldValue = obj.style.removeProperty('height');
If you want to change contents in a stylesheet, see this example:
var declaration = document.styleSheets[0].rules[0].style;
var oldValue = declaration.removeProperty('height');
... However, be careful with the stylesheet example, as a change of indices can throw this off. It would be much safer to find an alternative that adds/removes classes with the values you desire instead.

Unable to update CSS coloring using JavaScript

I've been trying to make this work for a while and for some reason the colors aren't updating. If I had to guess, it has to do with my returning an invalid string, but I'm not sure. The intended result is it converts the hours, minutes, and seconds into hexadecimal values respectively, but for some reason it is not working. If anyone can help it would be greatly appreciated. Thanks!
var div = document.getElementById("full");
function getclockColor() {
var h = toString(today.getHours());
var m = toString(today.getMinutes());
var s = toString(today.getSeconds());
color = '#' + h + m + s;
}
return color;
}
function changeColor() {
div.style.backgroundColor = getclockColor();
}
setInterval(changeColor, 1000);
body {
overflow: hidden;
margin: 0;
padding: 0;
}
#full {
position: absolute;
height: 100%;
width: 100%;
}
<link rel="stylesheet" type="text/css" href="/Users/zanolon/Desktop/Color Clock/Clock.css">
<div id="full"></div>
You have multiple errors:
You are invoking return outside your getclockColor function (and you have an extra }).
There is no today object. From your code I assume you want a Date object newly generated (with the current date). You can create a Date object like this: new Date().
This is not an error, but just so you know, you don't need to convert the numbers to string. It will automatically cast the values to string when concatenating to a string with the + operator.
Consider adding a zero when the number only contains one digit, because otherwise you will find many cases where the string generated will have less than 6 digits (plus the #).
The idea doesn't make that much sense, because you are combining three "random" numbers into a string. In many cases this won't result in a valid hex color string. You could try using the hsl format instead, which looks like this: hsl(120, 100%, 50%). You can achieve this easily with string templates: ` hsl(${h}, ${m}%, ${s}%) `
var div = document.getElementById("full");
function getclockColor() {
const today = new Date()
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
color = '#' + h + m + s;
return color;
}
function changeColor() {
div.style.backgroundColor = getclockColor();
}
setInterval(changeColor, 1000);
body {
overflow: hidden;
margin: 0;
padding: 0;
}
#full {
position: absolute;
height: 100%;
width: 100%;
}
<link rel="stylesheet" type="text/css" href="/Users/zanolon/Desktop/Color Clock/Clock.css">
<div id="full"></div>
Several issues:
You have an extra dangling } there (Which is why you're getting the illegal return statement). You cannot return when not in a function.
Also, today is not set anywhere.
There is no function called toString(). toString() is a method on number, so you can call it like so: today.getHours().toString()
You might want to consider 0 padding your h, m, and s if they're < 10, as you may be getting invalid hex codes (4 characters long), which may not be what you're looking for.
See this (Be aware, the color is changing, but because it's using the hex code :
var div = document.getElementById("full");
function getclockColor() {
var today = new Date();
var h = today.getHours().toString();
var m = today.getMinutes().toString();
var s = today.getSeconds().toString();
var color='#'+h+m+s;
return color;
}
function changeColor() {
console.log(getclockColor());
div.style.backgroundColor = getclockColor();
}
setInterval(changeColor, 1000);
body {
overflow: hidden;
margin: 0;
padding: 0;
}
#full {
position: absolute;
height: 100%;
width: 100%;
}
<div id="full"></div>
To fix the potential 0 padding issue, see below (Grabbed pad from this question):
var div = document.getElementById("full");
function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
function getclockColor() {
var today = new Date();
var h = today.getHours().toString();
var m = today.getMinutes().toString();
var s = today.getSeconds().toString();
var color='#'+pad(h,2)+pad(m,2)+pad(s,2);
return color;
}
function changeColor() {
console.log(getclockColor());
div.style.backgroundColor = getclockColor();
}
setInterval(changeColor, 1000);
body {
overflow: hidden;
margin: 0;
padding: 0;
}
#full {
position: absolute;
height: 100%;
width: 100%;
}
<div id="full"></div>

Looping Arrays to Change Background Image of Div

I am trying to create a loop of an array that changes the background of a div only one single loop. The code is as follows;
var ImagesF = [];
ImagesF[0]="images/image1.png";
ImagesF[1]="images/image2.png";
ImagesF[2]="images/image3.png";
var i = 1;
var index = 0;
var iterations = 0;
var interval = setInterval(autoImgB(), 2000);
function autoImgB(arr1, id){
var url = 'url(' + arr1 [i] + ')';
if(index >= arr1.length) {
index = 0;
iterations++;
}
document.getElementById(id).style.backgroundImage = url;
if (iterations >= 2) {
clearInterval(interval);
} else {index++}
}
The code is being called like, onclick="autoImgB(ImagesF, 'DIV')"It seems to be trying to work and it does change the first image, however then it doesn't seem to be passing the arguments to the next iteration, what am I doing wrong?
-- UPDATE --
I have attempted to add the following code to pass the argument as originally passed during the function call autoImgB(ImagesF, 'DIV'), however I get an error that states, "arr1 is undefined".
var index = 0;
var iterations = 0;
var interval = setInterval(function() {
autoImgB(arr1, id);
}, 2000);
function autoImgB(arr1, id){
var url = 'url(' + arr1 [index] + ')';
if(index >= arr1.length) {
index = 0;
iterations++;
}
document.getElementById(id).style.backgroundImage = url;
if (iterations >= 2) {
clearInterval(interval);
} else {index++}
}
-- UPDATE 2 --
#Andy, requested that I post my nested DIV's for further help, the DIV structure within the contain are as depicted;
var ImagesF = [];
ImagesF[0]="image1.png";
ImagesF[1]="image2.png";
ImagesF[2]="image3.png";
var n = 0;
function autoImgB(arr1) {
var url = 'url(' + arr1 [n] + ')';
if (n < arr1.length) {
document.getElementById('DIV3').style.backgroundImage = url;
setTimeout(autoImgB, 2000, arr1, ++n);
console.log(url,n)
}
}
.DIV1{
position:absolute;
top: 0px;
left: 0px;
width:100%;
height:100%;
background-image:url('');
background-color: none;
display: none;
z-index: 2;
}
.DIV2{
position:absolute;
top: 0px;
left: 0px;
width:100%;
height:100%;
background-image:url('');
background-color: none;
display: none;
z-index: 1;
}
.DIV3{
position:absolute;
top: 40px;
left: 417px;
width:105px;
height:130px;
background-image:url('');
background-color: none;
display: block;
z-index: 2;
}
<div class="holder">
<div class="DIV1" id="DIV1"></div>
<div class="DIV2" id="DIV2"></div>
<div class="DIV3" id="DIV3"></div>
</div>
<button style="cursor:pointer" onclick="autoImgB(ImagesF)">Press</button>
What I would like for this to do is be able to call it by ID within the function, eg: autoImgB(ImagesF, 'DIV3').
OK. So the main issue is that you are calling the function immediately rather than passing a reference to the function to setInterval.
var interval = setInterval(autoImgB, 2000);
The other problem is that you aren't passing any arguments to the function. There are two ways to do that. The first is to pass them as additional arguments after the time:
var interval = setInterval(autoImgB, 2000, ImagesF, 0);
The second is to call the function itself within the setInterval callback:
var interval = setInterval(function () {
autoImgB(ImagesF, 0);
}, 2000);
The other issue is that it's not clear what your HTML looks like. You appear to be getting an element with a particular id but are passing in div as the argument. So either you have an element like <div id="div"></div> or something else is going on. You should probably take a closer look at that.
That said you can shorten your code considerably if you use setTimeout instead of setInterval, as you only need to do the minimum of checks, and there's no need to clear the timer at any point. Just check to see if the index is less than the array length and call the function again.
var div = document.querySelector('div');
function autoImgB(arr, i) {
if (i < arr.length) {
div.style.backgroundImage = 'url("' + arr[i] + '")';
setTimeout(autoImgB, 2000, arr, ++i);
}
}
autoImgB(ImagesF, 0);
Here's some working code with setTimeout.
setInterval expects a function as its first parameter
var interval = setInterval(function() {
autoImgB(ImagesF, 'DIV');
}, 2000);
The only thing which is wrong in the code you've created is that you pass the return value of the autoImgB function which is undefined into the setInterval function, but the setInterval function only accepts a function or a code string.
Documentation for setInterval
I've created a example based on your code to show you how it'll work.

How do I add class for time(clock)

I get date and clock.
var mydate = new Date();
var clock = tarih.getHours();
var minute = tarih.getMinutes();
And want this;
if (clock> 5) {
add this class, if have id "menu" = "menu_edit" (i dont know how can i do)
}
How can I do that?
If 'menu' is id of element:
document.querySelector('#menu').className += " menu_edit";
UPD:
According to your comment:
document.querySelector('.class1').className += ' class2';
Or if there are several elements:
var elems = document.querySelectorAll('.class1');
elems.forEach = [].forEach;
elems.forEach(function(el){
el.className += ' class2';
});
https://developer.mozilla.org/docs/Web/API/Document/querySelector - about function.
http://www.w3schools.com/cssref/css_selectors.asp - about selectors.
Maybe something like this. Please see the comments for an explanation.
checkout https://babeljs.io/ for info on compiling ES6 to ES5
const menu = document.querySelector('#menu')
const menuClasses = [
'menu--morning',
'menu--afternoon',
'menu--evening'
]
// helper function to toggle classes like a radio button
// this uses currying to lock in the classes and element, but
// allow us to change the active class dynamically
const toggleClasses = (classes, element) => clazz => {
element.classList.remove(...classes)
element.classList.add(clazz)
}
// create the toggle function and pass in the classes and the element
const toggleMenuClass = toggleClasses(menuClasses, menu)
// run a timer every n seconds
const timer = () => {
const date = new Date()
// I'm using seconds for the example as you will see the change
// but you should change this to hours
const second = date.getSeconds()
if (second < 20) {
toggleMenuClass('menu--morning')
}
else if (second < 40) {
toggleMenuClass('menu--afternoon')
}
else {
toggleMenuClass('menu--evening')
}
// just to show the current time for the example
menu.textContent = second
// call the timer function again after 500 milliseconds
setTimeout(timer, 500)
}
// init the timer on load
timer()
#menu {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transition: 1s background;
font-size: 5em;
font-family: sans-serif;
color:#fff;
text-align: center;
line-height: 100vh;
}
#menu.menu--morning {
background: #AED6F1;
}
#menu.menu--afternoon {
background: #ABEBC6;
}
#menu.menu--evening {
background: #B95A75;
}
<div id="menu">clock</div>
Thanks everyone. I solved my problem with pHp.
Instead of adding class, i try take a different css page. Thanks for all things.
Have a nice day. :)
$clock = date('H');
if ($clock > 14) {
echo "<link rel='stylesheet' type='text/css' href='css/night.css'>";
}

Image gallery with max items and pagination with javascript

This is my situation:
I have a image gallery with 10 images visible on the main page and a pagination bar. The images came from a for loop iteration over a json file. That's no problem, they are just there ;-)
Something like:
for i=0; i <10; i++
create div with styles and images[i].image;
My question is:
I want to display the next 10 images on page 2, so when you click on page 2, it counts from 11 to 20.
I found the jQuery 'Jpaginate'-plugin...
Can i accomplish that with this plugin?
Could someone explain me in the way i have to thing with Vars, Counts, Objects??
Thanks and kind regards,
Mike
I have made you an example on how you can approach this. I'm not saying it is bugproof, but it's the concept that matters. You might find some inspiration and maybe reach your goal.
var imgSrc = "https://s-media-cache-ak0.pinimg.com/236x/36/a5/7b/36a57b0f0ab16e885fcc230addb695c2.jpg";
var json = [];
for (var i = 0; i < 36; i++)
json.push({
Title: "Title " + (i + 1),
Source: imgSrc
});
/*
Just for ease, I'm creating an array with 36 objects (3x3 gallery)
so 9 images per page
*/
var pageLimit = 9;
var page = 1;
showImages();
$("#btnPrevious").click(function() {
if (pageLimit <= 9) {
pageLimit = 9;
page = 1;
} else {
page--;
pageLimit -= 9;
}
showImages();
});
$("#btnNext").click(function() {
if (pageLimit >= json.length) {
pageLimit = json.length;
} else {
page++;
pageLimit += 9;
}
showImages();
});
function showImages() {
$(".images").empty();
for (var i = pageLimit - 9; i < pageLimit; i++) {
var template = $("<div></div>").addClass("template");
var img = $("<img>");
img.attr("src", json[i].Source);
img.attr("alt", json[i].Title);
var br = $("<br/>");
var title = $("<span></span>").html(json[i].Title);
template.append(img).append(br).append(title);
$(".images").append(template);
}
$("#page").html("Page " + page);
}
.gallery {
width: 100%;
height: 500px;
border: 1px solid black;
background-color: lightgray;
text-align: center;
}
.images {
width: 90%;
margin: 0 auto;
height: 100%;
margin-bottom: 15px;
}
img {
height: auto;
width: 33%;
margin: 20px 5px;
}
.template {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gallery">
<div class="images"></div>
<button id="btnPrevious">
< Previous
</button>
<span id="page"></span>
<button id="btnNext">
> Next
</button>
</div>
Don't mind the CSS, because I suck at that (lol). It was based on the space I had on jsFiddle, but looking at it now (on full page or just the area the snippet provides) it looks awful. If a CSS guru could fix this .. Question in a question?
You can create your own pagination plugin.
You must store current page somewhere and modify your factory.
Something like: for i=current_page * count_per_page; i < count_per_page * (current_page + 1); i++ create div with styles and images[i].image;

Categories