Setting height auto of textarea causes scroll - javascript

I am trying to design a textarea which resizes itself according to the content. This is what I wrote -
HTML
<div class='container'>
<textarea data-autoresize='true'></textarea>
</div>
JavaScript
$('body').on('keyup input','textarea', function(){
var offset = this.offsetHeight - this.clientHeight;
$(this).css('height','auto').css('height', this.scrollHeight + offset);
}).removeAttr('data-autoresize');
CSS
textarea {
overflow: hidden;
width: 150px;
height: 150px;
}
However, this causes the container element to scroll to the top of the textarea on each character input when the text area grows in size and the container becomes scrollable. Is there any way to stop this scroll?
Edit
You can refer this fiddle - https://jsfiddle.net/07d6gsb1/

Your scrolling position is automatically set to the top of the focused element (the textarea). You'll have to manually set your scrolling position to the initial value, add this to your jQuery:
$('body').on('keyup input','textarea', function(){
var offset = this.offsetHeight - this.clientHeight;
var scroll = $('body').scrollTop();
$(this).css('height','auto').css('height', this.scrollHeight + offset);
$('body').scrollTop(scroll);
}).removeAttr('data-autoresize');
.scrollTop() takes the scrolling position of an element, scrollTop(n) sets the scrolling position of an element.
A working codepen:
http://codepen.io/robertspier/pen/GNLmoY

You can use this plugin autogrow.
You can try by pressing and hold enter key in textarea. Compare the effect with the other auto expanding textarea plugin....
$(function() {
$('textarea').autogrow();
});
note: you should include the needed js files...
To prevent the scrollbar in the textarea from flashing on & off during expansion/contraction, you can set the overflow to hidden as well:

Related

How to obtain the left, right, top and bottom position of scroll in a div in HTML with Javascript

I would like to draw a <div> box with fixed height, width and scrollbars and register the location of the scrolled view. I have found the function scrollTop but don't know how to get the bottom scroll location.
Which CSS do I need to draw the box with scrollbars?
How can I access the left, right, top and bottom position inside (relative to) the box with Javascript?
I would use these 4 numbers to draw a <div> inside.
Starting with your second question:
scrollTop is the vertical position (in px) of the scrollbar, relative to the top position. So if your scrollbar is at the very top, scrollTop = 0.
It's the same for scrollLeft, but horizontal.
You can set these values via js to bring the scrollbar to a certain position programmatically.
So, if you want to know when the scrollbar is on top, you simply register an event listener for scrolling and wait for scrollTop = 0.
To check if the scrollbar is at the very bottom, you need a bit of calculation since you need to know the scroll height of the container (scroll height - scrollTop = 0).
See the following code (using jquery but it also works with plain js) which fires an event when the scrollbar reaches start or end position (this is for horizontal scrolling, so you have to replace "left" with "top" and "width" with "height"):
$('#yourDivId').on('scroll', function () {
if (scrollbarIsAtStart($(this))) {
$(document).trigger("scrollbar.left");
}
if (scrollbarIsAtEnd(this, $(this))) {
$(document).trigger("scrollbar.right");
}
})
const scrollbarIsAtStart = (jQuery) => {
if (jQuery.scrollLeft() == 0) {
return true;
}
return false;
}
const scrollbarIsAtEnd = (e, jquery) => {
//Minus one, probably rounding issue!?
if (jquery.width() + jquery.scrollLeft() >= e.scrollWidth - 1) {
return true;
}
return false;
}
So there are two events triggered, one for the scrollbar reaching start position, one for the end of the container. Now, you can listen to these events and handle them:
$(document)
.on('scrollbar.left', {}, function (event) {
//do whatever you want to do
})
Regarding your first question, I'm not a css expert, but if I look at bootstraps table-responsive class (which enables horizental scrolling), it looks like this:
.table-responsive {
display: block;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
Vertical scrolling is enabled by default if you define a fixed height on your div and the data exceeds this size. You can of course override the width with a fixed value or a different percentage.

How to resize left floating div to accommodate right floating DIV?

How can I set up 2 html div tags, one float left (actually containing the Google Earth Plugin), one float right (initially hidden)?
The content of the right div will be dynamically populated with a number of different dialogs and then made visible. Once visible it's width can expand further.
I need the left div to shrink to accommodate the right div when ever the right div toggles from invisible to visible or whenever it's width adjusts.
Just adjust the width of your left div with some javascript?
Depending on your layout you can use % or px or whatever you prefer.
HereĀ“s a really simple example showing how to do it with a percentage based layout:
HTML
<div class="l">LEFT</div>
<div clasS="r">RIGHT</div>
<br>
<a>TOGGLE R</a>
JS
(function($) {
var visible = false;
$("a").click(function(event) {
event.preventDefault();
$("div.r").toggle();
$("div.l").css("width", 50+(visible*50)+"%");
visible = !visible;
});
})(jQuery);
Try it out in the fiddle here: http://jsfiddle.net/ZbzL5/
Here an example:
You have to make an event when the new div is get visible and change the width of the left div.
JS:
$(function(){
$("button").click(function(){
var precSize = $("#width_input").val();
var parentWidth = $(".wrapper").width();
var leftOldSize = $(".left").width();
var newSize = parentWidth * ( (100 - parseInt(precSize)) / 100);
$(".left").width(newSize);
$(".right").width( $(".right").width() + (leftOldSize - newSize));
});
});
jsFiddle
basically to make google earth aware that div size changed you need
google.maps.event.trigger(map, "resize");
reference : so g map resize
But in your scenarion you can also trigger the abovein the resize event of the right div using jquery. $('div').bind('resize', function(){})

Overflow: hidden but i still want to have the empty scrollbar

I set 'overflow:hidden' on my html body with Javascript when I press a button. But when I do that the whole body moves 5 pixels or so to the left because the space of the scrollbar is gone. How do i prevent that.
I can't set margin of the body to a specific size because the width of scrollbars differentiate between browsers
Since the previous solution does not work anymore (see original answer below), I've come across another solution which works for me and, according to MDN, it should work in all browser, with IE starting from version 6.
This solution to get the scrollbar width is even a bit simplified:
Append a div without a scrollbar to the body and position it off screen
Measure the client width of the div
Set the div to have a scrollbar (using css overflow style)
Measure the clientWidth of the div again
Remove the div
Return the difference of the two widths
And the code would look like this:
function scrollbarWidth() {
var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"></div>');
// Append our div, do our calculation and then remove it
$('body').append(div);
var w1 = div.prop('clientWidth');
div.css('overflow-y', 'scroll');
var w2 = div.prop('clientWidth');
$(div).remove();
return (w1 - w2);
}
And here is a working jsFiddle.
Original answer (for completeness sake)
Here is a solution to calculate the width of a scrollbar, which you can use in conjuction with some of the other answers here (and your own knowledge as far as I can tell).
The idea is to do the following steps:
Append two divs to the body and position them off screen
Measure the width of the inner div
Set the outer div to overflow
Measure the width of the inner div (again)
Remove the divs
Return the difference of the two widths
And here is the code, copied from the referenced page:
function scrollbarWidth() {
var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
// Append our div, do our calculation and then remove it
$('body').append(div);
var w1 = $('div', div).innerWidth();
div.css('overflow-y', 'scroll');
var w2 = $('div', div).innerWidth();
$(div).remove();
return (w1 - w2);
}
You could try this old trick:
html {
overflow-y: scroll;
}
What this does is force the scrollbar to always be visible.
Compare:
normal JSFiddle
JSFiddle with the vertical scrollbar always there
Here is code to add a disabled vertical scroll bar. If placed more prominent in CSS than the rest of the CSS, it should override whatever you've done to other portions.
html {
overflow-y: scroll;
}
You could always put a wrapper around the content that you are hiding and then place the overflow: scroll on div and overflow: hidden on the content div.
#wrapper { overflow-y: scroll; }
#content { overflow: hidden; }
See the attached fiddle for a working version
http://jsfiddle.net/15km/bfpAD/1/

How to keep jQuery function from moving elements all the way to the left?

I was able to implement the solution posted here ("position: fixed and absolute at the same time. HOW?") to get a div element to move with the rest of the page horizontally, but stay fixed vertically. However, this solution causes the selected element to move ALL the way to the left of the page (with what appears to be a 20px margin). I'm still new to javascript and jQuery, but as I understand it, the following:
$(window).scroll(function(){
var $this = $(this);
$('#homeheader').css('left', 20 - $this.scrollLeft());});
takes the selected element and, upon scrolling by the user, affects the CSS of the element so that its position from the left becomes some function of the current scrollbar position adjusted by the 20px margin. If this is correct? And if so, can anyone think of a way that I could change it so that instead of moving the selected element all the way to the left side of the window, we only move it as far left as my default CSS position for the body elements of the HTML document (shown below)?
body {font-size:100%;
width: 800px;
margin-top: 0px;
margin-bottom: 20px;
margin-left: auto;
margin-right: auto;
padding-left: 20px;
padding-right: 20px;}
EDIT: Here is a jsfiddle (code here) that I made to illustrate the issue. My page is designed so that when it is displayed in full-screen or near full-screen mode, the #homeheader element appears centered horizontally due to its width and the left and right margins being set to auto. As the page gets smaller and smaller the margins do as well, until they disappear altogether and are replaced by the padding-left and padding-right settings of 20px. So at this point (when the window is small enough that the margins disappear altogether), which is what the jsfiddle shows, the code appears to work as intended, but when the window is full-sized the JS overrides the CSS and pushes the div element all the way to the left (getting rid of the margin) upon any scrolling action.
There are two events you need to handle to get this to work correctly. First is the scroll event which you are pretty close on. The only thing you might want to do is to use offset to get the current left position value based on the document.
The other event which is not yet handled is the resize event. If you don't handle this then once a left position is defined your element (header) will be there always regardless of whether or not the user resizes the window.
Basically something like this should work:
var headeroffset;
var header = $('#homeheader');
// handle scroll
$(window).scroll(function() {
// auto when not defined
if (headeroffset === undefined) {
// capture offset for current screen size
headeroffset = header.offset();
}
// calculate offset
var leftOffset = headeroffset.left - $(this).scrollLeft();
// set left offset
header.css('left', leftOffset);
});
// handle resize
$(window).resize(function() {
// remove left setting
// (this stops the element from being stuck after a resize event
if (header.css('left') !== 'auto') {
header.css('left', '');
headeroffset = undefined;
}
});
JSFiddle example: http://jsfiddle.net/infiniteloops/ELCq7/6/
http://jsfiddle.net/infiniteloops/ELCq7/6/show
This type of effect can be done purely in css however, i would suggest taking a look at the full page app series Steve Sanderson did recently.
http://blog.stevensanderson.com/2011/10/05/full-height-app-layouts-a-css-trick-to-make-it-easier/
As an example you could do something like this:
http://jsfiddle.net/infiniteloops/ELCq7/18/
Try this
$('#homeheader').css('left', parseInt($('body').css('margin-left')) - $this.scrollLeft());});
What I did here is just replace 20 with body's left-margin value.

Browser Auto Scrolling for tabbing through form elements

When tabbing to a form field that is below the bottom of the viewport (or typing in a textarea that overlaps the bottom), browsers usually automatically scroll up enough so that you can see the field. Is there a way to set the position the browser moves to?
This is an issue because I have a fixed position bar at the bottom of the page and so it covers up where the browser scrolls to and would like it to scroll up further.
Cheers
Sure, you could add a focus event handler to your inputs and check their position onfocus. If it's too close to the bottom, just bump the window scroll a bit until it's acceptable.
Below is how you could do it in jQuery:
// Constant amount of padding an element should be from the bottom of the window
var padding = 50;
// Add focus event to all your different form elements
$("input, textarea, select").focus(function(){
// Check their position relative to the window's scroll
var elementBottom = $(this).offset().top + $(this).height();
var windowScroll = $(window).scrollTop();
var windowBottom = windowScroll + $(window).height();
if(elementBottom + padding > windowBottom){
$(window).scrollTop(windowScroll + padding);
}
});
You can see it in action here.
Edit: Typing in textarea
You could capture and check the position of the textarea during typing using the keydown event handler:
$('textarea').keydown(function(){
// same logic as above to check textarea position relative to window
});

Categories