So basically I have this div in body
<body>
<div id="main_content"></div>
</body>
Now I am downloading some data from the internet (a set of boolean data) and I have this div template. Let's say the data is (true, false, true). Then for each data I want to alter the template div. For example: first one is true so inside the template div I will change the sub1 div's height to 40 px; if it's false, I'd change sub2 div's height to 40 px; and then I'd append this modified template div to main_content div
Template div:
.child{
width:300px;
height:auto;
}
.sub1{
width:300px;
height:20px;
background-color:#0FF;
}
.sub2{
width:300px;
height:20px;
background-color:#F0F;
}
<div class="child">
<div class="sub1"></div>
<div class="sub2"></div>
</div>
After all this this should be the final output of main_content div
What would be the easiest way of doing this using HTML/CSS/JS.
Thanks
Short answer: Here is a codepen
Long answer:
I would use js to dynamically generate your template div:
function makeTemplateDiv() {
var child = document.createElement('div');
child.className = "child"
var sub1 = document.createElement('div');
sub1.className = "sub1"
var sub2 = document.createElement('div');
sub2.className = "sub2"
child.appendChild(sub1);
child.appendChild(sub2);
return child;
}
Then make a css class for a taller 40 px
.taller {
height: 40px;
}
Then use js to to alter your template based on a passed in value
function alterTemplateDiv(value) {
var template = makeTemplateDiv();
if(value) {
template.getElementsByClassName("sub1")[0].className += " taller";
} else {
template.getElementsByClassName("sub2")[0].className += " taller";
}
return template;
}
Then use js to pass in your array of values, make the divs, and append them
function appendDivs(arrayOfValues) {
var mainDiv = document.getElementById("main_content");
for(var i = 0; i < arrayOfValues.length; i++) {
mainDiv.appendChild(alterTemplateDiv(arrayOfValues[i]));
}
}
This kind of question begs for a million different types of answers, but I think this generally keeps with most best practices for front end coding without the use of a framework:
// Self-invoking function for scoping
// and to protect important global variables from other script changes
// (The variable references can be overwritten)
(function (window, document) {
var templateText,
generatedEl,
topEl,
bitArray;
// Data
bitArray = [true, false, true];
// Get template text
templateText = document.getElementById('my-template').text.trim();
// Loop through your T / F array
for (var i = 0, l = bitArray.length; i < l; i++) {
// Create a DIV and generate HTML within it
generatedEl = document.createElement('div');
generatedEl.innerHTML = templateText;
// Modify the new HTML content
topEl = generatedEl.getElementsByClassName('child')[0];
topEl.className += bitArray[i] ? ' typeA' : ' typeB' ;
// Insert generated HTML (assumes only one top-level element exists)
document.getElementById('my-container').appendChild(generatedEl.childNodes[0]);
}
})(window, document);
.child {
width: 300px;
height: auto;
}
/* For true */
.child.typeA > .sub1 {
width: 300px;
height: 40px;
background-color: #0FF;
}
.child.typeA > .sub2 {
width: 300px;
height: 20px;
background-color: #F0F;
}
/* For false */
.child.typeB > .sub1 {
width: 300px;
height: 20px;
background-color: #0FF;
}
.child.typeB > .sub2 {
width: 300px;
height: 40px;
background-color: #F0F;
}
<!-- Container -->
<div id="my-container">
<!-- HTML Template -->
<script id="my-template" type="text/template">
<div class="child">
<div class="sub1"></div>
<div class="sub2"></div>
</div>
</script>
</div>
Note that the HTML content, JavaScript code and CSS are all kept very separated. This is based on the concepts of "Separation of Concerns" and "Unobtrusive JavaScript". I invite you to read up on them if you haven't already. Also, front end templating can be used for dynamic content like I did here, but I would recommend doing templating on the back end when you can. It works better for SEO purposes.
jQuery makes it easier to manipulate the DOM, so here is another solution for your problem:
var data = [true, false, true];
for (i=0; i<data.length; i++) {
var height1;
var height2;
if (data[i] == true) {
height1 = 40;
height2 = 20;
}
else {
height1 = 20;
height2 = 40;
}
var div1 = document.createElement("div");
$(div1).toggleClass("sub1")
.height(height1)
.appendTo("#main_content");
var div2 = document.createElement("div");
$(div2).toggleClass("sub2")
.height(height2)
.appendTo("#main_content");
}
I am relatively new to all this so if you see anything I am doing wrong, or anyways to simplify any code please do not hesitate to say.
I have the following code to enlarge the div element:
var profilePostsClick = function () {
$('.largeBox, .smallBox, .longBox').click(function () {
$(this).animate({
width: '100%',
height: '40%'
}, 200);
$('.closePost', this).removeClass('closePostHide');
});
};
$(document).ready(profilePostsClick);
https://jsfiddle.net/jvkhmpbt/
I am wanting to close each div when the cross is clicked, returning it to it's original size and positioning (with height: auto if feasible).
Aslo is there a way to make it so each div opens above the smaller ones? (like the top left div does, i am aware this is because of it's positioning)
Thanks
You can do like following way by adding and removing class
JQuery:
$('.largeBox, .smallBox, .longBox').click(function (e) {
e.preventDefault();
$(this).addClass('increaseSize');
$('.closePost', this).removeClass('closePostHide');
});
$('.glyphicon-remove').click(function (e) {
e.stopPropagation()
$('.glyphicon-remove').parent().parent().removeClass('increaseSize');
$('.closePost', this).addClass('closePostHide');
});
CSS:
.increaseSize{
width: 100%;
height: 40%;
}
Check Fiddle Here.
You could save the animation properties/values in an cache-object and restore them after your animation.
http://jsfiddle.net/jvkhmpbt/4/
var animationResetCache = [];
var saveValues = function (node) {
animationResetCache.push({
node: node,
width: node.css('width'),
height: node.css('height')
});
};
var restoreValues = function (node) {
for (var i = 0; i < animationResetCache.length; ++i) {
var item = animationResetCache[i];
if (item.node.is(node)) {
return item;
}
}
};
var profilePostsClick = function () {
$('.largeBox, .smallBox, .longBox').click(function (e) {
var $this = $(this);
if ($this.hasClass('open')) return;
saveValues($this);
$this.addClass('open').animate({
width: '100%',
height: '40%'
}, 200);
$this.find('.closePost').removeClass('closePostHide');
});
$('.closePost').click(function () {
var $parent = $(this).parent('.largeBox, .smallBox, .longBox');
if ($parent.hasClass('open')) {
var cachedValues = restoreValues($parent);
$parent.animate({
width: cachedValues.width,
height: cachedValues.height
}, function () {
$parent.removeClass('open');
});
$parent.find('.closePost').addClass('closePostHide');
}
});
};
$(document).ready(profilePostsClick);
I think it's easier to use a toggle and do the animation in CSS3
$("img").click(function(){
$(this).toggleClass('expanded');
});
I would suggest to add one more identical class to each of smallBox,largeBox and longBox which will be called parentd to identify parent div and animate it back and add below js:
DEMO
$('.closePost').on('click',function(e)
{
$(this).closest('.parentd')
.animate({
width: '40%',
height: 'auto'
},200).removeAttr('style');
$(this).addClass('closePostHide');
e.stopPropagation();
});
If we continue on Rover his answer, we can use the switchClass function in jQuery Ui. (source)
This function let's you switch the classes of an object, creating an animation in the difference between those classes.
Example code: jsFiddle
<div class="large"></div>
CSS:
.large{
width: 100%;
height: 200px;
background-color: red;
}
.small {
width: 10%;
height: 50px;
background-color:green;
}
JS:
$("div").switchClass("large","small",500);
I want to dynamically create divs, append them to the body and set a jQuery animation.
This is where the elements are created:
function drawSpot()
{
var myH1 = document.createElement("div");
myH1.style.position = "absolute";
myH1.style.top = GetRandom(0,100)+"%";
myH1.style.left = GetRandom(0,100)+"%";
myH1.style.width="40px";
myH1.style.height="40px";
$("body").append(myH1);
}
And from the time on they are appended to the body, I want to start the animation.
If you already using jQuery, you should do it all the way:
$('<div>', {
css: {
position: 'absolute',
top: GetRandom(0,100)+'%',
left: GetRandom(0,100)+'%',
width: '40px',
height: '40px'
}
}).appendTo( document.body ).animate({
left: '100%' // for instance
}, 2000);
By using .appendTo() you still have a reference to your original object and be able to chain methods on it.
Ref.: jQuery constructor, .appendTo(), .animate()
demo: http://jsfiddle.net/dkuVu/
Use jQuery for creation of elements, and animate it when appending:
function drawSpot() {
var myH1 = $("<div>").css({ position: "absolute",
top: GetRandom(0,100)+"%",
left: GetRandom(0,100)+"%",
width: 40,
height: 40 });
$("body").append(myH1.animate(...));
}
http://jsfiddle.net/nagCf/
That should work
function drawSpot()
{
var myH1 = '<div id="newDiv">Some Text</div>';
$("body").append(myH1);
$("#newDiv").css({'position' : 'absolute',
'top' : GetRandom(0,100)+"%",
'left' :GetRandom(0,100)+"%",
'width':'40px',
'height':'40px'
});
$("#newDiv").hide().fadeIn(500);
}
You can use : $(myH1).animate({left:'*randomvalue*', top:'*randomvalue*'},1000); after the append.
http://jsfiddle.net/Wumrr/2/
I have the following JavaScript variables:
var fontsize = "12px"
var left= "200px"
var top= "100px"
I know that I can set them to my element iteratively like this:
document.getElementById("myElement").style.top=top
document.getElementById("myElement").style.left=left
Is it possible to set them all together at once, something like this?
document.getElementById("myElement").style = allMyStyle
If you have the CSS values as string and there is no other CSS already set for the element (or you don't care about overwriting), make use of the cssText property:
document.getElementById("myElement").style.cssText = "display: block; position: absolute";
You can also use template literals for an easier, more readable multiline CSS-like syntax:
document.getElementById("myElement").style.cssText = `
display: block;
position: absolute;
`;
This is good in a sense as it avoids repainting the element every time you change a property (you change them all "at once" somehow).
On the other side, you would have to build the string first.
Using Object.assign:
Object.assign(yourelement.style,{fontsize:"12px",left:"200px",top:"100px"});
This also gives you ability to merge styles, instead of rewriting the CSS style.
You can also make a shortcut function:
const setStylesOnElement = function(styles, element){
Object.assign(element.style, styles);
}
#Mircea: It is very much easy to set the multiple styles for an element in a single statement.
It doesn't effect the existing properties and avoids the complexity of going for loops or plugins.
document.getElementById("demo").setAttribute(
"style", "font-size: 100px; font-style: italic; color:#ff0000;");
BE CAREFUL: If, later on, you use this method to add or alter style properties, the previous properties set using 'setAttribute' will be erased.
Make a function to take care of it, and pass it parameters with the styles you want changed..
function setStyle( objId, propertyObject )
{
var elem = document.getElementById(objId);
for (var property in propertyObject)
elem.style[property] = propertyObject[property];
}
and call it like this
setStyle('myElement', {'fontsize':'12px', 'left':'200px'});
for the values of the properties inside the propertyObject you can use variables..
I just stumbled in here and I don't see why there is so much code required to achieve this.
Add your CSS code using String Interpolation.
let styles = `
font-size:15em;
color:red;
transform:rotate(20deg)`
document.querySelector('*').style = styles
a
A JavaScript library allows you to do these things very easily
jQuery
$('#myElement').css({
font-size: '12px',
left: '200px',
top: '100px'
});
Object and a for-in-loop
Or, a much more elegant method is a basic object & for-loop
var el = document.getElementById('#myElement'),
css = {
font-size: '12px',
left: '200px',
top: '100px'
};
for(i in css){
el.style[i] = css[i];
}
set multiple css style properties in Javascript
document.getElementById("yourElement").style.cssText = cssString;
or
document.getElementById("yourElement").setAttribute("style",cssString);
Example:
document
.getElementById("demo")
.style
.cssText = "margin-left:100px;background-color:red";
document
.getElementById("demo")
.setAttribute("style","margin-left:100px; background-color:red");
Strongly typed in typescript:
The object.assign method is great, but with typescript you can get autocomplete like this:
const newStyle: Partial<CSSStyleDeclaration> =
{
placeSelf: 'centered centered',
margin: '2em',
border: '2px solid hotpink'
};
Object.assign(element.style, newStyle);
Note the property names are camelCase not with dashes.
This will even tell you when they're deprecated.
You can have individual classes in your css files and then assign the classname to your element
or you can loop through properties of styles as -
var css = { "font-size": "12px", "left": "200px", "top": "100px" };
for(var prop in css) {
document.getElementById("myId").style[prop] = css[prop];
}
Simplest way for me was just using a string/template litteral:
elementName.style.cssText = `
width:80%;
margin: 2vh auto;
background-color: rgba(5,5,5,0.9);
box-shadow: 15px 15px 200px black; `;
Great option cause you can use multiple line strings making life easy.
Check out string/template litterals here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Using plain Javascript, you can't set all the styles at once; you need to use single lines for each of them.
However, you don't have to repeat the document.getElementById(...).style. code over and over; create an object variable to reference it, and you'll make your code much more readable:
var obj=document.getElementById("myElement").style;
obj.top=top;
obj.left=left;
...etc. Much easier to read than your example (and frankly, just as easy to read as the jQuery alternative).
(if Javascript had been designed properly, you could also have used the with keyword, but that's best left alone, as it can cause some nasty namespace issues)
Since strings support adding, you can easily add your new style without overriding the current:
document.getElementById("myElement").style.cssText += `
font-size: 12px;
left: 200px;
top: 100px;
`;
Don't think it is possible as such.
But you could create an object out of the style definitions and just loop through them.
var allMyStyle = {
fontsize: '12px',
left: '200px',
top: '100px'
};
for (i in allMyStyle)
document.getElementById("myElement").style[i] = allMyStyle[i];
To develop further, make a function for it:
function setStyles(element, styles) {
for (i in styles)
element.style[i] = styles[i];
}
setStyles(document.getElementById("myElement"), allMyStyle);
Your best bet may be to create a function that sets styles on your own:
var setStyle = function(p_elem, p_styles)
{
var s;
for (s in p_styles)
{
p_elem.style[s] = p_styles[s];
}
}
setStyle(myDiv, {'color': '#F00', 'backgroundColor': '#000'});
setStyle(myDiv, {'color': mycolorvar, 'backgroundColor': mybgvar});
Note that you will still have to use the javascript-compatible property names (hence backgroundColor)
See for .. in
Example:
var myStyle = {};
myStyle.fontsize = "12px";
myStyle.left= "200px";
myStyle.top= "100px";
var elem = document.getElementById("myElement");
var elemStyle = elem.style;
for(var prop in myStyle) {
elemStyle[prop] = myStyle[prop];
}
This is old thread, so I figured for anyone looking for a modern answer, I would suggest using Object.keys();
var myDiv = document.getElementById("myDiv");
var css = {
"font-size": "14px",
"color": "#447",
"font-family": "Arial",
"text-decoration": "underline"
};
function applyInlineStyles(obj) {
var result = "";
Object.keys(obj).forEach(function (prop) {
result += prop + ": " + obj[prop] + "; ";
});
return result;
}
myDiv.style = applyInlineStyles(css);
Use CSSStyleDeclaration.setProperty() method inside the Object.entries of styles object.
We can also set the priority ("important") for CSS property with this.
We will use "hypen-case" CSS property names.
const styles = {
"font-size": "18px",
"font-weight": "bold",
"background-color": "lightgrey",
color: "red",
"padding": "10px !important",
margin: "20px",
width: "100px !important",
border: "1px solid blue"
};
const elem = document.getElementById("my_div");
Object.entries(styles).forEach(([prop, val]) => {
const [value, pri = ""] = val.split("!");
elem.style.setProperty(prop, value, pri);
});
<div id="my_div"> Hello </div>
There are scenarios where using CSS alongside javascript might make more sense with such a problem. Take a look at the following code:
document.getElementById("myElement").classList.add("newStyle");
document.getElementById("myElement").classList.remove("newStyle");
This simply switches between CSS classes and solves so many problems related with overriding styles. It even makes your code more tidy.
I think is this a very simple way with regards to all solutions above:
const elm = document.getElementById("myElement")
const allMyStyle = [
{ prop: "position", value: "fixed" },
{ prop: "boxSizing", value: "border-box" },
{ prop: "opacity", value: 0.9 },
{ prop: "zIndex", value: 1000 },
];
allMyStyle.forEach(({ prop, value }) => {
elm.style[prop] = value;
});
This is an old question but I thought it might be worthwhile to use a function for anyone not wanting to overwrite previously declared styles. The function below still uses Object.assign to properly fix in the styles. Here is what I did
function cssFormat(cssText){
let cssObj = cssText.split(";");
let css = {};
cssObj.forEach( style => {
prop = style.split(":");
if(prop.length == 2){
css[prop[0]].trim() = prop[1].trim();
}
})
return css;
}
Now you can do something like
let mycssText = "background-color:red; color:white;";
let element = document.querySelector("body");
Object.assign(element.style, cssFormat(mycssText));
You can make this easier by supplying both the element selector and text into the function and then you won't have to use Object.assign every time. For example
function cssFormat(selector, cssText){
let cssObj = cssText.split(";");
let css = {};
cssObj.forEach( style => {
prop = style.split(":");
if(prop.length == 2){
css[prop[0]].trim() = prop[1].trim();
}
})
element = document.querySelector(selector);
Object.assign(element.style, css); // css, from previous code
}
Now you can do:
cssFormat('body', 'background-color: red; color:white;') ;
//or same as above (another sample)
cssFormat('body', 'backgroundColor: red; color:white;') ;
Note: Make sure your document or target element (for example, body) is already loaded before selecting it.
You can write a function that will set declarations individually in order not to overwrite any existing declarations that you don't supply. Let's say you have this object parameter list of declarations:
const myStyles = {
'background-color': 'magenta',
'border': '10px dotted cyan',
'border-radius': '5px',
'box-sizing': 'border-box',
'color': 'yellow',
'display': 'inline-block',
'font-family': 'monospace',
'font-size': '20px',
'margin': '1em',
'padding': '1em'
};
You might write a function that looks like this:
function applyStyles (el, styles) {
for (const prop in styles) {
el.style.setProperty(prop, styles[prop]);
}
};
which takes an element and an object property list of style declarations to apply to that object. Here's a usage example:
const p = document.createElement('p');
p.textContent = 'This is a paragraph.';
document.body.appendChild(p);
applyStyles(p, myStyles);
applyStyles(document.body, {'background-color': 'grey'});
// styles to apply
const myStyles = {
'background-color': 'magenta',
'border': '10px dotted cyan',
'border-radius': '5px',
'box-sizing': 'border-box',
'color': 'yellow',
'display': 'inline-block',
'font-family': 'monospace',
'font-size': '20px',
'margin': '1em',
'padding': '1em'
};
function applyStyles (el, styles) {
for (const prop in styles) {
el.style.setProperty(prop, styles[prop]);
}
};
// create example paragraph and append it to the page body
const p = document.createElement('p');
p.textContent = 'This is a paragraph.';
document.body.appendChild(p);
// when the paragraph is clicked, call the function, providing the
// paragraph and myStyles object as arguments
p.onclick = (ev) => {
applyStyles(p, myStyles);
}
// this time, target the page body and supply an object literal
applyStyles(document.body, {'background-color': 'grey'});
With ES6+ you can use also backticks and even copy the css directly from somewhere:
const $div = document.createElement('div')
$div.innerText = 'HELLO'
$div.style.cssText = `
background-color: rgb(26, 188, 156);
width: 100px;
height: 30px;
border-radius: 7px;
text-align: center;
padding-top: 10px;
font-weight: bold;
`
document.body.append($div)
Please consider the use of CSS for adding style class and then add this class by JavaScript
classList & simply add() function.
style.css
.nice-style {
fontsize : 12px;
left: 200px;
top: 100px;
}
script JavaScript
const addStyle = document.getElementById("myElement");
addStyle.classList.add('nice-style');
<button onclick="hello()">Click!</button>
<p id="demo" style="background: black; color: aliceblue;">
hello!!!
</p>
<script>
function hello()
{
(document.getElementById("demo").style.cssText =
"font-size: 40px; background: #f00; text-align: center;")
}
</script>
We can add styles function to Node prototype:
Node.prototype.styles=function(obj){ for (var k in obj) this.style[k] = obj[k];}
Then, simply call styles method on any Node:
elem.styles({display:'block', zIndex:10, transitionDuration:'1s', left:0});
It will preserve any other existing styles and overwrite values present in the object parameter.
Is the below innerHtml valid
var styleElement = win.document.createElement("STYLE");
styleElement.innerHTML = "#notEditableVatDisplay {display:inline-flex} #editableVatInput,.print-section,i.fa.fa-sort.click-sortable{display : none !important}";
Different ways to achieve this:
1. document.getElementById("ID").style.cssText = "display:block; position:relative; font-size:50px";
2. var styles = {"display":"block"; "position":"relative"; "font-size":"50px"};
var obj = document.getElementById("ID");
Object.assign(obj.style, styles);
3. var obj = document.getElementById("ID");
obj.setAttribute("style", "display:block; position:relative; font-size:50px");
Hope this helps ~ RDaksh
var styles = {
"background-color": "lightgray",
"width": "500px",
"height": "300px"
};
/
var obj = document.getElementById("container");
Object.assign(obj.style, styles);