I'm trying to assign styles to an object. Initial code was
targetEl.style.top = `${top}px` ;
targetEl.style.display = 'block';
targetEl.style.background = `url(${this.props.imgSrc}) no-repeat`;
targetEl.style.backgroundSize = "1800px 900px";
I tried to use es6 destructuring and rewrote the code like this:
targetEl.style = {...targetEl.style,
top:`${top}px`,
display: 'block',
background: `url(${this.props.imgSrc}) no-repeat`,
backgroundSize: "1800px 900px" };
But for some reason it does not seem to work. What am I doing wrong?
You are not using destructuring, you are using experimental spread syntax in an object literal which creates a new object. You might be used to that when working with immutable data frameworks, but here you really want to assign properties of the targetEl.style CSS declaration object. You do not want to replace the whole .style object with a new one.
Try Object.assign with a plain literal:
Object.assign(targetEl.style, {
top: `${top}px`,
display: 'block',
background: `url(${this.props.imgSrc}) no-repeat`,
backgroundSize: '1800px 900px'
});
As a side note, it's a bit more efficient without Object.assign:
const s = targetEl.style;
s.top = `${top}px`;
s.display = 'block';
s.background = `url(${this.props.imgSrc}) no-repeat`;
s.backgroundSize = '1800px 900px';
but even more efficient to assign them all at once (How can I set multiple CSS styles in JavaScript?) :
targetEl.style.cssText += `; top = ${top}px, display = 'block',
background = url(${this.props.imgSrc}) no-repeat, backgroundSize = '1800px 900px'; `;
Related
I want to convert my node style attribute value to a js object which contains all the CSS properties and its values.
Style attribute value
background-image:url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=);background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%
Convert it to JS Object
{
backgroundImage: url(data;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=): undefined;
backgroundColor: #00cc7e;
backgroundSize: cover;
opacity: 1;
transition: opacity 500ms 500ms;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%
}
Any helpful answer will be appreciated.
You can try methods of CSSStyleDeclaration.
Here getStyles is of type CSSStyleDeclaration which will give list of inline style properties.
const getStyles = document.getElementById('img').style;
const properties = Array.from(getStyles).reduce((acc, curr) => {
acc[curr] = getStyles.getPropertyValue(curr)
return acc;
}, {})
console.log(properties)
<img id='img' style="background-image:url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=);background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%">
Well you can definitely do that by:
let element = document.querySelector("your-selector-here")
console.log(element.style)
But let me warn you that you'll get a very big object of css properties because your element has more css properties than what you define in you style-sheet.
Why you wanna do so ?
If its style of an element you can grab it by first selecting the element in your js and then getting style using element.style ,you can slect element by various methods such as by its ID, class etc. Tho this will give you all the element's style including the default one's.
console.log(document.querySelector('#test').style)
<div id="test"></div>
This shall be used in worst case scenario until you can filter the default one's.
If you have the style as a sting with you, and you want to convert it to object, you can use JSON.parse ,but before that you will have to convert you styles into object format, replace ';' with ',' and convert each individual key and value to string. This might not be easy.
const test = 'background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%';
var afterReplace = test.replaceAll(";", '","').replaceAll(":", '":"');
objectForm = JSON.parse('{"' + afterReplace + '"}')
console.log(objectForm)
Here add string value of the style in test from which we replace all ';' to '";"' and ':' to '":"' then we add {" and "} to both start and end, and finally parse it into a json object.
Though I would suggest you not to use it.
This answer is incorrect but I thought it was important to leave here. While it works fine in Chrome, it doesn't work in Firefox, where the CSS2Properties object they return don't have enumerable property.
This method goes through the computed style of the element, so it has some browser-specific values. element.style has all possible style attributes, so this filters out the empty ones and returns the balance as a javascript notation style object
let element = document.querySelector('#element');
let styleobj = Object.fromEntries(Object
.entries(element.style)
.filter(e => isNaN(e[0]) && e[1].trim())
)
let element = document.querySelector('#element');
let styleobj = Object.fromEntries(Object.entries(element.style).filter(e => isNaN(e[0]) && e[1].trim()))
console.log(styleobj)
<div id='element' style='background-image:url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=);background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%'></div>
I am creating a javascript class to handle SVG tags in HTML. (I know that there are plenty of classes that does this already but I did not succeed with transformations via svg.js. Also, I have made all the required functions to work and I just want to implement them as a class for syntactical ease.)
However, not being that familiar with javascript, I have trouble with a variable that is set to Undefined in my constructor:
class SLD {
constructor(container,x=1000, y=1000) {
this.ctn = document.getElementById(container);
this.svgobj = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
// Defining object attributes
var obj = {
'width': "1000",
'height': "1000",
'xmlns':"http://www.w3.org/2000/svg",
'version':"1.1",
'xmlns:xlink':"http://www.w3.org/1999/xlink"
};
// Setting attribute via for loop
for(prop in obj) {
this.svgobj.setAttribute(prop, obj[prop])
}
}
While trying to run it, I am returned the following error code:
How do I define the variable properly? I am using Chrome (version 83.0.4103.116) and the browser supports classes as far as I am noticed.
Let me know if I should provide any other relevant information.
I assume prop hasn't been declared yet so you'll need to use var.
for(var prop in obj) {
this.svgobj.setAttribute(prop, obj[prop])
}
You could try this:
for (const prop in obj) {
this.svgobj.setAttribute(prop, obj[prop]);
}
Variable declaration was your problem.
Your code could be optimized by replacing the for loop with:
Object.entries({
'width': "20",
'height': "20",
'xmlns':"http://www.w3.org/2000/svg",
'version':"1.1",
'xmlns:xlink':"http://www.w3.org/1999/xlink"
}).forEach(([prop,value])=>svgobj.setAttribute(prop, value));
I'm getting some weird behavior trying to implement a conditional for the style of items in Vuejs.
I have seen S.O. posts on how to implement a ternary, via both an interpolated string or a computed style object. I've tried both but neither works properly.
Given this div:
<div
:class="{'radar__container':true,'inactive':inactive}"
:style= "[inactive ? {getStyleRadarContainerInactive} : {getStyleRadarContainer}]"
>
I would implement this style:
computed: {
getStyleRadarContainer: function(){
let styleRadarContainer = {
left: this.radarItem.posX*100 + '%',
top: this.radarItem.posY*100 + '%',
transform: 'translate(-50%,-50%) scale(' + this.radarItem.scale + ')',
opacity: this.radarItem.opacity,
}
return styleRadarContainer;
},
getStyleRadarContainerInactive: function(){
let styleRadarContainerInactive= {
left: this.radarItem.posX*100 + '%',
top: this.radarItem.posY*100 + '%',
transform: 'translate(-50%,-50%) scale(0)',
opacity: this.radarItem.opacity,
}
return styleRadarContainerInactive;
},
}
This should make each of these items scale down (because of the scale(0) in opacity property),but instead the style attribute doesn't render at all. I also tried an inline ternary on the style prop (since that scale is the only thing that changes between the two properties:
transform: 'translate(-50%,-50%) ' + inactive ? 'scale(' + radarItem.scale + ')' : 'scale(0)',
What am I missing?
The style binding expects an object. By wrapping the ternary in square brackets, you're passing in an array containing an object, which is unnecessary. Also, you're wrapping the returned object on either side of the ternary in brackets, which is nesting them further. Removing those brackets will let the returned object can be handled in correctly:
<div
:class="{'radar__container':true,'inactive':inactive}"
:style= "inactive ? getStyleRadarContainerInactive : getStyleRadarContainer"
>
As a side note, if you add a variable containing an object to another object without specifying property name, the variable name is used as a property name.
var myObject = {
property: 'value'
};
$('#output').html(JSON.stringify({myObject}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="output"></div>
try to use condition in V-bind:style
v-bind:style= "[condition ? {style_A} : {style_B}]"
https://v2.vuejs.org/v2/guide/class-and-style.html
There should work if you use spread operator like this:
:style= "[inactive ? {...getStyleRadarContainerInactive} : {...getStyleRadarContainer}]"
Your solution did not work because you produced double curly brackets
:style="[{ obj: { styleObject }}]" // This won't work
You can either have an array containing styleObjects or only a styleObject.
E.g.
:style="[ { color: 'blue' } ]"
:style="{ color: 'blue' }"
I have a set of destructured variables that all have the same parent class. Is there a way to remove 'hollow-gallery-01' from each and add that to the destructuring process?
const [modal,ctrls,slides,close,images,arrows] =
[
document.querySelector('.hollow-gallery-01 .modal'),
document.querySelectorAll('.hollow-gallery-01 .control'),
document.querySelectorAll('.hollow-gallery-01 .slide'),
document.querySelector('.hollow-gallery-01 .close'),
document.querySelectorAll('.hollow-gallery-01 .img-wrap'),
document.querySelectorAll('.hollow-gallery-01 .arrow')
]
You could do
const [[modal], ctrls, slides, [close], images, arrows] = ["modal", "control", "slide", "close", "img-wrap", "arrow"].map(sel =>
document.querySelectorAll(".hollow-gallery-01 ." + sel)
);
to reduce the repetition.
That said, a better and more efficent approach (as also suggested by the other answers) is to use the selectors on the parent element, not document:
const gallery = document.querySelector('.hollow-gallery-01');
const modal = gallery.querySelector('.modal'),
ctrls = gallery.querySelectorAll('.control'),
slides = gallery.querySelectorAll('.slide'),
close = gallery.querySelector('.close'),
images = gallery.querySelectorAll('img-wrap'),
arrows = gallery.querySelectorAll('arrow');
This will work for you. console.log and html is for demo purposes.
var parentobj = document.getElementsByClassName("hollow-gallery-01")[0];
const [modal,ctrls,slides,close,images,arrows] =
[
parentobj.querySelector('.modal'),
parentobj.querySelectorAll('.control'),
parentobj.querySelectorAll('.slide'),
parentobj.querySelector('.close'),
parentobj.querySelectorAll('.img-wrap'),
parentobj.querySelectorAll('.arrow')
];
console.log(modal.innerHTML);
<div class="hollow-gallery-01">
<div class="modal">test</div>
</div>
It's not quite clear why you're using destructuring here rather than assigning the variables directly, but if you wanted to simplify the selectors you could get the parent class, and then use querySelector on that.
const parent = document.querySelector('.hollow-gallery-01');
const modal = parent.querySelector('.modal');
const controls = parent.querySelectorAll('.control');
etc.
I am looking for a way to retrieve the style from an element that has a style set upon it by the style tag.
<style>
#box {width: 100px;}
</style>
In the body
<div id="box"></div>
I'm looking for straight javascript without the use of libraries.
I tried the following, but keep receiving blanks:
alert (document.getElementById("box").style.width);
alert (document.getElementById("box").style.getPropertyValue("width"));
I noticed that I'm only able to use the above if I have set the style using javascript, but unable to with the style tags.
The element.style property lets you know only the CSS properties that were defined as inline in that element (programmatically, or defined in the style attribute of the element), you should get the computed style.
Is not so easy to do it in a cross-browser way, IE has its own way, through the element.currentStyle property, and the DOM Level 2 standard way, implemented by other browsers is through the document.defaultView.getComputedStyle method.
The two ways have differences, for example, the IE element.currentStyle property expect that you access the CCS property names composed of two or more words in camelCase (e.g. maxHeight, fontSize, backgroundColor, etc), the standard way expects the properties with the words separated with dashes (e.g. max-height, font-size, background-color, etc).
Also, the IE element.currentStyle will return all the sizes in the unit that they were specified, (e.g. 12pt, 50%, 5em), the standard way will compute the actual size in pixels always.
I made some time ago a cross-browser function that allows you to get the computed styles in a cross-browser way:
function getStyle(el, styleProp) {
var value, defaultView = (el.ownerDocument || document).defaultView;
// W3C standard way:
if (defaultView && defaultView.getComputedStyle) {
// sanitize property name to css notation
// (hypen separated words eg. font-Size)
styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
} else if (el.currentStyle) { // IE
// sanitize property name to camelCase
styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) {
return letter.toUpperCase();
});
value = el.currentStyle[styleProp];
// convert other units to pixels on IE
if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
return (function(value) {
var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
el.runtimeStyle.left = el.currentStyle.left;
el.style.left = value || 0;
value = el.style.pixelLeft + "px";
el.style.left = oldLeft;
el.runtimeStyle.left = oldRsLeft;
return value;
})(value);
}
return value;
}
}
The above function is not perfect for some cases, for example for colors, the standard method will return colors in the rgb(...) notation, on IE they will return them as they were defined.
I'm currently working on an article in the subject, you can follow the changes I make to this function here.
I believe you are now able to use Window.getComputedStyle()
Documentation MDN
var style = window.getComputedStyle(element[, pseudoElt]);
Example to get width of an element:
window.getComputedStyle(document.querySelector('#mainbar')).width
In jQuery, you can do alert($("#theid").css("width")).
-- if you haven't taken a look at jQuery, I highly recommend it; it makes many simple javascript tasks effortless.
Update
for the record, this post is 5 years old. The web has developed, moved on, etc. There are ways to do this with Plain Old Javascript, which is better.
Use getComputedStyle function, Computed style contains all the CSS properties set to an element. Even if do not set a property to an element. You will still find that property in the computed styles.
Example:
<style>
#Body_element {
color: green;
}
</style>
<body id="Body_element">
<script>
alert(getComputedStyle(Body_element).color)
</script>
</body>
This is a helper function if you want to get multiple style rules from the same element.
You pass it the element and the styles you want as arguments, and it will return their values
const convertRestArgsIntoStylesArr = ([...args]) => {
return args.slice(1);
}
const getStyles = function () {
const args = [...arguments];
const [element] = args;
let stylesProps = [...args][1] instanceof Array ? args[1] : convertRestArgsIntoStylesArr(args);
const styles = window.getComputedStyle(element);
const stylesObj = stylesProps.reduce((acc, v) => {
acc[v] = styles.getPropertyValue(v);
return acc;
}, {});
return stylesObj;
};
Now, you can use this function like this:
const styles = getStyles(document.body, "height", "width");
OR
const styles = getStyles(document.body, ["height", "width"]);