In my page, I wish to detect whether the page has vertical scrollbars, and if so, need to detect the width of the scrollbar, so I can reduce my body by the width and thus prevent my sidebar from changing location from viewing a non-scrolling page to a scrolling page.
I have the following jQuery/Javascript code:
$(document).ready(function () {
var parent, child, width;
if (width === undefined) {
parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body');
child = parent.children();
width = child.innerWidth() - child.height(99).innerWidth();
parent.remove();
}
if ($("body").height() > $(window).height()) {
//change width of body here
}
});
Unfortunately, this code doesn't work for me. Can someone please let me know where I'm going wrong?
(function($) {
$.fn.ScrollBarWidth = function() {
if (this.get(0).scrollHeight > this.height()) { //check if element has scrollbar
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild(inner);
document.body.appendChild(outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;
document.body.removeChild(outer);
return (w1 - w2);
}
}
})(jQuery);
Runs like so :
var scrollbarWidth = $('body').ScrollBarWidth();
console.log(scrollbarWidth); //prints the scrollbar width to the console
FIDDLE
You shouldn't need to change the width of the body. By default, it's 100% of the window's width and will adjust when scrollbars appear.
However, if you can't for some reason set the width to 100%, first see if disabling the horizontal scrollbar helps you:
overflow-x: hidden;
If that doesn't cut it, use the function from here to get the scrollbar's width. Then, listen to the window resize event:
var $window = $(window),
$body = $('body');
function resize() {
if ($body.height() > $window.height()) {
$body.width($body.width() - getScrollBarWidth());
}
}
$(window).resize(resize);
Related
I want to show "back-to-top" button when the screen resolution is bigger or equal 1200px. Of course, it depends on window width. Here is jQuery code:
var wW = $(window).width() + 17;
console.log(wW);
if (wW >= 1200) {
$(window).scroll(function () {
if ($(this).scrollTop() > 100) {
$('#oc-ontop').fadeIn('fast');
} else {
$('#oc-ontop').fadeOut('fast');
}
});
}
So, if you set the window width to 1200px, console show you the value 1200. But 1200 is the sum of window width (1183px) + scrollbar width (17px).
How can I calculate scrollbar width in this function to be independent of it's width?
Take a look at this thread: How can I get the browser's scrollbar sizes?
When you apply the code from there (originally Alexandre Gomes Blog):
function getScrollBarWidth () {
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;
document.body.removeChild (outer);
return (w1 - w2);
};
You can write:
var wW = $(window).width() + getScrollBarWidth();
Essentially, I'm creating a custom click & drag selection box. The problem is that the div is position absolutely, so it will scroll with the page, but it will not move with the page when the window is being resized. My attempted solution was to listen to the window resize, and move the div according to the change. The problem is that it will SEEM to work, but it will not move entirely accurately, so it will slowly move out of place if the window is resized slowly, or quickly move out of place if the window is resized quickly. It seems that the resize listener does not capture every resize event. I've narrowed the code down to the concept I'm using.
Try injecting this script into a page (I'm using the Chrome console and I haven't made any attempt for cross-compatibility because this will be used in a Chrome extension). It will attempt to resize only when the scrollbar is not active, to replicate the behavior of the page content. The client and scoll variables are interchangeable for recording the change in dimensions, but they are both there for testing purposes. I would love to see a solution which solves this problem using styling attributes. Thanks for your help!
var div = document.createElement("div");
div.style.position = "absolute";
div.style.backgroundColor = "#000";
div.style.width = div.style.height = div.style.left = div.style.top = "200px";
document.body.appendChild(div);
// get the highest z index of the document
function highestZIndex() {
var elems = document.getElementsByTagName("*");
var zIndex = 0;
var elem, value;
for (var i = 0; i < elems.length; i++) {
value = parseInt(document.defaultView.getComputedStyle(elems[i], null).zIndex, 10);
if (value > zIndex) {
zIndex = value;
elem = elems[i];
}
}
return {
elem: elem,
zIndex: zIndex
};
}
// set the div on top if it is not already
var highestZ = highestZIndex();
if (highestZ.elem != div) div.style.zIndex = highestZ.zIndex + 1;
// last width & height of client & scroll to calculate the change in dimensions
var clientWidth = document.body.clientWidth;
var clientHeight = document.body.clientHeight;
var scrollWidth = document.body.scrollWidth;
var scrollHeight = document.body.scrollHeight;
// move the div when the window is being resized
function resizeListener() {
var _clientWidth = document.body.clientWidth;
var _clientHeight = document.body.clientHeight;
var _scrollWidth = document.body.scrollWidth;
var _scrollHeight = document.body.scrollHeight;
// horizontal scrollbar is not enabled
if (_scrollWidth <= _clientWidth) {
div.style.left = parseInt(div.style.left.replace(/px/, ''), 10) + (_scrollWidth - scrollWidth) / 2 + 'px';
}
// vertical scrollbar is not enabled
if (_scrollHeight <= _clientHeight) {
div.style.top = parseInt(div.style.top.replace(/px/, ''), 10) + (_scrollHeight - scrollHeight) / 2 + 'px';
}
clientWidth = _clientWidth;
clientHeight = _clientHeight;
scrollWidth = _scrollWidth;
scrollHeight = _scrollHeight;
}
window.addEventListener("resize", resizeListener);
PS: Please, no jQuery solutions.
Since the resize listener isn't quite dependable with outside events, I've developed a simple "hack" to get the wanted results. The window overflow is forced to scroll and the body width & height are set to +1 so that the scrollbar is active, in which the div will then stay in place. Once the resize is complete, the overflow and body dimensions are restored. This may not be a desired solution for others who want the div to move on a manual window resize, but I am invoking the resize from JavaScript so it works perfectly for me.
The script in practice:
var overflow, overflowX, overflowY, bodyWidth, bodyHeight;
function startResize() {
// store the original overflow values
overflow = document.body.style.overflow;
overflowX = document.body.style.overflowX;
overflowY = document.body.style.overflowY;
bodyWidth = document.body.style.width;
bodyHeight = document.body.style.height;
// force the scrollbar
document.body.style.overflow = "scroll";
// activate the scrollbar
document.body.style.width = document.client.width + 1 + "px";
document.body.style.height = document.client.height + 1 + "px";
}
function stopResize() {
// restore the original overflow values; x & y are included because enabling the global overflow will update x and y
document.body.style.overflow = overflow;
document.body.style.overflowX = overflowX;
document.body.style.overflowY = overflowY;
// restore the original body width & height
document.body.style.width = bodyWidth;
document.body.style.height = bodyHeight;
}
Here is the problem. I have
<div id="main"></div>
I want to check user resolution and change his height according user resolution, using javascript?
Javascript:
window.onload = function() {
var height = screen.height
document.getElementById(main).style.height = height;
};
I even try this:
window.onload = function() {
var height = screen.height
var ele = document.getElementById(main);
if(ele.style.height == "auto")
{
ele.style.height = height;
}
else {
ele.style.height = height;
}
};
If you want set the Screen Height:
var mainNode = document.getElementById("main");
mainNode.style.height = screen.height + "px";
Screen Avail Height
Screen Height
DOMElement Client Height
Screen height is different from client height (document.documentElement.clientHeight).
Given a <textarea> with a fixed width, I would like its "active width" to be constant (in px). By "active width" I mean the area where the text appears.
When the vertical scroll bar doesn't appear, the "active width" equals to width. But, when the vertical scroll bar appears, the "active width" becomes smaller than width (I guess smaller exactly by the width of the scroll bar).
I thought to identify whether the vertical scroll bar appears or not, and if yes, to increase the width of the <textarea> by the width of the scroll bar. How could I identify the width of the scroll bar?
Is there a better approach?
(I'm interested in Firefox, if it makes the life easier.)
There is a jQuery plugin that can help with this: https://github.com/brandonaaron/jquery-getscrollbarwidth/blob/master/jquery.getscrollbarwidth.js
Also, from http://www.alexandre-gomes.com/?p=115
Here is some code that may help.
This creates a hidden <p> element at 100% width inside a <div> with a scrollbar, then calculates the <div> width - the <p> width = scroll bar width.
function getScrollBarWidth () {
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;
document.body.removeChild (outer);
return (w1 - w2);
};
Scrollbar width is simply (offsetWidth - clientWidth) in a borderless! element.
This function calculates it on the fly and caches the result for further use. No need need for percentage width etc.
var getScrollbarWidth = function() {
var div, width = getScrollbarWidth.width;
if (width === undefined) {
div = document.createElement('div');
div.innerHTML = '<div style="width:50px;height:50px;position:absolute;left:-50px;top:-50px;overflow:auto;"><div style="width:1px;height:100px;"></div></div>';
div = div.firstChild;
document.body.appendChild(div);
width = getScrollbarWidth.width = div.offsetWidth - div.clientWidth;
document.body.removeChild(div);
}
return width;
};
I believe this is a more straightforward solution: (assuming body {width:100%;})
function calculateScrollBarWidth() {
return window.innerWidth - document.body.clientWidth;
}
A solution to calculate the scrollbar width of any element (e.g. a div with overflow, or a textarea)
function calculateScrollbarWidth(element) {
if (!element) {
// Return the body scrollbar width, when no element was specified.
return window.innerWidth - document.body.clientWidth;
} else {
// When an element is specified, return its specific scrollbar width.
return element.offsetWidth - element.clientWidth;
}
}
Maybe you could put
overflow-y:scroll;
in your css. This forces the scrollbar to be present even when the text area is blank, so the width is always constant.
Using jQuery, simply write:
function getScrollBarWidth () {
var $outer = $('<div>').css({visibility: 'hidden', width: 100, overflow: 'scroll'}).appendTo('body'),
widthWithScroll = $('<div>').css({width: '100%'}).appendTo($outer).outerWidth();
$outer.remove();
return 100 - widthWithScroll;
};
I was looking for something similar - here is what i found
function measureScrollbar() {
var $c = $("<div style='position:absolute; top:-10000px; left:-10000px; width:100px; height:100px; overflow:scroll;'></div>").appendTo("body");
var dim = {
width: $c.width() - $c[0].clientWidth,
height: $c.height() - $c[0].clientHeight
};
$c.remove();
return dim;
}
Source : Slickgrid uses this - https://github.com/mleibman/SlickGrid/blob/master/slick.grid.js#L378
Or
Use Google Closure Library -link
/**
* Returns the scroll bar width (represents the width of both horizontal
* and vertical scroll).
*
* #param {string=} opt_className An optional class name (or names) to apply
* to the invisible div created to measure the scrollbar. This is necessary
* if some scrollbars are styled differently than others.
* #return {number} The scroll bar width in px.
*/
goog.style.getScrollbarWidth = function(opt_className) {
// Add two hidden divs. The child div is larger than the parent and
// forces scrollbars to appear on it.
// Using overflow:scroll does not work consistently with scrollbars that
// are styled with ::-webkit-scrollbar.
var outerDiv = goog.dom.createElement('div');
if (opt_className) {
outerDiv.className = opt_className;
}
outerDiv.style.cssText = 'overflow:auto;' +
'position:absolute;top:0;width:100px;height:100px';
var innerDiv = goog.dom.createElement('div');
goog.style.setSize(innerDiv, '200px', '200px');
outerDiv.appendChild(innerDiv);
goog.dom.appendChild(goog.dom.getDocument().body, outerDiv);
var width = outerDiv.offsetWidth - outerDiv.clientWidth;
goog.dom.removeNode(outerDiv);
return width;
};
I think this helps to get the width of scrollbar.
textarea.scrollHeight
gives the height so cant this be used..
CSS:
.scrollbar-measure {
width: 100px;
height: 100px;
overflow: scroll;
position: absolute;
top: -9999px;
}
Vanilla JS:
// Create the measurement node
var scrollDiv = document.createElement("div");
scrollDiv.className = "scrollbar-measure";
document.body.appendChild(scrollDiv);
// Get the scrollbar width
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
console.warn(scrollbarWidth); // Mac: 15
// Delete the DIV
document.body.removeChild(scrollDiv);
Solution by David Walsh
With jQuery:
var t = jQuery('<textarea/>').css({
position: 'absolute',
top: '-100px',
overflowX: 'hidden',
overflowY: 'scroll'
}).prependTo('body'),
w = t[0].offsetWidth - t[0].clientWidth;
console.log('bar width = ', w);
t.remove();
bar width = 18
I have a div with overflow set to scroll which essentially streams data line by line off a file. I'd like to scroll automatically to the bottom of the div whenever the stream overflows, but without using a "Click here to scroll to bottom" button.
I already know of the scrollTop = scrollHeight solution, but that requires some kind of event trigger on the client's side. I don't want this element to be interactive; it should scroll by itself.
Is there any way to achieve this?
A lot of the scrollHeight implementations didn't work for me, offsetHeight seemed to do the trick.
Pretty sure that scrollHeight tries to move it to the bottom of the height of the static element, not the height of the scrollable area.
var pane = document.getElementById('pane');
pane.scrollTop = pane.offsetHeight;
There's no way to automatically scroll an element to the bottom. Use element.scrollTop = element.scrollHeight.
If you don't know when the element is going to resize, you could add a poller:
(function(){
var element = document.getElementById("myElement");
var lastHeight = element.scrollHeight;
function detectChange(){
var currentHeight = element.scrollHeight;
if(lastHeight != currentHeight){
element.scrollTop = currentHeight;
lastHeight = currentHeight;
}
}
detectChange();
setInterval(detectChange, 200); //Checks each 200ms = 5 times a second
})();
Some old code of mine with a running example that will stay at the bottom when new content is added, if the user scrolls it will not more it to the bottom.
var chatscroll = new Object();
chatscroll.Pane =
function(scrollContainerId)
{
this.bottomThreshold = 25;
this.scrollContainerId = scrollContainerId;
}
chatscroll.Pane.prototype.activeScroll =
function()
{
var scrollDiv = document.getElementById(this.scrollContainerId);
var currentHeight = 0;
if (scrollDiv.scrollHeight > 0)
currentHeight = scrollDiv.scrollHeight;
else
if (objDiv.offsetHeight > 0)
currentHeight = scrollDiv.offsetHeight;
if (currentHeight - scrollDiv.scrollTop - ((scrollDiv.style.pixelHeight) ? scrollDiv.style.pixelHeight : scrollDiv.offsetHeight) < this.bottomThreshold)
scrollDiv.scrollTop = currentHeight;
scrollDiv = null;
}