Get target style from Javascript while transitioning - javascript

During a transition, is there a way to see what the target value is for a style rule which is under transition? window.getComputedStyle gets the interpolated value, and element.style only looks at the style attribute (I think).
Here's a demo of the problem;
I'd like to retrieve the target height value of 1200px during the transition:
https://jsfiddle.net/EoghanM/xz5s3ua6/5/
setInterval(function() {
document.body.children[0].innerHTML = getComputedStyle(document.body.children[0])['height']
}, 300)
setTimeout(function() {
document.body.children[0].classList.toggle('changing')
}, 1000)
div {
height: 400px;
border: 1px solid red;
width: 200px;
transition: height 100s linear;
}
div.changing {
height: 1200px;
}
<div></div>

How about using getComputedStyle on a new instance of changing class?
You can create a div with the class changing and then use getComputedStyle to get the class properties (considering that the height of changing class will be the final height after the transition of your div) like this:
<div class="changing" id="new-changing-div"></div>
and get it's properties:
const element = document.querySelector('#new-changing-div');
const heightAttribute = window.getComputedStyle(element).getPropertyValue('height');

I'm 99% sure all of the DOM properties and methods for requesting the element's height (clientHeight, offsetHeight, getBoundingClientRect, etc.) will only give you the interpolated value. Another solution may be to read the value from the CSS stylehseet itself using the CSSOM.
In the code below, we search through the document's stylesheets checking if the selector exists in a rule declaration and if it does, return the value of the property we're looking for. You can console.log() various parts of the stylesheets and rules below to see how the browser stores the information as objects.
Of course this is a simple example based on a simple test case. There could be multiple rules using the same selector, but this will only find the first occurrence. The solution would need to be more robust to find the exact rule you're looking for.
function getCssRuleValue(selector, property) {
const styleSheets = document.styleSheets;
let styleSheetsLen = styleSheets.length;
while (styleSheetsLen--) {
const styleSheet = styleSheets[styleSheetsLen];
const rules = styleSheet.rules;
let rulesLen = rules.length;
while (rulesLen--) {
const rule = rules[rulesLen];
// The passed-in selector text is found in the rule text
if (rule.cssText.indexOf(selector) > -1) {
return rule.style[property];
}
}
}
// The selector/property was not found in any document stylesheets
return -1;
}
setInterval(function() {
document.body.children[0].innerHTML =
getComputedStyle(document.body.children[0])['height']
+ '<br>' +
getCssRuleValue('.changing', 'height')
}, 300)
setTimeout(function() {
document.body.children[0].classList.toggle('changing')
}, 1000)
div {
height: 400px;
border: 1px solid red;
width: 200px;
transition: height 100s linear;
}
div.changing {
height: 1200px;
}
<div></div>

Related

why v-bind:style is not reacting to changes if the data is set to a false value (null, false, undefined etc.) [duplicate]

How to I reset the max-height property to its default, if it has been previously set in some CSS rule? This doesn't work:
pre {
max-height: 250px;
}
pre.doNotLimitHeight {
max-height: auto; // Doesn't work at least in Chrome
}
Reset it to none:
pre {
max-height: 250px;
}
pre.doNotLimitHeight {
max-height: none;
}
Reference
You can clear the max-height attribute by using the following css:
max-height:none;
You can use
max-height: unset;
which resets a property to its inherited value if you are inheriting from its parent (will work as keyword inherit) and in case you are not inheriting it will resets to its initial value ( will work as keyword initial).
Just a note, if you're using JavaScript to style the element like $el.style.maxHeight = '50px'; using $el.style.maxHeight = 'none'; will not "reset" or "remove" the 50px, it will simply override it. This means that if you try to "reset" the max height of an element using $el.style.maxHeight = 'none'; it will apply the none value to the max-height property of the element, overriding any other valid max-height properties in CSS selection rules that match that element.
An example:
styles.css
.set-max-height { max-height: 50px; }
main.js
document.querySelectorAll('.set-max-height').forEach($el => {
if($el.hasAttribute('data-hidden')){
$el.style.maxHeight = '0px'; // Set max-height to 0px.
} else {
$el.style.maxHeight = 'none'; // 'Unset' max-height according to accepted answer.
});
To actually "unset" an inline style, you should use $el.style.removeProperty('max-height');.
To complete this for an entire style rule and not just a single element, you should first find the rule you want to modify, and then call the removeProperty function on that rule:
for(let i = 0; i < document.styleSheets[0].cssRules.length; ++i){
if(document.styleSheets[0].cssRules[i].selectorText == '.set-max-height'){
document.styleSheets[0].cssRules[i].style.removeProperty('max-height');
break;
}
}
You can find the StyleSheet and CssRule objects however you want, but for a simple application I'm sure the above would suffice.
Sorry for putting this as an answer, but I don't have 50 rep so I can't comment.
Cheers.
Use either
max-height: none;
or
max-height: 100%;
Note: the second one is relative to the height of the containing block.

Set height of a div in vue js

I am using vue js . I want to set one div based on another div height, with pure javascript. the problem I am facing is I can't set the height using pure java script. but I can set it using jquery. can any one please help me to change this jquery to javascript . the code I am using is given
Vue.nextTick(function () {
var offsetHeight = document.getElementById('filterSection').offsetHeight;
$(".searchResultSection").css("max-height",`calc(100% - ${offsetHeight}px)`);
});
I need to change the jquery part into java script.
In fact, computed properties (https://v2.vuejs.org/v2/guide/computed.html#Computed-Properties) is the perfect option to solves your problem:
Declare a computed property who will return the filterSectionHeight
export default {
name: "App",
computed: {
filterSectionHeight() {
const filterSectionDOM = document.getElementById("filterSection");
return filterSectionDOM ? filterSectionDOM.offsetHeight : 0;
},
}
};
Define your div filterSection and searchResultsSection in your component (or App component), don't forget to add a :style attribute who handle the dynamic max-height provided to .searchResultsSection in your template
<div id="filterSection"></div>
<div class="searchResultsSection"
:style="{
'max-height': `calc(100% - ${filterSectionHeight}px)`
}">
</div>
Set height of each div to 100% in your css
#app {
height: 600px;
width: 100%;
}
#filterSection {
height: 100%;
background: rebeccapurple; //https://en.wikipedia.org/wiki/Eric_A._Meyer
}
.searchResultsSection{
height: 100%;
background: rebeccapurple;
opacity: 0.6;
}
You will find a full demo here > https://codesandbox.io/s/1rkmwo1wq
Not sure about the context of this change, but I'll try to give you some solutions based on best practices on how to achieve that:
If parent element has a fixed height, then children with height: 100% will adopt parents height.
.parent {
height: 200px;
}
.child {
height: 100%;
}
Use a vue-directive for DOM manipulation: https://v2.vuejs.org/v2/guide/custom-directive.html
Use v-bind:style="height: calc(100% - ${offsetHeight}px)\" on the element that you want to achieve the height!
You need to use the javascript DOM-style to do this.
Try this.
Vue.nextTick(function () {
var offsetHeight = document.getElementById('filterSection').offsetHeight;
var x = document.getElementsByClassName("searchResultSection");
x[0].style.maxHeight = "calc(100% - ${offsetHeight}px)";
});

Why is the scrollWidth of a valid text area undefined?

I have found many answers suggesting I use scrollWidth and scrollHeight to get the content width and height, respectively, of a text area. However, my code returns the scrollWidth as undefined. Any idea why this could be the case?
function changewidth(o) {
if ($(o).val().length>8)
{
var current = $(o).css("width");
console.log($(".name").scrollWidth+'px');
$(o).css("width",$(".name").scrollWidth+'px');
}
}
And this javascript function is being called by this text area:
<textarea rows="1" onkeyup="changewidth(this)" class="name" type="textarea" placeholder="name"></textarea>
The console prints undefinedpx. Based on research, I have tried to alter the CSS and currently have the following:
.name {
width: 100px;
margin: 0;
padding: 0;
border: none;
font-size: 20px;
color: #00B45E;
resize: none;
overflow: hidden;
}
You have to try this, No need to wrap currently passed object into $() unless you need it.
function changewidth(o) {
if ($(o).val().length > 8) {
var current = $(o).css("width");
console.log(o.scrollWidth + 'px'); // o.scrollWidth
$(o).css("width", o.scrollWidth + 'px'); // use object as o direclty
}
}
With pure Javascript
function changewidth(o) {
if (o.value.length>8)
{
var current = o.style.width;
console.log(o.scrollWidth+'px');
o.style.width = o.scrollWidth+'px';
}
}
Fiddle
With pure javascript
Demo
scrollWidth
scrollWidth only applies to plain Javascript, it seems you are using it on jQuery.
instead of $(".name").scrollWidth try changing it to document.getElementsByClassName("name").scrollWidth

Why can't I use jQuery prop to get the CSS setting?

In the HTML file, I have created a DOM element:
<div id="colorOne"></div>
and I set the attributes in css file:
#colorOne{
position: absolute;
top: 70%;
left: 8%;
width: 36px;
height: 36px;
border-color: black;
border-width: 5px;
border-style: solid;
background-color: white;
}
However, as I command
$('#colorOne').prop('width'); $('#colorOne').prop('height');
If I want to get any attribute of the element colorOne by $.prop, it only shows undefined. But I also noticed that if I change prop to css and I can get what I want.
And if I write
<div id="colorOne" style="width:36px;"></div>
And the $.prop works.
I want to know why is that. How does the browser engine handle these two different writing methods?
(1. inline style 2. setting the attributes in .css file)
If you want to get the final, computed style with jQuery you need to use .css().
This uses getComputedStyle internally so you can use it with styles from several different sources.
Here is what jQuery does internally to do this:
function (elem, name) {
var ret, defaultView, computedStyle, width, style = elem.style;
name = name.replace(rupper, "-$1").toLowerCase();
if ((defaultView = elem.ownerDocument.defaultView) && (computedStyle = defaultView.getComputedStyle(elem, null))) {
ret = computedStyle.getPropertyValue(name);
if (ret === "" && !jQuery.contains(elem.ownerDocument.documentElement, elem)) {
ret = jQuery.style(elem, name);
}
}
// A tribute to the "awesome hack by Dean Edwards"
// WebKit uses "computed value (percentage if specified)" instead of "used value" for margins
// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
if (!jQuery.support.pixelMargin && computedStyle && rmargin.test(name) && rnumnonpx.test(ret)) {
width = style.width;
style.width = ret;
ret = computedStyle.width;
style.width = width;
}
return ret;
}
When you perform a .attr or .prop call you're reading an HTML attribute/property and not a style. If you read the style attribute you're only getting that and not the actual computed style from all the stylesheets etc.
css is what you want.
Try:
$('#colorOne').css('width');
$('#colorOne').css('height');
$.prop is use to access attributes like name, href, etc.
If you still want to use prop, you will have to set width, height attributes in html elements.
<div id="colorOne" width='36px'></div>
$('#colorOne').prop('width');
The above works because, width is an attribute to the element #colorOne.
If width of the element is changed by js or css(using !important) in anyway, $.prop will give you wrong answer. But $.css will give you the correct one.

Class CSS property return

How would one return a class computed CSS property/property array?
Like, if I have a class defined in CSS:
.global {
background-color: red;
color: white;
text-shadow: 0px 1px 1px black;
}
It's applied on the go with javascript to an element. Now I want to change this elements childrens' color to parents' (.global) element background-color.
And is there a way to read CSS properties from a previously defined class in a style tag or externally included *.css?
Something like, getCSSData([span|.global|div > h1]); (where the passed variable is a CSS selector, that gets data for exactly matching element) that would return an object with each property in it's own accessible variable?
Something like:
cssdata = {
selector : '.global',
properties : {
backgroundColor : 'red',
color : 'white',
textShadow : '0px 1px 1px black'
// plus inherited, default ones (the ones specified by W3..)
}
}
And the usage for my previously explained example would be:
// just an example to include both, jQuery usage and/or native javascript
var elements = $('.global').children() || document.getElementsByClassName('.global')[0].children;
var data = $('.global').getCSSData() || document.getCSSData('.global');
return elements.css('color', data.properties.backgroundColor) || elements.style.backgroundColor = data.properties.backgroundColor;
Is there a function built in already in javascript/jquery and I've overlooked it?
If not, what should I look for to make one?
P.S. Can be DOM Level 3 too.. (HTML5'ish..)
If you want to grab the background color of the parent element and then apply that color to the font of all of it's children you could use the following code.
$(document).ready(function(){
var global = $('.global');
var bgColor = global.css('background-color');
global.children().css('color', bgColor);
};
Here's an example on jsFiddle.net
You can access the computedStyle of an element which includes all inherited style values, here is a example that outputs the computed style of a div element in the console.
<script type="text/javascript">
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", listComputedStyles, false);
}
function listComputedStyles() {
var element = document.getElementById("myDiv");
var properties = window.getComputedStyle(element, null);
for (var i = 0; i < properties.length; i++)
{
var value = window.getComputedStyle(element, null).getPropertyValue(properties[i]);
console.log(properties[i], value);
}
}
</script>
<div id="myDiv" style="background-color: blue; height: 500px;"></div>
You can find more information here: http://help.dottoro.com/ljscsoax.php
If I understand your question correctly, you'd like to find a general approach to modifying a class; and to have that modifcation affect all of the instantiations of that class. This was the subject of another detailed discussion on SO over here.
There turned out to be an extremely interesting and useful treatment of classes that works in almost all browsers, notably excepting IE8 and below.

Categories