how can I determine that an element height is fixed - javascript

I need to know whether an HTML element will expand as the content is added to it. The height of the element can be preset in a number of ways - with the inline style height or max-height, by setting relative height when the parent element has its height set, via a css class, etc.
All I need to know whether the height of the element will increase as I add children. I hoped to use the JQuery css method, but it computes the actual value and does not tell me whether it will change as new children are added.

There are several ways to set a height of the element. Here is a test function you can use in order to determine if specified element has fixed height:
HTML
<span id="notAffected"></span>
<div id="hasCSSHeight"/>
<div id="hasInlineHeight" style="height:50px"/>
<div id="hasAttribureHeight" height="10px" />
<div id="hasNoHeight"/>
CSS
#notAffected,
#hasCSSHeight {
height: 100px;
}
JavaScript
function hasHeight(el) {
var i,
l,
rules = window.getMatchedCSSRules(el),
display = window.getComputedStyle(el).getPropertyValue('display');
// Inline displayed elements are not affected by height definition
if(display === 'inline') {
return false;
}
// CSS
if(rules) {
for(i=0,l=rules.length;i<l;i++) {
if(rules[i].style.getPropertyValue('height')) {
return true;
}
}
}
// Inline style
if(el.style.height) {
return true;
}
// Attribute
if(el.getAttribute('height')) {
return true;
}
return false;
}
Example see here http://jsbin.com/usojec/3/edit

Related

Bounding rect of HTML element within scrolling element

I'm interested in getting the bounding rect of a HTML element within an scrolling (overflow:auto) div container. I've tried getBoundingClientRect() but this is always relative to the window. A DOMRect is not needed, I just wanna know the width of the viewport and the position of the element.
So for me the only solution seems to be to subtract the rect of the scrolling div. But this could get complicated as my final use case is working with shadow DOM and custom components.
<div style="overflow:auto;height:100px;position:absolute;top:50px;">
<div id="elem">
some content
</div>
<div style="height:100px;">
ignore
</div>
<div>
ignore
</div>
<div>
ignore
</div>
</div>
<script>
window.alert("top="+document.getElementById("elem").getBoundingClientRect().top);
</script>
In this example you can see the outer most div has overflow set but the bounding rect does not show 0 before scrolling but 50.
Example: https://jsfiddle.net/nvemtoyk/
Found a workaround but with some caveats. First, you have to traverse all parent elements until you find the viewport. Secondy, It's only working if the overflow div was already scrolled.
At least in my case the second is true because the overflow style is not visible in javascript at my custom element. Maybe in "legacy" HTML this is not the case.
getViewport(elem) {
// root element
if (elem === document.body) {
return document.documentElement;
}
// scrolling element (only working if already scrolled)
// maybe elem.style.overflow is available, but not in my case
else if (elem.scrollLeft > 0 || elem.scrollTop > 0) {
return elem;
}
// traverse
else {
return getViewport(elem.offsetParent);
}
}
getBoundingRect(element, viewport) {
// root element
if (viewport === document.documentElement) {
return element.getBoundingClientRect();
}
// relative to viewport
else {
var elRect = element.getBoundingClientRect();
var vpRect = viewport.getBoundingClientRect();
return {
bottom: elRect.bottom - vpRect.top,
height: elRect.height,
left: elRect.left - vpRect.left,
right: elRect.right - vpRect.left,
top: elRect.top - vpRect.top,
width: elRect.width
};
}
}

Find div width that makes the text inside not wrapped

I built a CRM with some javascript to adjust the columns widths as the user wants, but I would like to have a button to automatically adjust the width of all column.
The idea is to check each div to verify if the text is wrapped and if so, increase the div width (within a given limit) or reduce in the opposite case. Something like that:
while(div.contentTextWrapped && parseInt(div.style.width)>50)
{
div.style.width=parseInt(div.style.width)-5+"px";
}
while(div.contentTextWrapped && parseInt(div.style.width)<500)
{
div.style.width=parseInt(div.style.width)+5+"px";
}
But I don't know such feature. Maybe I could set the white-space to nowrap and check the width but I need the content is not an element, or maybe I need to add a div inside and then I could check its width and compare ?
I think you have to calculate number of lines and then adjust width of object. There are a lot of ways to do that, here's one approach:
function findWidth(obj, minW, maxW) {
let lines, ref, lineHeight, wdt, dif=10, done=false;
// Get line height from myDummy
ref=document.getElementById('myDummy')
lineHeight=ref.offsetHeight;
if(lineHeight==0) return
// Assign min widht to start
wdt=minW;
obj.style.width=wdt+'px';
lines=Math.round(obj.offsetHeight/lineHeight);
while(lines>1) {
// Get current width and increase or assign max / min and exit
wdt=parseInt(obj.style.width);
if(wdt+dif>maxW) {
wdt=maxW;
done=true;
} else if(wdt<minW) {
wdt=minW;
done=true;
} else {
wdt+=dif;
}
obj.style.width=wdt+'px';
if(done) break;
lines=Math.round(obj.offsetHeight/lineHeight);
}
}
// Some tests...
findWidth(document.getElementById('myDiv1'), 25, 200);
findWidth(document.getElementById('myDiv2'), 25, 200);
findWidth(document.getElementById('myDiv3'), 25, 200);
#myDummy {
visibility: hidden;
}
div {
border: 1px solid crimson;
}
<div id="myDummy"> </div>
<div id="myDiv1">
This is some text...
</div>
<div id="myDiv2">
This is some text... with more and more and more and more and more...
</div>
<div id="myDiv3">
T...
</div>
You can try to find width of one character. then get whole text of your div and calculate total size of div:
const singleCharWidth = 3; // in px
const textLength = div.textContent.length;
div.style.width = `${textLength * singleCharWidth}px`;
If you want to read more about calculating text width you can read more about this here: Calculate text width with JavaScript

combine conditions if browser window is X height and element is scrolled to X point within

I've started with the below which works perfect, but I only need this to run and execute when my nav element .mainNav is scrolled to within a certain point within browser height.
#media screen and (max-height: 660px) {
.mainNav {
margin-top:-130px !important;
}
}
So detecting vertical browser height WITH scroll position within then chain .css with jQuery to. (margin-top:-100px)
Basically how to combine above parameter with below parameter. Below detects scroll position...
var $document = $(document),
$element = $('#some-element'),
className = 'hasScrolled';
$document.scroll(function() {
if ($document.scrollTop() >= 50) {
// user scrolled 50 pixels or more;
// do stuff
$element.addClass(className);
} else {
$element.removeClass(className);
}
});
You could do this by using the clientBoundingRect of the element. For example (untested, just theory);
var mainNav = document.getElementsByClassName('.mainNav')[0];
window.onscroll(function(e){
if(mainNav.clientBoundingRect().top <= 100 && window.height <= 660){
mainNav.style.marginTop = "-130px";
// or you could add a class here, as per the suggestion above, such as
// mainNav.setAttribute('class', 'mainNav locked');
}else{
mainNav.style.marginTop = "0";
// and remove it here
// mainNav.setAttribute('class', 'mainNav');
}
})
There is no visbility pseudo-selector in CSS, so you're looking at implementing this using JS handing of the visibilitychange event on your element, and then toggling the right (sequence of) class(es) through the element.classList interface, probably with transition rules in the CSS itself for the properties you want to be dynamic.

Can't get left position with global stylesheet in JavaScript

I need to get the upper left position of an image in JavaScript. I define the location of an image in a global style sheet:
<style type="text/css">
img.movable { position:relative; top:0px; left:375px; }
</style>
When I define the image using the global style
<img id="image11" class="movable" src="testimage.jpg" onclick="jump()" />
The style.left attribute is empty:
<script type="text/javascript">
function jump() {
xpos = document.getElementById("image11").style.left;
alert( "style.left="+xpos );
xpos = document.getElementById("image11").offsetLeft;
alert( "offsetLeft="+xpos );
}
</script>
But when I define the image using an inline style:
<img id="image11" style="position:relative; top:0px; left:375px;" src="logo.jpg" onclick="jump()" />
style.left contains a value.
This behaviour is the same for IE8 and Firefox. Any ideas why that is?
Cheers,
Martin.
el.style is actually a map of all the css properties applied using the style attribute. To get styles defined in stylesheets or default browser styles, you need to use computed style. Quirksmode, as usual, is a first stop.
The DOM element that represents the IMG tag you specified has its own style property, and its values will override any given by globals. Unfortunately in this case, the property of the element you specified will indeed be empty, as the values do not cascade down to the JavaScript object level.
You will need to get the position from either the offsetLeft property or the CSS rule itself.
.style properties only relate to inline css. Styles specified in a stylesheet will thus not be present in the .style list. If you want to get the position of an element on the page (as opposed to viewport) something like this should work:
function getNodePosition(node) {
var top = left = 0;
while (node) {
if (node.tagName) {
top = top + node.offsetTop;
left = left + node.offsetLeft;
node = node.offsetParent;
} else {
node = node.parentNode;
}
}
return [top, left];
}
Adapted from Quirksmode. OffsetTop and OffsetLeft are wrt to the parent, so this iterates up the tree to get the total offsets, and hence page position. If you want to know the position wrt the viewport, you can adjust the values returned here by the scroll distance.
Get Left Element of a given HTMLElement
function getHTMLElementLeft(HTMLElement, left)
{
if (left == undefined)
{
var left = 0;
}
if (HTMLElement.nodeType == 1)
{
left += HTMLElement.offsetLeft;
if (HTMLElement.offsetParent)
{
left = getHTMLElementLeft(HTMLElement.offsetParent, left);
}
}
return left;
}

Detecting width: auto in jQuery

I'm retrieving the width of elements using jQuery and would prefer it if I could have an indication of whether there was an explicit width (and height) specified.
<div id="test"></div>
<script type="text/javascript">
$(function() { alert($('#test').css('width')); });
</script>
This will alert the implicit width of the div in terms of how many pixels it takes up on the client's screen. Is there any way that if the width is either missing or set as width: auto that it can be verified using jQuery?
That is, instead of the above example returning an integer, it would return either auto or undefined. Or, alternatively, is there an equivalent of a isAuto function?
This will get either string "auto" or "180px" on absolute values.
$('element').prop('style').width
for width or
$('element').prop('style').height
for height.
I don't believe it's possible for the moment. At least not in any other browser than IE. IE implements element.currentStyle which represents styles at they were written in the CSS file. On the other hand, the rest of the browsers implement window.getComputedStyle which returns the computed values of those styles. That's what you receive there, a numeric value instead of auto.
The only way around it would be to parse CSS declarations from document.styleSheets.
References:
http://msdn.microsoft.com/en-us/library/ms535231(VS.85).aspx
https://developer.mozilla.org/en/DOM:window.getComputedStyle
https://developer.mozilla.org/en/CSS/computed_value
$('#test')[0].style.width=="auto" should work: http://jsfiddle.net/KxTLE/ and http://jsfiddle.net/KxTLE/1/
Try
jQuery.fn.isAuto=function() {
if(this[0]) {
var ele=$(this[0]);
if(this[0].style.width=='auto' || ele.outerWidth()==ele.parent().width()) {
return true;
} else {
return false;
}
}
return undefined;
};
And example: http://jsfiddle.net/KxTLE/6/
As far as I know, there is no native jQuery function to detect auto widths or heights. So I wrote a plugin to do it.
$.fn.isAuto = function(dimension){
if (dimension == 'width'){
var originalWidth = this.innerWidth();
var marginLeft = parseInt(this.css('margin-left'));
var testMarginWidth = marginLeft+50;
this.css('margin-left', testMarginWidth);
var newWidth = this.innerWidth();
this.css('margin-left', marginLeft);
if(newWidth<originalWidth){
return true;
}
else{
return false;
}
}
else if(dimension == 'height'){
var originalHeight = this.height();
this.append('<div id="test"></div>');
var testHeight = originalHeight+500;
$('#test').css({height: testHeight});
var newHeight = this.height();
$('#test').remove();
if(newHeight>originalHeight){
return true;
}
else{
return false;
}
}
};
Originally, I had written it to do height, so I just expanded it to include width. You just call it like this:
$('#element').isAuto('width');
or
$('#element').isAuto('height');
Here is a fiddle demonstrating the plugin's functionality.
I am not quite sure if I am answering your question correctly, but if you use the width() function this will give you an integer representing the rendered width in pixels.
create function
pass css element id to function
write a case where statement to be performed on the width property of the element id
NOTE: to use on mulitple elements would be wise to use a loop with an array of element names

Categories

Resources