How to apply css to a dynamically created div? - javascript

Here I have a function that creates a div box, but I wish to move the styling to a external css file. When I do that, however, the boxes are no longer styled. How could I apply the css to the div boxes that are created dynamically? Is it even worth moving the styling to an external css file?
function createBox() {
var box = document.createElement("DIV");
box.setAttribute("id", "box");
document.body.appendChild(box);
boxStyle = box.style;
boxStyle.position = "absolute";
boxStyle.background = '#'+Math.floor(Math.random()*16777215).toString(16);
boxStyle.width = Math.floor(Math.random()*50) + '%';
boxStyle.height = Math.floor(Math.random()*50) + '%';
boxStyle.top = Math.floor(Math.random()*100) + '%';
boxStyle.left = Math.floor(Math.random()*100) + '%';
}
EDIT: I realized that what's been causing me grief in my CSS is that I was using Math.floor and Math.random() functions that don't work in CSS. Silly me!

As you are creating div with id #box, add the following css in the external css file and include it in the <head>
#box {
position: absolute;
background: red;
width: 90px;
height: 50px;
left: 100;
top: 100;
}
It looks like you will creating more boxes of with same id #box. I would recommend you to create based on classes. And use css to apply the styles based on the classname.
function createBox() {
var box = document.createElement("DIV");
box.setAttribute("class", "boxes");
document.body.appendChild(box);
}
css:
.boxes {
position: absolute;
background: red;
width: 90px;
height: 50px;
left: 100;
top: 100;
}
demo

You can apply CSS to dynamicly created items the same way for usual HTML. All you need is to target the correct selector.
http://codepen.io/anon/pen/mnIhj

You can gather the properties you wish to apply on the div box in a class in external style sheet, and use:
function createBox() {
var box = document.createElement("DIV");
box.setAttribute("id", "box");
box.className = "boxStyle";
document.body.appendChild(box);
}

Try this chnages in your script,
function createBox() {
var box = document.createElement("DIV");
box.setAttribute("id", "box");
document.body.appendChild(box);
var boxStyle = document.getElementById("box").style;
boxStyle.position = "absolute";
boxStyle.background = '#'+Math.floor(Math.random()*16777215).toString(16);
boxStyle.width = Math.floor(Math.random()*50) + '%';
boxStyle.height = Math.floor(Math.random()*50) + '%';
boxStyle.top = Math.floor(Math.random()*100) + '%';
boxStyle.left = Math.floor(Math.random()*100) + '%';
}

Related

Code inside "hover" CSS selector stops working

I'm trying to create a small and interactive image gallery inside my page and everything besides this problem is working fine: When I mouse over the images they change opacity and size, as expected, however, after I click one of them and enlarge it, nothing happens when I try mousing over them again.
This is what I mean:
Current CSS:
#houseImages img {
opacity: 0.7;
margin: 1em;
transition: 0.3s;
width: 18em;
height: 15em;
border-radius: 3em;
border-style: solid;
border-width: 0.05em;
}
#houseImages img:hover {
transform: scale(1.1);
opacity: 1.0;
cursor: pointer;
}
Current script that is being used when an image is clicked:
"use strict";
function defaultSettings(imgElement)
{
imgElement.style.position = "initial";
imgElement.style.transform = "scale(1.0)";
imgElement.style.opacity = "0.7";
}
function clickedSettings(imgElement)
{
imgElement.style.position = "absolute";
imgElement.style.transform = "scale(2.6)";
imgElement.style.left = "40%";
imgElement.style.top = "30%";
imgElement.style.opacity = "1.0";
imgElement.style.zIndex = "99";
}
function imageClicked(imgID)
{
let img = document.getElementById("img" + imgID);
let otherImages = document.querySelectorAll("#houseImages img:not(#img" + imgID + ")");
let div = document.getElementById("houseImages");
let previousCloseImageButton = document.querySelector("#houseImages button");
// if another image was already clicked there's some cleanup to do
if(previousCloseImageButton)
previousCloseImageButton.remove();
otherImages.forEach(image => defaultSettings(image));
clickedSettings(img);
let closeImageButton = document.createElement('button');
closeImageButton.setAttribute("id","close");
closeImageButton.setAttribute("onclick","notClicked(" + imgID + ")");
closeImageButton.innerHTML = 'X';
div.append(closeImageButton);
}
function notClicked(imgID)
{
let img = document.getElementById("img" + imgID);
let closeImageButton = document.querySelector("#houseImages button");
defaultSettings(img);
closeImageButton.remove();
}
When you call defaultSettings(img); in the notClicked(imgID) function, you are setting a style property directly on the HTML img objects, as if you have written <img style="opacity: 0.7"> in HTML. Styles set on an object always have higher priority than those resulting from a stylesheet. In effect, rules defined for #houseImages img:hover cannot affect your image.
What you need to do is unset a local style property to let the stylesheet work again:
function defaultSettings(imgElement)
{
imgElement.style.position = "";
imgElement.style.transform = "";
imgElement.style.opacity = "";
}

How to create a initiate a CSS transitioned event?

I have a code which draws a circle on the screen using the css transition, when the transition is finished, it triggers something else. In the code below the transitioned event doesn't work.
Part1: css
<style>
.circle {
transition-property: width, height;
transition-duration: 2s;
position: fixed;
left = 100px;
top = 100px;
background-color: red;
border-radius: 50%;
}
</style>
Part2: Javascript:
<script >
function changeRadius(radius) {
let div = document.createElement('div');
div.className = 'circle';
document.body.append(div);
div.style.width = div.style.height = 0;
console.log(div.style.width);
div.addEventListener("transitionend", function () {
alert('transitionend event!');
});
div.style.width = div.style.height = 2 * radius + 'px';
console.log(div.style.width);
}
changeRadius(100);
The 'transitioned event' is not triggered even if the 'console.log' showed the 'width' property of div has changed to 200px. I have to wrap the last part in the setTimeout function as below:
setTimeout(() => {
div.style.width = div.style.height = 2 * radius + 'px';
}, 0);
Now it works!
May someone knows the inner logic behind this. My assumption is: when the code is implemented, even if the style property inside a function changes, it's not considered as a transitioned event. However, the code outside this block to change the style property will work, such as 'setTimeout' or 'mouse hover' etc. I would like to get some deeper interpretation of this!

How can you get the final height on an element transitioning with css?

If you have an element whose height is animating using a CSS transition, is there a way to use jQuery or pure Javascript to get its finished height before the transition completes?
Consider the following example: https://jsfiddle.net/qm6zz0kq/
<div id="test"></div>
<style>
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 100px;
}
</style>
<script>
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
setInterval(function() {
testElement.innerHTML = 'Height: ' + testElement.clientHeight;
}, 100);
</script>
How could you modify the interval so it always generates "Height: 100"?
I've considered doing some kind of jQuery clone that doesn't have to transition and measuring its height but in this instance, the CSS is nested enough that I'd have to clone basically of the element's parents to make sure it's correct and that could be expensive.
You can put another hidden div (hidden-test, as an example) that is the same as the div test and add to it the class showing right away (without timeout), then get its height, that will be the same.
Look here an example: https://jsfiddle.net/qm6zz0kq/1/
You could read the actual CSSRule, note though this would just get the value defined in the CSS. For instance if the height was specified as 70% it would give 70% and not the actual px height it would end up as, eg if parents height was 170px, it wouldn't give you the value of 70% of 170px. Also note this will not work if the stylesheet is include from a file <link href="css.css">
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
setTimeout(function() {
var rule = getRule("#test.showing");
if(rule){
testElement.innerHTML = 'Height: ' + rule.style.height;
}
}, 100);
function getRule(selector) {
var foundRule = null;
[].slice.call(window.document.styleSheets)
.filter(sheet=>sheet.rules || sheet.cssRules).forEach(sheet=>{
foundRule = foundRule || [].slice.call(sheet.rules||sheet.cssRules)
.filter(rule=>rule.selectorText == selector);
});
if(foundRule && foundRule[0]) return foundRule[0];
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 100px;
}
<div id="test"></div>
You could also put in an element that is a clone. You do not have to also clone the parents like you mention in your question. You just have to insert the element into the same parent. This particular example uses display:none to hide the element, the returned value will not be a calculated value. Again like above if the parent's height is 400px and the height of the element is 75%, 100px will not be returned, 75% would be.
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
//display:none so we do not have to see the temp element
clone.style.display = "none";
clone.classList.add("showing");
testElement.parentNode.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
//Clone the element
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
//display:none so we do not have to see the temp element
clone.style.display = "none";
clone.classList.add("showing");
testElement.parentNode.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
//Remove it as we dont need it anymore
clone.remove();
setTimeout(function() {
testElement.innerHTML = 'Height: ' + endHeight;
}, 300);
#parent {
height:300px;
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 70%;
}
<div id="parent">
<div id="test"></div>
</div>
If you want the actual calculated height you would need to change the clone to use a couple different stles.
visibility:hidden to hide it instead of display:none as display will make it so we won't get a calculated value.
position:absolute to prevent it from modifying the parents dimensions
clone.style.visibility = "hidden";
clone.style.position = "absolute";
//needed to make sure element is contained by parent
parent.style.position = parent.style.position || "relative";
var endHeight = window.getComputedStyle(clone).height;
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
//Clone the element
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
clone.style.visibility = "hidden";
clone.style.position = "absolute";
clone.classList.add("showing");
var parent = testElement.parentNode;
parent.style.position = parent.style.position || "relative";
parent.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
//Remove it as we dont need it anymore
clone.remove();
setTimeout(function() {
testElement.innerHTML = 'Height: ' + endHeight;
}, 300);
#parent {
height:300px;
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 70%;
}
<div id="parent">
<div id="test"></div>
</div>
You can add an 'animationend' event listener to the element .
Example :
testElement.addEventListener('animationend' , showNewHeight);
showNewHeight function(){
// show new height ...do something after animation .
}
Source : http://www.w3schools.com/jsref/event_animationend.asp
hope this helps..

setAttribute background-image can't be changed. Stuck at default value

function showHome() {
removeSlideShow();
var homeHeader = document.createElement("div");
homeHeader.setAttribute("id", "homeHeader");
document.getElementById("window").insertBefore(homeHeader, document.getElementById("content"));
var slideShowDiv = document.createElement("div");
var images = ["slideShow/slideShow-1.jpg", "slideShow/slideShow-2.jpg", "slideShow/slideShow-3.jpg", "slideShow/slideShow-4.jpg", "slideShow/slideShow-5.jpg", "slideShow/slideShow-6.jpg", "slideShow/slideShow-7.jpg"];
homeHeader.appendChild(slideShowDiv);
startSlideShow(slideShowDiv, images);
content.innerHTML = "";
}
function startSlideShow(element, images) {
var iterator = 0;
element.setAttribute("id", "slideShowDiv");
element.setAttribute("style", "background-image: url(" + images[0] + ")");
var startInterval = setInterval(function() {
iterator++;
if (iterator == images.length) iterator = 0;
element.setAttribute("style", "background-image: url(" + images[iterator] + ")");
element.style = "background-image: url(" + images[iterator] + ")";
transition(element);
}, 3000);
}
function removeSlideShow() {
if (document.getElementById("homeHeader")) {
document.getElementById("window").removeChild(document.getElementById("homeHeader"));
}
}
function transition(element) {
element.setAttribute("style", "opacity:0.01;");
var i = 0;
var set = setInterval(function() {
i += 0.01;
element.setAttribute("style", "opacity:" + i + ";");
}, 4);
setTimeout(function() {
clearInterval(set);
element.setAttribute("style", "opacity:1;");
}, 500);
}
div#homeHeader {
background-color: #FFF;
width: 900px;
height: 280px;
border: solid 2px #F00;
border-radius: 20px;
}
div#slideShowDiv {
background-image: url(slideShow/slideShow-1.jpg);
background-color: #FFF;
width: 898px;
height: 278px;
border: solid 1px #FFF;
border-radius: 20px;
background-size: 100% 100%;
}
What i want to do is change the background image every 3 seconds. The code work but it's not changing the image, stays at 'slideShow-1.jpg'. If i remove the transition(element); part, the image rotate just fine. What should i do to get it work? Im still beginner in Javascript, will learn jquery when i got better. Sorry for my grammar.
If i remove the transition(element); part, the image rotate just fine.
The transition part sets a new value for the style attribute.
Setting a new value for the attribute replaces the old value.
You are removing the style for the background image. (So the one from the stylesheet is applied again instead).
What should i do to get it work?
Don't use setAttribute(..., ...) to modify styles.
Use .style.cssPropertyName = ... instead.

Query text() over dynamically added img

I realize it's probably an already answered question, but I wanted to ask, if there is something new on the market, that can easily solve my issue.
I'm loading images to specified coordinates using javascript.
var span = document.createElement("span");
span.innerHTML = "<img src=\"source.gif\" id=\"someid\">";
span.style.position = "absolute";
span.style.left = coodinatesLeft[i] + "px";
span.style.top = coodinatesTop[i] + "px";
document.body.appendChild(span);
Later on, when the mouse goes over the images I want to use the simple mouseenter function in jquery
$("mydivid").mouseenter(function(){ $(this).text("something"); });
to write a text there, where the image is. And I don't get any text, I suppose, because the image is more foreground then the text. Other times I've used it, and it worked, but then I just had a div, and no actual image source on it.
Is there a way to keep the structure and append the text over the image?
PS: I read about the z-index, but not sure if it is exactly what I need, since I don't have a pre-defined css class for the images.
Thanks in advance!
You should use event delegation for dynamically added elements.
$('<span />')
.html('<img src="source.gif" class="myImages">')
.css({
'position': 'absolute',
'left': coodinatesLeft[i] + 'px',
'top': coodinatesTop[i] + 'px'
})
.appendTo('body');
$('.myImages').hover(function() {
$(this).append('<span id="myText">MY TEXT HERE</span>');
}, function() {
$('#myText').remove();
});
CSS:
#myText {
height: same as .myImages;
width: same as .myImages;
opacity: .5;
background: #ccc;
}
You could try something like this:
var span = document.createElement("span");
span.innerHTML = "<img src=\"source.gif\" id=\"someid\" class=\"image-class\">";
span.style.position = "absolute";
span.style.left = coodinatesLeft[i] + "px";
span.style.top = coodinatesTop[i] + "px";
var imgText = document.createElement("span");
imgText.className = "overlay-text";
span.appendChild(imgText);
document.body.appendChild(span);
Add the following css:
.image-class {
width: 100px;
height: 100px;
background-color: red;
}
.overlay-text {
position: absolute;
left: 0;
top: 0;
}
Please checkout this jsfiddle: https://jsfiddle.net/duLL2wrj/
$("#mydivid").mouseenter(function(){ $(this).children('.overlay-text').text("something"); });
$("#mydivid").mouseleave(function(){ $(this).children('.overlay-text').text(""); });

Categories