Reputation: 145
We have a situation in our project when resizing a container. It seems to be impossible to keep the "auto" value for our elements margin.
For example when trying to get the margin value with javascript or jquery, the value always returns 0. We really need to keep "auto" when resizing, so is there a way to determine which elements have margin: auto;
Even if it's possible using raw javascript?
----------------- Possible solution but needs Extending -----------------
I have found this useful. Which in fact solves part of the problem!
Retrieve element margin if it's 'auto' (Answer 3)
if($(this).position().left*2 == ($(this).parent().innerWidth() - $(this).outerWidth())) {
console.info($(this).attr('id'));
}
However this matches far to many elements, so need to somehow be more specific. hopefully someone knows how to improve this code?
Upvotes: 9
Views: 939
Reputation: 145
Thanks to Vigrond previous answer above. I was able to research further into the CSS Rule Object.
Finally I have come up with my own solution to return the actual CSS rules direct from the style-sheet! This not only solves my problem with margin auto, it also allows me to return all other css values which are not returned by the jquery CSS object.
Although the code could be optimized further. I am very happy with the result, also I added a white list as in my case it is not necessary to loop through all style-sheets.
Here is the code I ended up with!
var cssObj = {};
function getStyle(element) {
var extractStyles = function(cssText) {
var css = {};
regEx = /\.*\{[^\}](.*)}/im;
styles = cssText.match(regEx)[1].split(';');
$.each(styles, function(k, style) {
$key = style.split(':')[0].trim();
$val = style.split(':')[1];
if($key != '')
css[$key] = $val.trim();
});
return css;
};
var sheets = document.styleSheets;
var whiteList = [
cssPath+'product.css',
cssPath+'style.css'
];
$.each(sheets, function(key, sheet) {
if($.inArray(sheet.href, whiteList) >=0) {
$rules = sheet.rules || sheet.cssRules;
$.each($rules, function(key, rule) {
if(element.is(rule.selectorText)) {
if(typeof(rule.cssText) != 'undefined' && rule.cssText) {
cssObj[rule.selectorText] = extractStyles(rule.cssText);
} else {
cssObj[rule.selectorText] = (typeof(rule.cssText) != 'undefined' ? extractStyles(rule.style.cssText) : '');
}
}
});
}
});
}
Upvotes: 1
Reputation: 8198
EDIT: I've only tested the following solution in Chrome. It isn't currently working in IE or Firefox. I'll provide an update when I get it working.
EDIT 2: Firefox solution: http://jsfiddle.net/E9eW6/8/ . The problem is that each browser handles their CSSStyleDeclaration object differently. While Firefox's was managable, IE is out in la-la land somewhere with their CSSRuleStyleDeclaration equivalent. I apologize, but I am not knowledgeable nor patient enough to learn Microsoft's poor implementation that will likely change in the future.
after a bit of research of this intriguing question, I found a solution
jsFiddle: http://jsfiddle.net/S5Sbf/3/
The answer was actually in another question here on Stackoverflow: Can jQuery get all CSS styles associated with an element? (see 2nd answer)
Basically the function will iterate through document.Stylesheets looking for the element that matches yours, and returns all of its CSS in a nice scrumptious object.
This is a very beautiful function, use it with pride!
function css(a){
var sheets = document.styleSheets, o = {};
for(var i in sheets) {
var rules = sheets[i].rules || sheets[i].cssRules;
for(var r in rules) {
if(a.is(rules[r].selectorText)) {
o = $.extend(o, css2obj(rules[r].style), css2obj(a.attr('style')));
}
}
}
return o;
}
function css2obj(css){
var s = {};
if(!css) return s;
if(css instanceof CSSStyleDeclaration) {
for(var i in css) {
if((css[i]).toLowerCase) {
s[(css[i]).toLowerCase()] = (css[css[i]]);
}
}
} else if(typeof css == "string") {
css = css.split("; ");
for (var i in css) {
var l = css[i].split(": ");
s[l[0].toLowerCase()] = (l[1]);
};
}
return s;
}
(Usage details in 2nd answer: Can jQuery get all CSS styles associated with an element?)
Using the css function above:
$("*").each(function(index, element){
cssObj = css($(element));
$(element).after("margin-left is " + cssObj['margin-left'] + '<br/>');
$(element).after("margin-right is " + cssObj['margin-right'] + '<br/>');
$(element).after("margin-top is " + cssObj['margin-top'] + '<br/>');
$(element).after("margin-bottom is " + cssObj['margin-bottom'] + '<br/>');
});
Upvotes: 5
Reputation: 189
you can do this for every element in a page with the $("*") search in jQuery
$("*").each(function(){
if($(this).css('margin') == 'auto'){
console.log($(this).attr('id')+' has margin auto');
}
});
Upvotes: 0
Reputation: 20163
well yo could something like this?
$('.container').each(function(){
if($(this).css('margin') == 'auto'){
console.log($(this).attr('id')+' has margin auto');
}
});
but if you post some code or link will be easier to help
Upvotes: 0