I have a CSS defined for a div
#myDiv
{
padding-top: 20px,
padding-bottom: 30px
}
In a JS function, I would like to increment the value of padding-top by 10px
function DoStuff()
{
var myDiv = document.getElementById('myDiv');
//Increment by 10px. Which property to use and how? something like..
//myDiv.style.paddingTop += 10px;
}
The .style property can only read inline styles defined on an element. It cannot read styles defined in stylesheets.
You need a library to get the value, or use something like (from this question):
function getStyle(elem, name) {
// J/S Pro Techniques p136
if (elem.style[name]) {
return elem.style[name];
} else if (elem.currentStyle) {
return elem.currentStyle[name];
}
else if (document.defaultView && document.defaultView.getComputedStyle) {
name = name.replace(/([A-Z])/g, "-$1");
name = name.toLowerCase();
s = document.defaultView.getComputedStyle(elem, "");
return s && s.getPropertyValue(name);
} else {
return null;
}
}
Then your code becomes:
var element = document.getElementById('myDiv'),
padding = getStyle(element, 'paddingTop'); // eg "10px"
element.style.paddingTop = parseInt(padding, 10) + 10 + 'px';
References:
.style and inline vs stylesheet styles
getStyle function
radix (2nd) parameter to parseInt
You should be using jquery to do this sort of thing, as most other solutions won't be very cross browser compatible and you'll spend days pulling your hair out over it.
function Dostuff()
{
var currentPadding = $('#myDiv').css('padding-top');
$('#myDiv').css('padding-top', currentPadding + 1);
}
See jquery.com for more.
Related
This question already has an answer here:
Query property value of a css class even if not in use
(1 answer)
Closed 7 years ago.
I dispose of the following class :
.specialCell {
padding-left: 10px;
}
I would like to use this value as a property in JS, eg
var specialCellLeftPadding = getCssValue('.specialCell', 'padding-left');
The only way I can think of would be to create an element with the wanted class and get the seeked attribute value :
var tmpElt = document.createElement('div');
tmpElt.className = 'specialCell';
document.body.appendChild(tmpElt);
var specialCellLeftPadding = getComputedProperties(tmpElt).getPropertyValue('padding-left');
document.body.removeChild(tmpElt);
Is it possible to achieve the same purpose without creating and adding an new element to the dom ? (assuming no element with this class exists).
You can query CSS information directly from stylesheets using the CSSOM. E.g.,
var stylesheet = document.styleSheets[0];
document.getElementById('output').innerHTML = stylesheet.cssRules[0].style.paddingLeft;
.test { padding-left: 12px; }
Padding left: <span id="output"></span>
Borrowing from the example of dystroy's answer, you can get a css value using the document.styleSheets property
Using the css
.specialCell {
padding-left: 10px;
}
and
function getCssProperty(cssclass, property) {
for (var i = 0; i < document.styleSheets.length; i++) {
var styleSheet = document.styleSheets[i];
var cssRules = styleSheet.rules || // chrome, IE
styleSheet.cssRules; // firefox
for (var ir = cssRules.length; ir-- > 0;) {
var rule = cssRules[ir];
if (rule.selectorText == "." + cssclass) {
return rule.style.getPropertyValue(property);
}
}
}
}
var prop = getCssProperty('specialCell', 'padding-left');
console.info(prop);
this example will print 10px in the console
I have the following javascript which I have hashed together from bits of code that I found on Stack Overflow (I'm no JavaScript expert!): -
var walk_the_DOM = function walk(node, func) {
func(node);
node = node.firstChild;
while (node) {
walk(node, func);
node = node.nextSibling;
}
};
function myFunction() {
var wrapper = document.createElement("pastedHtml");
wrapper.innerHTML = " <pre style=\"font-family: Consolas; background: white; color: black; font-size: 13px\"data-listid> <span style=\"color: blue\" data-listid><</span><span style=\"color: maroon\" data-listid>telerik</span><span style=\"color: blue\" data-listid>:</span><span style=\"color: maroon\" data-listid>EditorTool</span> <span style=\"color: red\" data-listid>Name</span><span style=\"color: blue\" data-listid>=</span><span style=\"color: blue\" data-listid>\"Cut\"</span> <span style=\"color: blue\" data-listid>/></span> </pre>";
walk_the_DOM(wrapper, function(el) {
{
if (typeof el.style != "undefined") {
el.style.color = "None";
}
}
});
document.getElementsByTagName("UL")[0].appendChild(wrapper);
}
You can see it not working in this JSFiddle.
What I want it to do is to change the color of all style attributes to "None".
In other words I want to remove all color from the text.
I think that it might be something to do with passing by value rather than reference?
I've attached the IE debugger and I can see that after setting el.style.color = "None" the value of el.style.color is unchanged.
What is wrong here?
In CSS, value none is not valid.
You can use element.style.color="" (as said in comments) or element.style.color="black" (or any value you want).
Additionally, I'd recommend using classes and css instead of element.style.
This code:
<script>
element.style.color = "black";
</script>
Can be also written this way:
<style>
.black{
color: black;
}
</span>
<script>
element.classList.add("black");
</script>
And then you can easily remove the class like element.classList.remove("black");
If you want the text to disappear, the only logical action that setting the color to none would do, then you should set the color to 'transparent', like so:
element.style.color = "transparent";
Though, if you just want to hide elements, a more performant way would be to set the element's display to none, like so:
element.style.display = "none";
This is a follow up.
The answer that I was looking for was to set element.style.color="".
However when I tried to use this scipt in the markup of my ASP.NET web page, it didn't work in IE!?!
I debugged it in Visual Studio and though it was not throwing any errors, the set property seemed to be having no effect.
I therefore modified the code and used the cssText property which I found in the debugger watch window in order to filter out certain values from the style by manipulating the csstext string as this JSFIDDLE shows.
walk_the_DOM(wrapper, function(el) {
{
if (typeof el.style != "undefined") {
var attr = el.getAttribute("style");
if (attr != null) {
var attrs = attr.replace(/\s+/g, "").split(";");
attr = "";
for (var i = 0; i < attrs.length; i++) {
var propName = attrs[i].split(":")[0].toLowerCase();
if (propName != "" && propName != "background" && propName != "font-size" && propName != "color") {
attr += attrs[i] + "; "
};
};
if (attr == "")
el.removeAttribute("style");
else el.setAttribute("style", attr);
};
}
}
});
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).
Is it possible to get ALL of the styles for an object using JavaScript? Something like:
main.css
-------
#myLayer {
position: absolute;
width: 200px;
height: 100px;
color: #0000ff;
}
main.js
-------
var ob = document.getElementById("myLayer");
var pos = ob.(getPosition);
// Pos should equal "absolute" but
// ob.style.position would equal null
// any way to get absolute?
You are talking about what is known as Computed Style, check out these article on how to get it:
Get Styles on QuirksMode
Get Computed Style
Get the rendered style of an element
From the last article, here is a function:
function getStyle(oElm, strCssRule){
var strValue = "";
if(document.defaultView && document.defaultView.getComputedStyle){
strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
}
else if(oElm.currentStyle){
strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
return p1.toUpperCase();
});
strValue = oElm.currentStyle[strCssRule];
}
return strValue;
}
How to use it:
CSS:
/* Element CSS*/
div#container{
font: 2em/2.25em Verdana, Geneva, Arial, Helvetica, sans-serif;
}
JS:
var elementFontSize = getStyle(document.getElementById("container"), "font-size");
You might use:
var ob = document.getElementById("myLayer");
var pos = ob.style.position;
Every CSS property has it's own object model. Usually those css properties that contain '-' are written using java model.
For example:
//getting background-color property
var ob = document.getElementById("myLayer");
var color = ob.style.backgroundColor;
If you want to get all the css properties that are defined for an object, you will have to list them one by one, because even if you did not set the property in your style sheet, an object will have it with the default value.
Polyfill to get the current CSS style of element using javascript ... Visit the link for more info
/**
* #desc : polyfill for getting the current CSS style of the element
* #param : elem - The Element for which to get the computed style.
* #param : prop - The Property for which to get the value
* #returns : The returned style value of the element
**/
var getCurrentStyle = function (ele, prop) {
var currStyle;
if (!window.getComputedStyle) {
currStyle = ele.currentStyle[prop];
} else {
currStyle = window.getComputedStyle(ele).getPropertyValue(prop);
}
return currStyle;
}
/** How to use **/
var element = document.getElementById("myElement");
getCurrentStyle(element, "width"); // returns the width value
This question already has answers here:
Check if element is visible in DOM
(27 answers)
Closed 6 years ago.
In JavaScript, how would you check if an element is actually visible?
I don't just mean checking the visibility and display attributes. I mean, checking that the element is not
visibility: hidden or display: none
underneath another element
scrolled off the edge of the screen
For technical reasons I can't include any scripts. I can however use Prototype as it is on the page already.
For the point 2.
I see that no one has suggested to use document.elementFromPoint(x,y), to me it is the fastest way to test if an element is nested or hidden by another. You can pass the offsets of the targetted element to the function.
Here's PPK test page on elementFromPoint.
From MDN's documentation:
The elementFromPoint() method—available on both the Document and ShadowRoot objects—returns the topmost Element at the specified coordinates (relative to the viewport).
I don't know how much of this is supported in older or not-so-modern browsers, but I'm using something like this (without the neeed for any libraries):
function visible(element) {
if (element.offsetWidth === 0 || element.offsetHeight === 0) return false;
var height = document.documentElement.clientHeight,
rects = element.getClientRects(),
on_top = function(r) {
var x = (r.left + r.right)/2, y = (r.top + r.bottom)/2;
return document.elementFromPoint(x, y) === element;
};
for (var i = 0, l = rects.length; i < l; i++) {
var r = rects[i],
in_viewport = r.top > 0 ? r.top <= height : (r.bottom > 0 && r.bottom <= height);
if (in_viewport && on_top(r)) return true;
}
return false;
}
It checks that the element has an area > 0 and then it checks if any part of the element is within the viewport and that it is not hidden "under" another element (actually I only check on a single point in the center of the element, so it's not 100% assured -- but you could just modify the script to itterate over all the points of the element, if you really need to...).
Update
Modified on_top function that check every pixel:
on_top = function(r) {
for (var x = Math.floor(r.left), x_max = Math.ceil(r.right); x <= x_max; x++)
for (var y = Math.floor(r.top), y_max = Math.ceil(r.bottom); y <= y_max; y++) {
if (document.elementFromPoint(x, y) === element) return true;
}
return false;
};
Don't know about the performance :)
As jkl pointed out, checking the element's visibility or display is not enough. You do have to check its ancestors. Selenium does this when it verifies visibility on an element.
Check out the method Selenium.prototype.isVisible in the selenium-api.js file.
http://svn.openqa.org/svn/selenium-on-rails/selenium-on-rails/selenium-core/scripts/selenium-api.js
Interesting question.
This would be my approach.
At first check that element.style.visibility !== 'hidden' && element.style.display !== 'none'
Then test with document.elementFromPoint(element.offsetLeft, element.offsetTop) if the returned element is the element I expect, this is tricky to detect if an element is overlapping another completely.
Finally test if offsetTop and offsetLeft are located in the viewport taking scroll offsets into account.
Hope it helps.
This is what I have so far. It covers both 1 and 3. I'm however still struggling with 2 since I'm not that familiar with Prototype (I'm more a jQuery type of guy).
function isVisible( elem ) {
var $elem = $(elem);
// First check if elem is hidden through css as this is not very costly:
if ($elem.getStyle('display') == 'none' || $elem.getStyle('visibility') == 'hidden' ) {
//elem is set through CSS stylesheet or inline to invisible
return false;
}
//Now check for the elem being outside of the viewport
var $elemOffset = $elem.viewportOffset();
if ($elemOffset.left < 0 || $elemOffset.top < 0) {
//elem is left of or above viewport
return false;
}
var vp = document.viewport.getDimensions();
if ($elemOffset.left > vp.width || $elemOffset.top > vp.height) {
//elem is below or right of vp
return false;
}
//Now check for elements positioned on top:
//TODO: Build check for this using Prototype...
//Neither of these was true, so the elem was visible:
return true;
}
/**
* Checks display and visibility of elements and it's parents
* #param DomElement el
* #param boolean isDeep Watch parents? Default is true
* #return {Boolean}
*
* #author Oleksandr Knyga <oleksandrknyga#gmail.com>
*/
function isVisible(el, isDeep) {
var elIsVisible = true;
if("undefined" === typeof isDeep) {
isDeep = true;
}
elIsVisible = elIsVisible && el.offsetWidth > 0 && el.offsetHeight > 0;
if(isDeep && elIsVisible) {
while('BODY' != el.tagName && elIsVisible) {
elIsVisible = elIsVisible && 'hidden' != window.getComputedStyle(el).visibility;
el = el.parentElement;
}
}
return elIsVisible;
}
You can use the clientHeight or clientWidth properties
function isViewable(element){
return (element.clientHeight > 0);
}
Prototype's Element library is one of the most powerful query libraries in terms of the methods. I recommend you to check out the API.
A few hints:
Checking visibility can be a pain, but you can use the Element.getStyle() method and Element.visible() methods combined into a custom function. With getStyle() you can check the actual computed style.
I don't know exactly what you mean by "underneath" :) If you meant by it has a specific ancestor, for example, a wrapper div, you can use Element.up(cssRule):
var child = $("myparagraph");
if(!child.up("mywrapper")){
// I lost my mom!
}
else {
// I found my mom!
}
If you want to check the siblings of the child element you can do that too:
var child = $("myparagraph");
if(!child.previous("mywrapper")){
// I lost my bro!
}
else {
// I found my bro!
}
Again, Element lib can help you if I understand correctly what you mean :) You can check the actual dimensions of the viewport and the offset of your element so you can calculate if your element is "off screen".
Good luck!
I pasted a test case for prototypejs at http://gist.github.com/117125. It seems in your case we simply cannot trust in getStyle() at all. For maximizing the reliability of the isMyElementReallyVisible function you should combine the following:
Checking the computed style (dojo has a nice implementation that you can borrow)
Checking the viewportoffset (prototype native method)
Checking the z-index for the "beneath" problem (under Internet Explorer it may be buggy)
One way to do it is:
isVisible(elm) {
while(elm.tagName != 'BODY') {
if(!$(elm).visible()) return false;
elm = elm.parentNode;
}
return true;
}
Credits: https://github.com/atetlaw/Really-Easy-Field-Validation/blob/master/validation.js#L178
Try element.getBoundingClientRect().
It will return an object with properties
bottom
top
right
left
width -- browser dependent
height -- browser dependent
Check that the width and height of the element's BoundingClientRect are not zero which is the value of hidden or non-visible elements. If the values are greater than zero the element should be visible in the body. Then check if the bottom property is less than screen.height which would imply that the element is withing the viewport. (Technically you would also have to account for the top of the browser window including the searchbar, buttons, etc.)
Catch mouse-drag and viewport events (onmouseup, onresize, onscroll).
When a drag ends do a comparison of the dragged item boundary with all "elements of interest" (ie, elements with class "dont_hide" or an array of ids). Do the same with window.onscroll and window.onresize. Mark any elements hidden with a special attribute or classname or simply perform whatever action you want then and there.
The hidden tests are pretty easy. For "totally hidden" you want to know if ALL corners are either inside the dragged-item boundary or outside the viewport. For partially hidden you're looking for a single corner matching the same test.
I don't think checking the element's own visibility and display properties is good enough for requirement #1, even if you use currentStyle/getComputedStyle. You also have to check the element's ancestors. If an ancestor is hidden, so is the element.
Check elements' offsetHeight property. If it is more than 0, it is visible. Note: this approach doesn't cover a situation when visibility:hidden style is set. But that style is something weird anyways.
Here is a sample script and test case. Covers positioned elements, visibilty: hidden, display: none. Didn't test z-index, assume it works.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<style type="text/css">
div {
width: 200px;
border: 1px solid red;
}
p {
border: 2px solid green;
}
.r {
border: 1px solid #BB3333;
background: #EE9999;
position: relative;
top: -50px;
height: 2em;
}
.of {
overflow: hidden;
height: 2em;
word-wrap: none;
}
.of p {
width: 100%;
}
.of pre {
display: inline;
}
.iv {
visibility: hidden;
}
.dn {
display: none;
}
</style>
<script src="http://www.prototypejs.org/assets/2008/9/29/prototype-1.6.0.3.js"></script>
<script>
function isVisible(elem){
if (Element.getStyle(elem, 'visibility') == 'hidden' || Element.getStyle(elem, 'display') == 'none') {
return false;
}
var topx, topy, botx, boty;
var offset = Element.positionedOffset(elem);
topx = offset.left;
topy = offset.top;
botx = Element.getWidth(elem) + topx;
boty = Element.getHeight(elem) + topy;
var v = false;
for (var x = topx; x <= botx; x++) {
for(var y = topy; y <= boty; y++) {
if (document.elementFromPoint(x,y) == elem) {
// item is visible
v = true;
break;
}
}
if (v == true) {
break;
}
}
return v;
}
window.onload=function() {
var es = Element.descendants('body');
for (var i = 0; i < es.length; i++ ) {
if (!isVisible(es[i])) {
alert(es[i].tagName);
}
}
}
</script>
</head>
<body id='body'>
<div class="s"><p>This is text</p><p>More text</p></div>
<div class="r">This is relative</div>
<div class="of"><p>This is too wide...</p><pre>hidden</pre>
<div class="iv">This is invisible</div>
<div class="dn">This is display none</div>
</body>
</html>
Here is a part of the response that tells you if an element is in the viewport.
You may need to check if there is nothing on top of it using elementFromPoint, but it's a bit longer.
function isInViewport(element) {
var rect = element.getBoundingClientRect();
var windowHeight = window.innerHeight || document.documentElement.clientHeight;
var windowWidth = window.innerWidth || document.documentElement.clientWidth;
return rect.bottom > 0 && rect.top < windowHeight && rect.right > 0 && rect.left < windowWidth;
}