Scrollable table unobtrusive script - javascript

Here is nice piece of code that works fair in all browsers: http://www.imaputz.com/cssStuff/bigFourVersion.html
Since there are things that need to be computed for every particular table (extra space for scrollbar, fixed width for every cell), I'd like to create a javascript that modifies the table to make it scrollable.
Such scripts already exist, i.e. http://www.farinspace.com/jquery-scrollable-table-plugin/
but all of them need to specify the height of the table. I'd like to extract the height from CSS to make the script unobtrusive.
If I write the height as inline style, all browsers can read the table.style.height property. But when external style is used
<style>
.scrollTable { display: block; overflow: hidden; height: 200px; }
</style>
only Firefox can read the offsetHeight/clientHeight property as expected. Other browsers can't change table layout to block, I guess.
The only thing that I figured out is to read external CSS
function getCSS(rule,prop) {
if(!(document && document.styleSheets)) return;
var result="", ds = document.styleSheets;
for(var i=0; i<ds.length; i++) {
var r = getCSS1(ds[i],rule,prop);
if(r) result = r;
}
return result;
}
function getCSS1(sheet,rule,prop) {
var rules = sheet.cssRules? sheet.cssRules: sheet.rules;
var result = "";
for(var i=0; i<rules.length; i++) {
var r = rules[i].selectorText.toLowerCase();
if(r.indexOf(rule)==-1) continue;
if(r.lastIndexOf(rule)!=r.length-rule.length) continue;
var p = rules[i].style[prop];
if(p) result = p;
}
return result;
}
var height = getCSS(".scrollTable","height");
But the height might be specified otherwise: by id, another class or inherited, so I am probably in wrong way. Is there any other way how to guess the table height? I am about to give up.
In short
I want this code
<script src="scrollTable.js"></script> // load the script
<style> .scrollTable { height: 200px; } // set the CSS
<table class="scrollTable">...</table> // script should do all the tricks
My script can do all the tricks except for get the table height. How to extract it?

Why not enclose the <table> in a <div>? This way you should be able to the get the <div> height even if it's in an external CSS.

With jQuery you can use .css() function:
table_height = $("table.scrollTable").css("height");
This will return the height of your table including px. So you can extract only the number with some other javascript function.

Assuming you are using jQuery (you did mention a jQuery plugin), you can calculate the height of an element using $('table.selector').height().

Is getComputedStyle the answer ? See here : http://blog.stchur.com/2006/06/21/css-computed-style/

You could use
document.getElementById("ID").clientHeight
It worked for me in IE8 and Chrome when I tested height set via
html
inline style
style sheet
Here's what I did:
<table height="350" id="one">
<table>
<table style="height:400px;" id="two">
<table>
<table class="height" id="three">
<table>
and
alert(document.getElementById("one").clientHeight);
alert(document.getElementById("two").clientHeight);
alert(document.getElementById("three").clientHeight);
Working example: http://jsfiddle.net/jasongennaro/h9B2j/
EDIT
Something else must be interfering with the code, I think, as
document.getElementById("").clientHeight;
works for me even without the height being set.
See another example here: http://jsfiddle.net/jasongennaro/h9B2j/2/

Related

How to override an element's default style with Javascript?

In CSS we can do:
div { font-size:20px }
To set the default font size for all divs. Is there a way to change default styles for elements with JavaScript?
Alternately, how could I find and set the above style rule? You can find classes by searching document.styleSheets[0].cssRules by name, but I don't know how to find the style for div.
EDIT:
Oops, the answer is in my question.
My confusion arose from attempting to alter rules that were set for multiple elements at once.
So you would be able to find and alter the CSS rule for div as above.
What I don't know is how you'd alter the rule for multiple definitions:
div,span { font-size:20px }
You can't find the rule by searching for div, span or div,span.
You can use style.fontSize property for setting font size using javascript. The code will look like
document.getElementById("//id here").style.fontSize = "50px"; //size
See an example here
well if you want to change the style of an determinated div you have to do this in you javascript code
getElementById('div_register').setAttribute("style","font-size:20px");
in this way you are getting de div by its id, and setting a style that you want, you can set differents styles with these and will save code space as declare one by one the style you want...i hope i helped you :-D
With the help of javascript you can change the DOM properties. You can create one outer div and give it some name/id. Then, loop through all inner divs and update the css style attributes.
innerDivs = document.getElementById('odivID').getElementsByTagName('div');
for (var i = innerDivs.length-1; i >= 0; i--) {
innerDivs[i].style.fontSize = "25px";
}
You can do this by n number of ways, but I recommend to use class name:
style
div.my-style {
font-size:20px;
}
script
...
var divs = document.getElementsByTagName('div');
var len = divs.length;
var cn;
if(len --) do {
cn = divs[len].className;
if(cn) {
cn += ' my-style';//<-- spaces to separate with the existing class names, if any
} else {
cn = 'my-style';
}
divs[len].className = cn;
} while(len --);
...
Note: Applying style to all divs will apply to those divs as well on the same page which you don't want to do.
You could create your own css style rule that override the default one.
either
create <style> in <header> using javascript
or, link external css file <link>
please see fiddle using first method: http://jsfiddle.net/b8Hn7/
var myStyle = document.createElement("style");
myStyle.innerText = 'div { font-size: 40px; }';
document.head.appendChild(myStyle);
The above code overrides the default style by creating same rule but place after the default style, there is no need to "locate" the default style and change it.
U can try it with create 'style' dom like my under code:
html:
</div>
js:
var style = document.createElement('style');
style.innerText = 'div{width:100px;height:100px;border:1px solid #c4e;}';
document.body.appendChild(style);

Net width and net height of current browser

I try to build a web application that will fit with almost all sizes of devices/browsers. To do so, my actual approach is to define,inside of my body, a div that will take the whole space of body:
#mydiv {
width: 100%;
height: 100%;
}
I calculate, then, width and height of my available space using:
var Width= $("#mydiv").width();
var Height= $("#mydiv").height();
I do what I want after. I position my elements with jQuery/CSS (percentages, top property, absolute positionnong,...), I draw with Rapahael.js....
I discovered that this approach is not always efficient, especially for browsers that display their addons as HTML. For example in my Chrome, when I install a toolbar addon, this toolbar is rendered in the page code source as HTML elements with their own styles (top=0, fixed postion..). The consequence is that all my work with top position is shifted by the height of the toolbar.
How can I calculate the net height of body?
What are alternative approaches to create webpage that adapts with the net browser size (I mean after any DOM injected elements outside of my control like ask.com toolbar... )?
Edit: so I gave this problem a little thought and I figure that if an add-on is going to draw to the DOM, it's most likely going to append itself to body. So, if you structured your document body in this manner:
<body>
<div id="container">
... all your content here
</div>
</body>
and the add-on inserted itself like this:
<body>
<div id="toolbar" style="margin:0;padding:5px;position:fixed;top:0px;left:0px;width:100%;height:20px;background-color:#000;color:#fff">toolbar</div>
<div id="container">
... all your content here
</div>
</body>
You could overcome this by setting #container's position to relative and adding the following script to your page:
var shift_amount = 0;
var children = document.body.children;
for(var i = 0; i < children.length; i++){
if(children[i].style.position == 'fixed'){
shift_amount += parseFloat(children[i].style.height);
}
}
var Height = $(window).height();
var Width = $(window).width();
if(shift_amount > 0){
// subtract fixed element height from available height
Height -= shift_amount;
}
As I'm pretty sure the question #RoryMcCrossan linked answers the question you asked, I will add that the preferred approach to creating responsive websites is to use media queries to adapt your CSS at various widths (mobile, tablet, desktop). Here is an example of media queries in action using Twitter Bootstrap, open that page and resize your browser window.
<style>
/* target only browsers less than or equal to 600px; */
#media (max-width: 600px) {
.sidebar {
display: none;
}
}
</style>
Regarding the issue of having toolbars and other components rendered in the HTML, this is going to be difficult to overcome as you can't know any and every element that will get injected into the DOM outside of your control. If you are targeting a specific use case, please point us to that add-on and there may be a solution to find.
I would take a look at the "mutation observers" to detect changes in the DOM structure.
Then you can just get those values again.
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MutationObserver(function(mutations, observer) {
// fired when a mutation occurs
Width= $("#mydiv").width();
Height= $("#mydiv").height();
});
// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document, {
subtree: true,
attributes: true
//...
});

How can I check if CSS calc() is available using JavaScript?

Is there a way to check if the CSS function calc is available using JavaScript?
I found lot of questions and articles about getting the same behaviour as calc using jQuery, but how can I only check if it's available?
In Modernizr you can find the test as css-calc currently in the non-core detects. They use the following code:
Modernizr.addTest('csscalc', function() {
var prop = 'width:';
var value = 'calc(10px);';
var el = document.createElement('div');
el.style.cssText = prop + Modernizr._prefixes.join(value + prop);
return !!el.style.length;
});
A bit late to the party but I figured I should share this because I was myself struggling with it. Came up with the idea of by using jQuery, I can create a div that uses the calc() value in a CSS property (such as width in this case) and also a fallback width in case the browser does not support calc(). Now to check whether it supports it or not, this is what I did:
Let's create the CSS style for the currently "non-existing" div element.
/* CSS3 calc() fallback */
#css3-calc {
width: 10px;
width: calc(10px + 10px);
display: none;
}
Now, if the browser does not support calc(), the element would return a width value of 10. If it does support it, it would return with 20. Doesn't matter what the values are exactly, but as long as the two width properties have different values in the end (in this case 10 and 20).
Now for the actual script. It's pretty simple and I suppose it's possible with regular JavaScript too, but here's the jQuery script:
// CSS3 calc() fallback (for unsupported browsers)
$('body').append('<div id="css3-calc"></div>');
if( $('#css3-calc').width() == 10) {
// Put fallback code here!
}
$('#css3-calc').remove(); // Remove the test element
Alternatively, native javascript check, and width:
#css3-calc { width: 1px; width: calc(1px + 1px); }
if( document.getElementById('css3-calc').clientWidth==1 ){
// clientHeight if you need height
/* ... */
}
Calc detection was added to modernizer according to their news page.
http://modernizr.com/news/
As well as tightening up support for existing tests, we've also added
a number of new detects, many submitted by the community:
[...]
css-calc
var cssCheck = document.createElement("DIV");
cssCheck.style.marginLeft = "calc(1px)";
if (cssCheck.style.getPropertyValue("margin-left"))
{
alert("calc is supported");
}
cssCheck = null;

Overlay graphic border on img tags

I want to be able to overlay a graphic border on all images on a site without having to manually apply it in photoshop. The border I'm using is a rough 'distressed' graphic which therefore isn't achievable by using css borders.
My initial idea is to use javascript to dynamically add a surrounding div (or divs) containing the border graphic to all img tags although I'm not quite sure how to do this.
I'd suggest the following JavaScript:
var D = document,
images = D.getElements​ByTagName('img');
function imageWrap(el, wrapper) {
if (!el) {
return false;
} else {
var wrapper = wrapper || 'div',
d = D.createElement(wrapper);
el.parentNode.insertBefore(d, el.nextSibling);
d.appendChild(el);
}
}
for (var i = 0, len = images.length; i < len; i++) {
imageWrap(images[i]);
}
JS Fiddle demo.
References:
appendChild().
createElement().
getElementsByTagName().
insertBefore().
parentNode.
There's an alternative using CSS3.
Example snippet:
img {
border-width: 20px;
-moz-border-image:url("border.png") 20 repeat stretch;
-webkit-border-image:url("border.png") 20 repeat stretch;
border-image:url("border.png") 20 repeat stretch;
}
​jsFiddle
References:
The W3C Candidate Recommendation
The W3C Working Draft
On Mozilla Developer Network
On CSS-Tricks
Disclaimer: CSS3 is currently not fully supported across browsers, this solution assumes we aim to move forward in web development to target modern browsers.
You can make your border as a background image and put the image inside it and add some margin
check my jsfiddle
You should be able to do it with JQuery, I tested this script and it worked for me. I just gave the image a background image and added padding.
You would call JQuery in the header:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
Then you could try this script:
<script>
$(document).ready(function(){
$('img').css({
'background' : 'url(images/002.jpg) repeat',
'padding' : '10px'
});
});
</script>
You could replace 'img' with your class, for example '.border', you could adjust the padding as well, and you would just replace the url of the background image with yours. Hope this helps/works!

Find the "potential" width of a hidden element

I'm currently extending the lavalamp plugin to work on dropdown menus but I've encountered a small problem. I need to know the offsetWidth of an element that is hidden. Now clearly this question makes no sense, rather what I'm looking for is the offsetWidth of the element were it not hidden.
Is the solution to show it, grab the width, then hide again? There must be a better way...
The width of an element that has CSS visibility: hidden is measurable. It's only when it's display: none that it's not rendered at all. So if it's certain the elements are going to be absolutely-positioned (so they don't cause a layout change when displayed), simply use css('visibility', 'hidden') to hide your element instead of hide() and you should be OK measuring the width.
Otherwise, yes, show-measure-hide does work.
The only thing I can think of is to show it (or a clone of it) to allow retrieval of the offsetWidth.
For this measurement step, just make its position absolute and its x or y value a big negative, so it will render but not be visible to the user.
You can use the following function to get the outer width of an element that is inside a hidden container.
$.fn.getHiddenOffsetWidth = function () {
// save a reference to a cloned element that can be measured
var $hiddenElement = $(this).clone().appendTo('body');
// calculate the width of the clone
var width = $hiddenElement.outerWidth();
// remove the clone from the DOM
$hiddenElement.remove();
return width;
};
You can change .outerWidth() to .offsetWidth() for your situation.
The function first clones the element, copying it to a place where it will be visible. It then retrieves the offset width and finally removes the clone. The following snippet illustrates a situation where this function would be perfect:
<style>
.container-inner {
display: none;
}
.measure-me {
width: 120px;
}
</style>
<div class="container-outer">
<div class="container-inner">
<div class="measure-me"></div>
</div>
</div>
Please be aware that if there is CSS applied to the element that changes the width of the element that won't be applied if it's a direct descendant of body, then this method won't work. So something like this will mean that the function doesn't work:
.container-outer .measure-me {
width: 100px;
}
You'll either need to:
change the specificity of the CSS selector ie. .measure-me { width: 100px; }
change the appendTo() to add the clone to a place where your CSS will also be applied to the clone. Ensure that where ever you do put it, that the element will be visible: .appendTo('.container-outer')
Again, this function assumes that the element is only hidden because it's inside a hidden container. If the element itself is display:none, you can simply add some code to make the clone visible before you retrieve it's offset width. Something like this:
$.fn.getHiddenOffsetWidth = function () {
var hiddenElement $(this)
width = 0;
// make the element measurable
hiddenElement.show();
// calculate the width of the element
width = hiddenElement.outerWidth();
// hide the element again
hiddenElement.hide();
return width;
}
This would work in a situation like this:
<style>
.measure-me {
display: none;
width: 120px;
}
</style>
<div class="container">
<div class="measure-me"></div>
</div>
Two options:
position the element outside the viewport (ex: left:-10000px)
use visibility: hidden or opacity: 0 instead of hide().
Either way will work as hiding the element but still being able to get the computed width. Be careful with Safari on thi, it's awfully fast and sometimes too fast...
Actual jQuery plugin!
Usage:
console.log('width without actual: ' + $('#hidden').width());
console.log('width with actual: ' + $('#hidden').actual('width'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.actual/1.0.19/jquery.actual.min.js"></script>
<div style="width: 100px; display: none;">
<div id="hidden"></div>
</div>
If you know the element to be the full width of a parent element another approach is to create a recursive method:
es5:
var getWidth;
getWidth = function($el){
return $el.offsetWidth || getWidth($el.parentElement);
}
var width = getWidth(document.getElementById('the-element'));
es6:
let getWidth
getWidth = ($el) => $el.offsetWidth || getWidth($el.parentElement)
const width = getWidth(document.getElementById('the-element'))
What I did was ;
by the time hiding that element, stored its width in its dataset.
It only will work for you if you can hide programmatically.
ie.
When Hiding ;
var elem = $("selectorOfElement");
elem.dataset.orgWidth = elem.clientWidth;
Later when getting ;
var elem = $("selectorOfElement");
var originalWidthWas = elem.dataset.orgWidth;
thats because its hidden via display: none; What ive done in the past is to make a "reciever" div which i use absolute positioning on to get it off the page. Then i load the new element into that, grab the dimensions and then remove it when im done - then remove the reciever when im done.
Another thing you can do is to not use hide(); but to instead set visibility: hidden; display: ; However this means the blank area will be rendered wherever the node is attached.
var $hiddenElement = $('#id_of_your_item').clone().css({ left: -10000, top: -10000, position: 'absolute', display: 'inline', visibility: 'visible' }).appendTo('body');
var width = parseInt($hiddenElement.outerWidth());
$hiddenElement.remove();
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
Sorry I am late to this conversation. I am surprised no one has mentioned getComputedStyle. (Note this only works if the CSS sets a width value)
Grab the element:
let yourEle = document.getElementById('this-ele-id');
and use the function:
getComputedStyle(yourEle).width
This returns a string so you will have to remove the numbers from the string.
This works even when the element's display style is set to none.
Other articles to read about this includes here at zellwk.com

Categories

Resources