Adjust a width based on parent w/ jQuery - javascript

I need to be able to adjust a width of a class based on a width of a parent. Currently .myClass has a width assigned in CSS. Would something like this work:
.myClass {
color: #000;
width:100px;
}
$(".myClass").width($(".myClass").parent().width());
This will be applied to a <DIV> and the parent could be a <TD> or another <DIV>.

What you have should work but I would probably change it to this:
$(".myClass").css("width",$(".myClass").parent().css("width"));
You might be able to use this instead of the second $(".myClass"), but you'd have to test that.
Keep in mind that it's not changing the class itself. It's changing the width of any element that uses that class.
UPDATE:
If you are going to be doing any sort of calculations with the parent width then you should probably stick with your original method. I like css when you are applying styles "as is" but that is a personal preference. If you are doing any kind of modifications to the parent value then width is probably better.
From the width documentation:
The .width() method is recommended
when an element's width needs to be
used in a mathematical calculation.

var parentW = $('.myClass').parent().width();
$('.myClass').width(parentW);
DEMO1
$('.myClass').width( $('.myClass').parent().width() );
DEMO2
And if you have more classes 'myClass':
$('.myClass').each(function() {
var myClass = $(this);
var parentW = myClass.parent().width();
myClass.width(parentW);
});
DEMO3
AND HERE IS ONE HARD CODED: (no javascript);)
DEMO4
And if you followed this song, here is the 'refrain': (the smart solution):
$('.myClass').css({width: 'auto'});
DEMO5

Related

Jquery detect if no width is set on an element [duplicate]

I have a stylesheet which defines default width for images. When I read the image width style with jQuery width() it returns the right width. It also returns the same width when I call css("width"). But if there is no width defined in the stylesheet the function css("width") will also return the computed width() value but won't say undefined or auto or something like that.
Any ideas how I could find out if style is or is not defined in the CSS code?
Solution works for me cross browser. Thanks to everyone for helping:
$(this).addClass("default_width_check");
var width = ($(this).width() == 12345) ? 'none-defined' : $(this).width();
var height = ($(this).height() == 12345) ? 'none-defined' : $(this).height();
$(this).removeClass("default_width_check");
.default_width_check {
width: 12345;
}
I have a workaround idea that might work.
Define a class named default_width before all other style sheets:
.default_width { width: 1787px }
/* An arbitrary value unlikely to be an image's width, but not too large
in case the browser reserves memory for it */
to find out whether an image has a width set:
Clone it in jQuery: element = $("#img").clone()
give the cloned element the default_width class: element.addClass("default_width")
If its width is 1787px, it has no width set - or, of course, is natively 1787px wide, which is the only case in which this method will not work.
I'm not entirely sure whether this will work, but it might. Edit: As #bobince points out in the comments, you will need to insert the element into the DOM for all classes to be applied correctly, in order to make a correct width calculation.
No, the getComputedStyle() method on which jQuery's css() function depends cannot distinguish between an width computed from auto vs explicit widths. You can't tell if there was something set in the stylesheet, only from direct inline style="width: ..." (which is reflected in the element's .style.width property).
currentStyle works differently and will give you auto, however this is a non-standard IE extension.
If you really wanted to work it out, you could iterate over document.styleSheets, reading each of their declarations, getting the selector out and querying it to see whether your target element matched, then seeing if it contains a width rule. This would, however, be slow and not at all fun, especially as IE's styleSheet DOM differs from the other browsers. (And it still wouldn't cope with pseudo-elements and pseudo-classes, like :hover.)
You can use image.style.width (image should be your element). This returns an empty string if it's not defined in CSS.
You can check the element's style.cssText if the width is defined;
<img id="pic" style="width:20px;" src="http://sstatic.net/ads/img/careers-ad-header-so.png" />
var pic = document.getElementById('pic');
alert(pic.style.cssText);
​But please note of the following styles
border-width: 10px;
width: 10px;
you should only match the width not the border-width.

How do I get the height of a textarea

I need to get the height of a textarea. Seemingly so simple but it's driving me mad.
I have been researching for ages on stackoverflow with no luck: textarea-value-height and jquery-js-get-the-scrollbar-height-of-an-textarea and javascript-how-to-get-the-height-of-text-inside-of-a-textarea, among many others.
This is how it looks currently:
This is how I want it to look, open a full height:
.
Here is my html:
<textarea id="history" class="input-xxlarge" placeholder="Enter the content ..." rows="13"></textarea>
CSS:
.input-xxlarge {
display: inline-block;
height: auto;
font-size: 12px;
width: 530px;
resize: none;
overflow: auto;
}
jQuery:
var textarea = $('#history');
I've tried (inter alia):
1. textarea.height() --> always returns 0
2. textarea.ready(function() { // wait for DOM to load
textarea.height();
}
3. getting scrollheight from textarea as an HTMLTextareaElement (i.e. DOM Element) --> returns 0
4. var contentSpan = textarea.wrapInner('<span>');
var height = contentSpan.height(); --> always returns 0
Please help, I'm at my wit's end!
Ok, I've found a solution. Whether it's the best solution, I don't know, but it works and that, frankly, is all I care about, having spent almost a day on this issue.
Here it is for anyone who faces the same problem:
Select the textarea:
var textarea = $('#history');
Get the textarea's text:
var text = textarea.text();
Create a temporary div:
var div = $('<div id="temp"></div>');
Set the temp div's width to be the same as the textarea. Very important else the text will be all on one line in the new temp div!:
div.css({
"width":"530px"
});
Insert the text into the new temp div:
div.text(text);
Append it to the DOM:
$('body').append(div);
Get the height of the div:
var divHeight = $('#temp').height();
Remove the temp div from the DOM:
div.remove();
Had a similar issue, in my case I wanted to have an expand button, that would toggle between two states (expanded/collapsed). After searching also for hours I finally came up with this solution:
Use the .prop to get the content height - works with dynamically filled textareas and then on a load command set it to your textarea.
Get the inner height:
var innerHeight = $('#MyTextarea').prop('scrollHeight');
Set it to your element
$('#MyTextarea').height(innerHeight);
Complete code with my expand button(I had min-height set on my textarea):
$(document).on("click", '.expand-textarea', function () {
$(this).toggleClass('Expanded');
if($(this).hasClass('Expanded'))
$($(this).data('target')).height(1);
else
$($(this).data('target')).height($($(this).data('target')).prop('scrollHeight'));
});
Modern answer: textarea sizing is a few lines of ES6 implementable two primary ways. It does not require (or benefit from) jQuery, nor does it require duplication of the content being sized.
As this is most often required to implement the functionality of auto-sizing, the code given below implements this feature. If your modal dialog containing the text area is not artificially constrained, but can adapt to the inner content size, this can be a perfect solution. E.g. don't specify the modal body's height and remove overflow-y directives. (Then no JS will be required to adjust the modal height at all.)
See the final section for additional details if you really, truly only actually need to fetch the height, not adapt the height of the textarea itself.
Line–Based
Pro: almost trivial. Pro: exploits existing user-agent behavior which does the heavy lifting (font metric calculations) for you. Con: impossible to animate. Con: extended to support constraints as per my codepen used to explore this problem, constraints are encoded into the HTML, not part of the CSS, as data attributes.
/* Lines must not wrap using this technique. */
textarea { overflow-x: auto; white-space: nowrap; resize: none }
for ( let elem of document.getElementsByTagName('textarea') ) {
// Prevent "jagged flashes" as lines are added.
elem.addEventListener('keydown', e => if ( e.which === 13 ) e.target.rows = e.target.rows + 1)
// React to the finalization of keyboard entry.
elem.addEventListener('keyup', e => e.target.rows = (elem.value.match(/\n/g) || "").length + 1)
}
Scrollable Region–Based
Pro: still almost trivial. Pro: animatable in CSS (i.e. using transition), though with some mild difficulty relating to collapsing back down. Pro: constraints defined in CSS through min-height and max-height. Con: unless carefully calculated, constraints may crop lines.
for ( let elem of document.getElementsByTagName('textarea') )
elem.addEventListener('keyup', e => {
e.target.style.height = 0 // SEE NOTE
e.target.style.height = e.target.scrollHeight + 'px'
})
A shocking percentage of the search results utilizing scrollHeight never consider the case of reducing size; for details, see below. Or they utilize events "in the wrong order" resulting in an apparent delay between entry and update, e.g. pressing enter… then any other key in order to update. Example.
Solution to Initial Question
The initial question specifically related to fetching the height of a textarea. The second approach to auto-sizing, there, demonstrates the solution to that specific question in relation to the actual content. scrollHeight contains the height of the element regardless of constraint, e.g. its inner content size.
Note: scrollHeight is technically the Math.max() of the element's outer height or the inner height, whichever is larger. Thus the initial assignment of zero height. Without this, the textarea would expand, but never collapse. Initial assignment of zero ensures you retrieve the actual inner content height. For sampling without alteration, remove the height override (assign '') or preserve (prior to) then restore after retrieval of scrolllHeight.
To calculate just the height of the element as-is, utilize getComputedStyle and parse the result:
parseInt(getComputedStyle(elem).height, 10)
But really, please consider just adjusting the CSS to permit the modal to expand naturally rather than involving JavaScript at all.
Place this BEFORE any HTML elements.
<script src="/path/to/jquery.js"></script>
<script>
$(document).ready(function(){
var textarea = $('#history');
alert(textarea.height()); //returns correct height
});
</script>
You obviously do not have to alert it. I was just using an easily visible example.
Given a textarea with an id of "history", this jQuery will return it's height:
$('#history').height()
Please see a working example at http://jsfiddle.net/jhfrench/JcGGR/
You can also retrieve the height in pixels by using $('#history').css('height'); if you're not planning on doing any calculations.
for current height in px:
height = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('height')
for current width in px:
width = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('width')
change 'textarea' to '#history' or like a css selector. or textarea, since a variable is declared to select element.

can not get the width of the html element

I create an element using js,and I have imported the related css,however I can not get the width of the element,this is the code:
css:
#mainDiv{
position:absolute;
width:500px;
height:500px;
}
js:
var mainDiv=document.createElement("div");
mainDiv.setAttribute("id","mainDiv");
document.body.appendChild(mainDiv);
//now I want to get the width of the 'mainDiv'
var wd=mainDiv.style.width;
console.info(wd);
However the value of the 'wd' is always ''.
I wonder why?
Using the firebug,I found that the width of the 'mainDiv' is 500px.
But why I can not get the value in the js?
I do not want to set the width and height of the 'mainDiv' in the js like:
mainDiv.style.width='500px';
I want to set the size in the css.
Any idea?
try
var wd=mainDiv.clientWidth;
Use mainDiv.offsetWidth .
Hope this helps.
Listen, this is an awful answer, but just use jQuery.
If you did this would be as simple as:
var width = $('#mainDiv').width(); // width has the value 500
Docs: http://api.jquery.com/width/
In order to get the actual width of a DOM element you must use offsetWidth.
From W3Schools:
offsetWidth: Returns the width of an element, including borders and padding if any, but not margins
This example should work:
var mainDiv=document.createElement("div");
mainDiv.setAttribute("id","mainDiv");
document.body.appendChild(mainDiv);
var wd=mainDiv.offsetWidth;
console.info(wd);
It's because the element is not yet rendered. I know it's awful, but you should delay reading the width a bit:
var mainDiv=document.createElement("div");
mainDiv.setAttribute("id","mainDiv");
document.body.appendChild(mainDiv);
setTimeout(100, function() {
console.info(mainDiv.style.width);
});
You cannot get the width because you are trying to get it from the style. Sorry went into train, basically because you are not setting the style element but rather defining a class - JavaScript can't read the value from the element.

jQuery/Javascript css("width") / check if style is defined in css?

I have a stylesheet which defines default width for images. When I read the image width style with jQuery width() it returns the right width. It also returns the same width when I call css("width"). But if there is no width defined in the stylesheet the function css("width") will also return the computed width() value but won't say undefined or auto or something like that.
Any ideas how I could find out if style is or is not defined in the CSS code?
Solution works for me cross browser. Thanks to everyone for helping:
$(this).addClass("default_width_check");
var width = ($(this).width() == 12345) ? 'none-defined' : $(this).width();
var height = ($(this).height() == 12345) ? 'none-defined' : $(this).height();
$(this).removeClass("default_width_check");
.default_width_check {
width: 12345;
}
I have a workaround idea that might work.
Define a class named default_width before all other style sheets:
.default_width { width: 1787px }
/* An arbitrary value unlikely to be an image's width, but not too large
in case the browser reserves memory for it */
to find out whether an image has a width set:
Clone it in jQuery: element = $("#img").clone()
give the cloned element the default_width class: element.addClass("default_width")
If its width is 1787px, it has no width set - or, of course, is natively 1787px wide, which is the only case in which this method will not work.
I'm not entirely sure whether this will work, but it might. Edit: As #bobince points out in the comments, you will need to insert the element into the DOM for all classes to be applied correctly, in order to make a correct width calculation.
No, the getComputedStyle() method on which jQuery's css() function depends cannot distinguish between an width computed from auto vs explicit widths. You can't tell if there was something set in the stylesheet, only from direct inline style="width: ..." (which is reflected in the element's .style.width property).
currentStyle works differently and will give you auto, however this is a non-standard IE extension.
If you really wanted to work it out, you could iterate over document.styleSheets, reading each of their declarations, getting the selector out and querying it to see whether your target element matched, then seeing if it contains a width rule. This would, however, be slow and not at all fun, especially as IE's styleSheet DOM differs from the other browsers. (And it still wouldn't cope with pseudo-elements and pseudo-classes, like :hover.)
You can use image.style.width (image should be your element). This returns an empty string if it's not defined in CSS.
You can check the element's style.cssText if the width is defined;
<img id="pic" style="width:20px;" src="http://sstatic.net/ads/img/careers-ad-header-so.png" />
var pic = document.getElementById('pic');
alert(pic.style.cssText);
​But please note of the following styles
border-width: 10px;
width: 10px;
you should only match the width not the border-width.

jQuery: Get height of hidden element in jQuery

I need to get height of an element that is within a div that is hidden. Right now I show the div, get the height, and hide the parent div. This seems a bit silly. Is there a better way?
I'm using jQuery 1.4.2:
$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
You could do something like this, a bit hacky though, forget position if it's already absolute:
var previousCss = $("#myDiv").attr("style");
$("#myDiv").css({
position: 'absolute', // Optional if #myDiv is already absolute
visibility: 'hidden',
display: 'block'
});
optionHeight = $("#myDiv").height();
$("#myDiv").attr("style", previousCss ? previousCss : "");
I ran into the same problem with getting hidden element width, so I wrote this plugin call jQuery Actual to fix it. Instead of using
$('#some-element').height();
use
$('#some-element').actual('height');
will give you the right value for hidden element or element has a hidden parent.
Full documentation please see here. There is also a demo include in the page.
Hope this help :)
You are confuising two CSS styles, the display style and the visibility style.
If the element is hidden by setting the visibility css style, then you should be able to get the height regardless of whether or not the element is visible or not as the element still takes space on the page.
If the element is hidden by changing the display css style to "none", then the element doesn't take space on the page, and you will have to give it a display style which will cause the element to render in some space, at which point, you can get the height.
I've actually resorted to a bit of trickery to deal with this at times. I developed a jQuery scrollbar widget where I encountered the problem that I don't know ahead of time if the scrollable content is a part of a hidden piece of markup or not. Here's what I did:
// try to grab the height of the elem
if (this.element.height() > 0) {
var scroller_height = this.element.height();
var scroller_width = this.element.width();
// if height is zero, then we're dealing with a hidden element
} else {
var copied_elem = this.element.clone()
.attr("id", false)
.css({visibility:"hidden", display:"block",
position:"absolute"});
$("body").append(copied_elem);
var scroller_height = copied_elem.height();
var scroller_width = copied_elem.width();
copied_elem.remove();
}
This works for the most part, but there's an obvious problem that can potentially come up. If the content you are cloning is styled with CSS that includes references to parent markup in their rules, the cloned content will not contain the appropriate styling, and will likely have slightly different measurements. To get around this, you can make sure that the markup you are cloning has CSS rules applied to it that do not include references to parent markup.
Also, this didn't come up for me with my scroller widget, but to get the appropriate height of the cloned element, you'll need to set the width to the same width of the parent element. In my case, a CSS width was always applied to the actual element, so I didn't have to worry about this, however, if the element doesn't have a width applied to it, you may need to do some kind of recursive traversal of the element's DOM ancestry to find the appropriate parent element's width.
Building further on user Nick's answer and user hitautodestruct's plugin on JSBin, I've created a similar jQuery plugin which retrieves both width and height and returns an object containing these values.
It can be found here:
http://jsbin.com/ikogez/3/
Update
I've completely redesigned this tiny little plugin as it turned out that the previous version (mentioned above) wasn't really usable in real life environments where a lot of DOM manipulation was happening.
This is working perfectly:
/**
* getSize plugin
* This plugin can be used to get the width and height from hidden elements in the DOM.
* It can be used on a jQuery element and will retun an object containing the width
* and height of that element.
*
* Discussed at StackOverflow:
* http://stackoverflow.com/a/8839261/1146033
*
* #author Robin van Baalen <robin#neverwoods.com>
* #version 1.1
*
* CHANGELOG
* 1.0 - Initial release
* 1.1 - Completely revamped internal logic to be compatible with javascript-intense environments
*
* #return {object} The returned object is a native javascript object
* (not jQuery, and therefore not chainable!!) that
* contains the width and height of the given element.
*/
$.fn.getSize = function() {
var $wrap = $("<div />").appendTo($("body"));
$wrap.css({
"position": "absolute !important",
"visibility": "hidden !important",
"display": "block !important"
});
$clone = $(this).clone().appendTo($wrap);
sizes = {
"width": $clone.width(),
"height": $clone.height()
};
$wrap.remove();
return sizes;
};
Building further on Nick's answer:
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").css({'position':'static','visibility':'visible', 'display':'none'});
I found it's better to do this:
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").removeAttr('style');
Setting CSS attributes will insert them inline, which will overwrite any other attributes you have in your CSS file. By removing the style attribute on the HTML element, everything is back to normal and still hidden, since it was hidden in the first place.
You could also position the hidden div off the screen with a negative margin rather than using display:none, much like a the text indent image replacement technique.
eg.
position:absolute;
left: -2000px;
top: 0;
This way the height() is still available.
I try to find working function for hidden element but I realize that CSS is much complex than everyone think. There are a lot of new layout techniques in CSS3 that might not work for all previous answers like flexible box, grid, column or even element inside complex parent element.
flexibox example
I think the only sustainable & simple solution is real-time rendering. At that time, browser should give you that correct element size.
Sadly, JavaScript does not provide any direct event to notify when element is showed or hidden. However, I create some function based on DOM Attribute Modified API that will execute callback function when visibility of element is changed.
$('[selector]').onVisibleChanged(function(e, isVisible)
{
var realWidth = $('[selector]').width();
var realHeight = $('[selector]').height();
// render or adjust something
});
For more information, Please visit at my project GitHub.
https://github.com/Soul-Master/visible.event.js
demo: http://jsbin.com/ETiGIre/7
Following Nick Craver's solution, setting the element's visibility allows it to get accurate dimensions. I've used this solution very very often. However, having to reset the styles manually, I've come to find this cumbersome, given that modifying the element's initial positioning/display in my css through development, I often forget to update the related javascript code. The following code doesn't reset the styles per say, but removes the inline styles added by javascript:
$("#myDiv")
.css({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
optionHeight = $("#myDiv").height();
optionWidth = $("#myDiv").width();
$("#myDiv").attr('style', '');
The only assumption here is that there can't be other inline styles or else they will be removed aswell. The benefit here, however, is that the element's styles are returned to what they were in the css stylesheet. As a consequence, you can write this up as a function where an element is passed through, and a height or width is returned.
Another issue I've found of setting the styles inline via js is that when dealing with transitions through css3, you become forced to adapt your style rules' weights to be stronger than an inline style, which can be frustrating sometimes.
By definition, an element only has height if it's visible.
Just curious: why do you need the height of a hidden element?
One alternative is to effectively hide an element by putting it behind (using z-index) an overlay of some kind).
In my circumstance I also had a hidden element stopping me from getting the height value, but it wasn't the element itself but rather one of it's parents... so I just put in a check for one of my plugins to see if it's hidden, else find the closest hidden element. Here's an example:
var $content = $('.content'),
contentHeight = $content.height(),
contentWidth = $content.width(),
$closestHidden,
styleAttrValue,
limit = 20; //failsafe
if (!contentHeight) {
$closestHidden = $content;
//if the main element itself isn't hidden then roll through the parents
if ($closestHidden.css('display') !== 'none') {
while ($closestHidden.css('display') !== 'none' && $closestHidden.size() && limit) {
$closestHidden = $closestHidden.parent().closest(':hidden');
limit--;
}
}
styleAttrValue = $closestHidden.attr('style');
$closestHidden.css({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
contentHeight = $content.height();
contentWidth = $content.width();
if (styleAttrValue) {
$closestHidden.attr('style',styleAttrValue);
} else {
$closestHidden.removeAttr('style');
}
}
In fact, this is an amalgamation of Nick, Gregory and Eyelidlessness's responses to give you the use of Gregory's improved method, but utilises both methods in case there is supposed to be something in the style attribute that you want to put back, and looks for a parent element.
My only gripe with my solution is that the loop through the parents isn't entirely efficient.
One workaround is to create a parent div outside the element you want to get the height of, apply a height of '0' and hide any overflow. Next, take the height of the child element and remove the overflow property of the parent.
var height = $("#child").height();
// Do something here
$("#parent").append(height).removeClass("overflow-y-hidden");
.overflow-y-hidden {
height: 0px;
overflow-y: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent" class="overflow-y-hidden">
<div id="child">
This is some content I would like to get the height of!
</div>
</div>
Here's a script I wrote to handle all of jQuery's dimension methods for hidden elements, even descendants of hidden parents. Note that, of course, there's a performance hit using this.
// Correctly calculate dimensions of hidden elements
(function($) {
var originals = {},
keys = [
'width',
'height',
'innerWidth',
'innerHeight',
'outerWidth',
'outerHeight',
'offset',
'scrollTop',
'scrollLeft'
],
isVisible = function(el) {
el = $(el);
el.data('hidden', []);
var visible = true,
parents = el.parents(),
hiddenData = el.data('hidden');
if(!el.is(':visible')) {
visible = false;
hiddenData[hiddenData.length] = el;
}
parents.each(function(i, parent) {
parent = $(parent);
if(!parent.is(':visible')) {
visible = false;
hiddenData[hiddenData.length] = parent;
}
});
return visible;
};
$.each(keys, function(i, dimension) {
originals[dimension] = $.fn[dimension];
$.fn[dimension] = function(size) {
var el = $(this[0]);
if(
(
size !== undefined &&
!(
(dimension == 'outerHeight' ||
dimension == 'outerWidth') &&
(size === true || size === false)
)
) ||
isVisible(el)
) {
return originals[dimension].call(this, size);
}
var hiddenData = el.data('hidden'),
topHidden = hiddenData[hiddenData.length - 1],
topHiddenClone = topHidden.clone(true),
topHiddenDescendants = topHidden.find('*').andSelf(),
topHiddenCloneDescendants = topHiddenClone.find('*').andSelf(),
elIndex = topHiddenDescendants.index(el[0]),
clone = topHiddenCloneDescendants[elIndex],
ret;
$.each(hiddenData, function(i, hidden) {
var index = topHiddenDescendants.index(hidden);
$(topHiddenCloneDescendants[index]).show();
});
topHidden.before(topHiddenClone);
if(dimension == 'outerHeight' || dimension == 'outerWidth') {
ret = $(clone)[dimension](size ? true : false);
} else {
ret = $(clone)[dimension]();
}
topHiddenClone.remove();
return ret;
};
});
})(jQuery);
If you've already displayed the element on the page previously, you can simply take the height directly from the DOM element (reachable in jQuery with .get(0)), since it is set even when the element is hidden:
$('.hidden-element').get(0).height;
same for the width:
$('.hidden-element').get(0).width;
(thanks to Skeets O'Reilly for correction)

Categories