How to get margin value of a div in plain JavaScript? - javascript

I can get height in jQuery with
$(item).outerHeight(true);
but how do I with JS?
I can get the height of the li with
document.getElementById(item).offsetHeight
but i will always get "" when I try margin-top:
document.getElementById(item).style.marginTop

The properties on the style object are only the styles applied directly to the element (e.g., via a style attribute or in code). So .style.marginTop will only have something in it if you have something specifically assigned to that element (not assigned via a style sheet, etc.).
To get the current calculated style of the object, you use either the currentStyle property (Microsoft) or the getComputedStyle function (pretty much everyone else).
Example:
var p = document.getElementById("target");
var style = p.currentStyle || window.getComputedStyle(p);
display("Current marginTop: " + style.marginTop);
Fair warning: What you get back may not be in pixels. For instance, if I run the above on a p element in IE9, I get back "1em".
Live Copy | Source

Also, you can create your own outerHeight for HTML elements. I don't know if it works in IE, but it works in Chrome. Perhaps, you can enhance the code below using currentStyle, suggested in the answer above.
Object.defineProperty(Element.prototype, 'outerHeight', {
'get': function(){
var height = this.clientHeight;
var computedStyle = window.getComputedStyle(this);
height += parseInt(computedStyle.marginTop, 10);
height += parseInt(computedStyle.marginBottom, 10);
height += parseInt(computedStyle.borderTopWidth, 10);
height += parseInt(computedStyle.borderBottomWidth, 10);
return height;
}
});
This piece of code allow you to do something like this:
document.getElementById('foo').outerHeight
According to caniuse.com, getComputedStyle is supported by main browsers (IE, Chrome, Firefox).

I found something very useful on this site when I was searching for an answer on this question. You can check it out at http://www.codingforums.com/javascript-programming/230503-how-get-margin-left-value.html. The part that helped me was the following:
/***
* get live runtime value of an element's css style
* http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element
* note: "styleName" is in CSS form (i.e. 'font-size', not 'fontSize').
***/
var getStyle = function(e, styleName) {
var styleValue = "";
if (document.defaultView && document.defaultView.getComputedStyle) {
styleValue = document.defaultView.getComputedStyle(e, "").getPropertyValue(styleName);
} else if (e.currentStyle) {
styleName = styleName.replace(/\-(\w)/g, function(strMatch, p1) {
return p1.toUpperCase();
});
styleValue = e.currentStyle[styleName];
}
return styleValue;
}
////////////////////////////////////
var e = document.getElementById('yourElement');
var marLeft = getStyle(e, 'margin-left');
console.log(marLeft); // 10px
#yourElement {
margin-left: 10px;
}
<div id="yourElement"></div>

Here is my solution:
Step 1: Select the element
Step 2: Use getComputedStyle and provide the element to it
Step 3: Now access all the properties
const item = document.getElementbyId('your-element-id');
const style= getComputedStyle(item);
const itemTopmargin = style.marginTop;
console.log(itemTopmargin)
It will give you margin with px units like "16px" which you might not want.
You can extract the value using parseInt()
const marginTopNumber = parseInt(itemTopmargin)
console.log(marginTopNumber)
It will give you the numerical value only (without any units).

Related

Can't change html attribute via javascript

This is very odd, I'm getting videos via document.getElementsByTag('video') and I can't change their width nor any other value.
Here's the Javascript code I'm using -
window.onload = function() {
this.videos = document.getElementsByTagName('video');
var self = this;
for(var i=0;i<videos.length;i++) {
videos.item(i).addEventListener("loadedmetadata",
(function(index){
return function() {
console.log(self.videos[index].offsetWidth); //shows X
self.videos[index].offsetWidth = "480";
console.log(self.videos[index].offsetWidth); //shows X
}
})(i)
);
}
}
Example <video> tag -
<video><source src="videos/video_1.mp4" type="video/mp4"></video>
I have no idea what it is happening and I've never encountered such kind of problem.
Thanks
EDIT:
Using the setAttribute function just adds it to the live html, but the size isn't really changing
The offsetWidth is a read-only DOM property so you can not update it. However why not change the element width?
window.onload = function() {
this.videos = document.getElementsByTagName('video');
var self = this;
for(var i=0;i<videos.length;i++) {
videos.item(i).addEventListener("loadedmetadata",
(function(index){
return function() {
self.videos[index].width = "480";
}
})(i));
}
}
You can take into account the borders, paddings, margins...
Note there is a difference between three things you are conflating into one:
HTML attributes
DOM properties
CSS styles
This is an HTML attribute:
If you have a DOM element representing an HTML tag, you can modify the attributes like so:
var a = document.createElement('a')
a.setAttribute('href', "http://example.com")
This is a DOM property:
var a = document.createElement('a')
a.href = "http://example.com"
Note how a DOM property can be similarly named to an HTML attribute, but they are not the same thing. Oftentimes, changing an HTML attribute will modify the corresponding DOM property, but not vice versa. Also, not all attributes have matching properties, and so on.
CSS styles are accessed via the DOM property style(which corresponds to the HTML attribute style, but while the HTML attribute style is a string, the DOM property is an object):
var a = document.createElement('a');
a.style.width = "500px";
a.style.height = "20%";
There are HTML attributes "width" and "height", but their use is deprecated in favor of using styles. Also, "width" and "height" as HTML attributes can only be numerical values representing pixels - while a CSS style can be many variations(pixels, ems, percentages, etc)
In your specific case, just modify the width styling of your element to change its width.
Another thing in your code is the usage of this and self, which is entirely unneeded. this.videos is setting a property on the global object(window) for no reason. You can also avoid closing over the index property by using .bind():
window.onload = function() {
var videos = document.getElementsByTagName('video');
for (var i = 0; i < videos.length;i++) {
var video = videos.item(i);
video.addEventListener("loadedmetadata", (function () {
console.log(this.offsetWidth);
this.style.width = "480px";
console.log(this.offsetWidth);
}).bind(video));
}
}
Try using getAttribute and setAttribute, as in videos[index].setAttribute('offsetWidth', 480)
First off, this doesn't seem right:
for(var i=0;i<videos.length;i++) {
Shouldn't it be self.videos? Fix that.
Then, to change the video size, you can change the size of the element:
self.videos[index].width = "480";
or, even better, the CSS width:
self.videos[index].style.width = "480px";
The size of the video itself will automatically extend to the size of the video element.

Remove Style on Element

I was wondering if this is possible.
There's this element
<div id="sample_id" style="width:100px; height:100px; color:red;">
So I want to remove width:100px; and height:100px;
the result would be
<div id="sample_id" style="color:red;">
Any help would be apprreciated. :)
You can edit style with pure Javascript. No library needed, supported by all browsers except IE where you need to set to '' instead of null (see comments).
var element = document.getElementById('sample_id');
element.style.width = null;
element.style.height = null;
For more information, you can refer to HTMLElement.style documentation on MDN.
var element = document.getElementById('sample_id');
element.style.removeProperty("width");
element.style.removeProperty("height");
Use javascript
But it depends on what you are trying to do. If you just want to change the height and width, I suggest this:
{
document.getElementById('sample_id').style.height = '150px';
document.getElementById('sample_id').style.width = '150px';
}
TO totally remove it, remove the style, and then re-set the color:
getElementById('sample_id').removeAttribute("style");
document.getElementById('sample_id').style.color = 'red';
Of course, no the only question that remains is on which event you want this to happen.
Update: For a better approach, please refer to Blackus's answer in the same thread.
If you are not averse to using JavaScript and Regex, you can use the below solution to find all width and height properties in the style attribute and replace them with nothing.
//Get the value of style attribute based on element's Id
var originalStyle = document.getElementById('sample_id').getAttribute('style');
var regex = new RegExp(/(width:|height:).+?(;[\s]?|$)/g);
//Replace matches with null
var modStyle = originalStyle.replace(regex, "");
//Set the modified style value to element using it's Id
document.getElementById('sample_id').setAttribute('style', modStyle);
$("#sample_id").css({ 'width' : '', 'height' : '' });
You can simply set that style to [unset], It forces CSS to pretend that style was never assigned to the given element.
var element = document.getElementById('sample_id');
element.style.width = "unset";
element.style.height = "unset";
Specifying auto on width and height elements is the same as removing them, technically. Using vanilla Javascript:
images[i].style.height = "auto";
images[i].style.width = "auto";
Just use like this
$("#sample_id").css("width", "");
$("#sample_id").css("height", "");

Can you detect when a dom node's style is set to 'auto'?

With the example CSS:
.thing { height: auto }
and HTML:
<div class="thing">The quick brown fox jumps over a lazy dog.</div>
is it possible to detect that the height of .thing is set to 'auto'?
The following methods return values:
jQuery('.thing').height() // n
jQuery('.thing').css('height') // 'npx'
getComputedStyle(node).height // 'npx'
Is there any method that will tell me that the browser is calculating these values from 'auto'?
Yes there is a way, but it's not a funny one. What you have to do is:
Loop through all styletags and linked stylesheets.
Then get the selectorText for all cssRules in all style tags
styletag.sheet.cssRules.selectorText
or for IE < 9
styletag.styleSheet.cssRules.selectorText
Get all of your elements parents id, class and tagName to find out what possible ways for the tag to get the attribute.
Find all possible combinations that point towards your element in your
list of cssRules
check those cssRules at cssRules.style.width if it is auto.
or do it some reverse way and find all cssRules with style.width == 'auto'; either way its not something easy to get without a lot of code
jQuery('.thing').each(function (i,n){
console.log( $(n).style.height);// if not then just try to simply find the n.style.height
});
//this is another way // at least in ff it would work :)
window.document.styleSheets[0].cssRules[0].style.height
hope it helps, otherwise you have alot of digging to do :)
For the second option where you see [0] means you have to loop as there may be different file names, etc etc...
full example :
var ss = window.document.styleSheets;
for(i=0;i<ss.length;i++){
var rules = ss[i].cssRules;
for(j=0;j<rules.length;j++){//loop style sheets
var rule = rules[j];
if(rule.selectorText=='thing'){//loop each stylesheet rule
console.log(rule.style.height);
// should return height for everytime height is used with every .thing in any of your stylesheets attached :)
}
}
}
PLEASE NOTE
You must escape those from cross domain.e.g. if you have included
<link ....="...jquery.com.../ui.css" /> it will not work as this might be considered as security risk (cross domain)...
This isn't the most efficient solution, particularly for old IE versions, but it should work pretty well:
Measure the height of your element
Append some content to the element e.g. <div style="clear: left; height: 30px">Test</div>
Test the new height, if it has changed your element has height auto
Remove the content
Here's my implementation:
$.fn.hasAutoHeight = function() {
if (this.length === 0) return;
var self = this.first();
var height = self.css("height");
var position = self.css("position");
// Check for inline elements
if (self.css("display") === "inline" && self.css("float") === "none") {
var position = self.css("position");
if (position === "static" || position === "relative") return true;
}
// Quick check to see if a style height is set
if ($.style(self[0], "height") !== "") return false;
// Otherwise use the long route
var test = $('<div style="clear: both; height: 30px">Test</div>');
self.append(test);
var hasAutoHeight = self.css("height") !== height;
test.css("color", "red").remove();
return hasAutoHeight;
};
Notes:
The 'quick check' line might not work correctly if there is a height: auto !important; rule in the CSS, in which case you'd always have to go the long route.
This is not efficient in terms of DOM interactions so your application would want to cache this result whenever possible.
I'm reluctant to cache the result internally in the plugin because classes/CSS rules might change and invalidate the result.
This won't work for elements with no body, such as <img> and <br>
Here's a more complete implementation of the above suggestions:
$("*").data("autoHeight", "false");
var stylesheets = window.document.styleSheets;
for (i=0; i < stylesheets.length; i++) {
var rules = stylesheets[i].cssRules;
for (j = 0; j < rules.length; j++) {
var rule = rules[j];
var style = rule.style.getPropertyValue("height");
var auto = !style || style.match(/^\s*auto\s*(!important)?$/);
$(rule.selectorText).each(function() {
var elem = $(this);
if (asSpecific(rule.selectorText, $(elem).data("autoHeightSelector"))) {
$(elem).data("autoHeight", !!auto);
$(elem).data("autoHeightSelector", rule.selectorText);
}
});
}
}
You'll need to implement asSpecific(a, b) which should work out if css selector a is at least as specific as selector b, e.g. p#foo a#bar is more specific than p.foo. You also need to take into account the !important flag.
This might be useful: http://www.w3.org/TR/CSS2/cascade.html#specificity
This should add a data property to each element specifying whether or not it has an auto height style in the CSS, but you'll also need to check the style attribute and think about default styles.

How to find the width of a div using vanilla JavaScript?

How do you find the current width of a <div> in a cross-browser compatible way without using a library like jQuery?
document.getElementById("mydiv").offsetWidth
element.offsetWidth (MDC)
You can use clientWidth or offsetWidth Mozilla developer network reference
It would be like:
document.getElementById("yourDiv").clientWidth; // returns number, like 728
or with borders width :
document.getElementById("yourDiv").offsetWidth; // 728 + borders width
All Answers are right, but i still want to give some other alternatives that may work.
If you are looking for the assigned width (ignoring padding, margin and so on) you could use.
getComputedStyle(element).width; //returns value in px like "727.7px"
getComputedStyle allows you to access all styles of that elements. For example: padding, paddingLeft, margin, border-top-left-radius and so on.
Another option is to use the getBoundingClientRect function. Please note that getBoundingClientRect will return an empty rect if the element's display is 'none'.
var elem = document.getElementById("myDiv");
if(elem) {
var rect = elem.getBoundingClientRect();
console.log(rect.width);
}
You can also search the DOM using ClassName. For example:
document.getElementsByClassName("myDiv")
This will return an array. If there is one particular property you are interested in. For example:
var divWidth = document.getElementsByClassName("myDiv")[0].clientWidth;
divWidth will now be equal to the the width of the first element in your div array.
Actually, you don't have to use document.getElementById("mydiv") .
You can simply use the id of the div, like:
var w = mydiv.clientWidth;
or
var w = mydiv.offsetWidth;
etc.
call below method on div or body tag onclick="show(event);"
function show(event) {
var x = event.clientX;
var y = event.clientY;
var ele = document.getElementById("tt");
var width = ele.offsetWidth;
var height = ele.offsetHeight;
var half=(width/2);
if(x>half)
{
// alert('right click');
gallery.next();
}
else
{
// alert('left click');
gallery.prev();
}
}
The correct way of getting computed style is waiting till page is rendered. It can be done in the following manner. Pay attention to timeout on getting auto values.
function getStyleInfo() {
setTimeout(function() {
const style = window.getComputedStyle(document.getElementById('__root__'));
if (style.height == 'auto') {
getStyleInfo();
}
// IF we got here we can do actual business logic staff
console.log(style.height, style.width);
}, 100);
};
window.onload=function() { getStyleInfo(); };
If you use just
window.onload=function() {
var computedStyle = window.getComputedStyle(document.getElementById('__root__'));
}
you can get auto values for width and height because browsers does not render till full load is performed.

Mootools textarea scrollHeight

How can I access the scrollHeight using mootools or some other property that contains the height so I can resize it to make an autogrow textarea?
Mootools offers a variety of Element 'dimension' functions that give you information on the scrollable and absolute element sizes. Full docs available here: http://mootools.net/docs/core/Element/Element.Dimensions
What you want to do is compare the return values of your element's getScrollSize() function to your element's getSize() function - in particular the 'y' member, which represents element and scrollable area height, respectively. Something along the lines of this should work:
var myElement = $('myElement'); // get a reference to your element
var scrollSize = myElement.getScrollSize(); // MooTools-specific function.
var elementSize = myElement.getSize(); // MooTools-specific function.
if (scrollSize.y > elementSize.y) {
// determine whether the scrollable area is greater than the dimensions
// of the element. If so, resize the element to match the scrollable area.
myElement.setStyle('height', scrollSize.y + 'px');
}
David Walsh created an excellent plugin for just this purpose:
http://davidwalsh.name/flext-textrea
Here's a simple method I'm using that expands but also contracts the textarea.
The issue you're always going to have is styling on the textare (padding/border).
The first thing to know is that getSize() will get the size of the textarea from absolute top to the absolute bottom, taking into account padding and borders. However, the actual style height of the text area .getStyle('height').toInt(), is the inside of the text box without padding and border. This is the part you need to be interested in as, when you set your height, it sets that, it doesn't set the full height of the textarea from absolute top to bottom.
Here's a working example, with a textarea that's styled (See Demo)
This will also resize the element correctly if you ran it inside domReady.
function expBox(el){
var e = $(el.id);
if(typeof(e._expBox) == "undefined"){
var v = e.value;
e.value = "";
var ss = e.getScrollSize();
var s = e.getSize();
var h = e.getStyle("height").toInt();
e._expBox = (s.y-h)-(s.y-ss.y);
e.value = v;
}
var k = event.keyCode || event.charCode;
if(k == 8 || k == 46){
e.setStyle("height","auto");
}
var ss = e.getScrollSize();
e.setStyle("height",(ss.y-e._expBox));
}
Demo:
http://jsfiddle.net/greatbigmassive/M6X5j/

Categories