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
});
Related
When I click my button, I append a new div. I would like that, if any part of the div is not visible to the window, scroll untill it shows.
So if it is upwards from the center of the window, scroll up JUST until you see it's top, and if it is downwards from the center, scroll down just until you see its bottom.
In my searchings I found https://api.jquery.com/scrollTop/ , but that doesn't seem to be what I'm describing
I only want to scroll enough to display it entirely on screen, not always on top
Check this working fiddle for the solution.
You can use scrollTop() to scroll to any div. First we need to find the direction of the scroll to correctly provide the value for scrollTop() function. This can be found using position().
$('#button4').click(function() {
// check if the div lies below the button
if ($('#div3').position().top - $('#button4').position().top > 0) {
// in this case we need to add shift
var shift = $(window).height() - $('#div3').height();
} else {
var shift = 0;
}
$(window).scrollTop($('#div3').offset().top - shift);
});
Alternatively if you wish to check the position of the div relative to the current viewport (or the center of the current window view) you can use getBoundingClientRect() like:
$('#button4').click(function() {
// check if the div lies below the viewport
if ($('#div3')[0].getBoundingClientRect().top > 0) {
// in this case we need to add shift
var shift = $(window).height() - $('#div3').height();
} else {
var shift = 0;
}
$(window).scrollTop($('#div3').offset().top - shift);
});
Here is the alternate fiddle.
So if you are using jQuery.
//scroll top of element
var $myNewElement = $(".new-element-class");
$('html, body').scrollTop($myNewElement.offset().top)
I think this should work. Make sure your div is appended before calling the scrollTop function.
If I understand correctly, this jsfiddle is what you are looking for.
I also added a simple animation so the document doesn't awkwardly jump around the viewport.
Features
If a new element is created, and part of that new element is below the current viewport, the document will be scrolled until the bottom of the viewport is shown. Vice versa if part of the new element is above the current viewport.
If the new element is completely visible within the current viewport, no scrolling will occur.
All scrolling effects are animated.
A configurable offset (Leave some padding instead of scrolling to the very edge of the new element)
How it works
When the button is clicked, a new div element is appended.
$('section').append('<div>');
Next, we figure out if this div is above the current viewport using the below function:
function isElementAboveViewport(element) {
return $(element).offset().top < $(window).scrollTop();
}
in an if statement:
if (isElementAboveViewport($('section > div:last-child'))) {
...
}
If the condition is truthy, we scroll! (offset is configurable - In the JS fiddle, I used 40 which is the height of the button covering the top 40px of the viewport)
$('html, body').animate({
scrollTop: $('section > div:last-child').offset().top - offset
}, 1000);
Now, we check if the new element is below the current viewport with a similar function:
function isElementBelowViewport(element) {
return $(element).offset().top + $(element).height() > $(window).scrollTop() + $(window).height();
}
If the element is too far down in the document, we scroll! (Again, offset is configurable)
$('html, body').animate({
scrollTop: $('section > div:last-child').offset().top + $('section > div:last-child').height() - $(window).height() + offset
}, 1000);
Please let me know if this is what you were looking for and/or if you have any questions about how it works.
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:
I have a page with the following functionality: there is a large image that generates scoll (both horizontally and vertically) and a button in a fixed position (it remains in the top left corner, even with scroll) that, when clicked, fits the image to the client width.
Since position: fixed is not supported in Internet Explorer 8, I used a workaround - this is the function:
function setFixedPosition(jqueryWrapper, pixelsFromTop, pixelsFromLeft) {
jqueryWrapper.css('position', 'absolute');
var setOffsets = function() {
jqueryWrapper.css("top", (($(window).scrollTop() + pixelsFromTop) + "px"));
jqueryWrapper.css("left", (($(window).scrollLeft() + pixelsFromLeft) + "px"));
};
setOffsets();
$(window).scroll(function() {
setOffsets();
});
}
setFixedPosition($('#zoomFitButton'), 15, 15);
This is the button's action:
$('#zoomFitButton').click(function() {
$('img.preview').css('width', '100%');
});
The button remains fixed both in Firefox 13 and IE8.
But, under IE8, if I am scrolling somewhere, then I click the button, the button moves to a "strange" position:
If I scroll vertically, then click, it puts the button in the lower-left corner;
If I scroll horizontally, then click, it puts the button in the upper-right corner;
If I scroll both ways, then click, it puts the button somewhere in the center.
In Firefox, the button always remains in the upper-left corner (the place where I expect it to be), even after I click the fit to width button.
Here is a test page.
Is my code OK for this functionality (in principle), or I need to add something to the fit to width action (to fix my button positioning); or there is something wrong with IE (and I need a workaround - if so, any suggestions?)?
Thanks.
I found a solution that works in IE6 also.
I think the problem has something to do with IE not updating the scrollTop and scrollLeft positions after the document is resized.
So, after I resize the picture, I have to scroll to the upper-left corner (scrollTop(0) and scrollLeft(0)).
Unfortunately, if I have a large picture that needs vertical scrolling even when it's fit to width, the workaround brings me to the top of the page. So I added code to bring me back proportionally to the aproximate position I was before. I wrapped the logic in a more generic function:
function doSomethingThatAffectsScrollPosition(affectingScrollPositionFunction) {
var oldDocumentWidth = $(document).width();
var oldScrollFromLeft = $(window).scrollLeft();
var oldDocumentHeight = $(document).height();
var oldScrollFromTop = $(window).scrollTop();
affectingScrollPositionFunction();
var newDocumentWidth = $(document).width();
var widthRatio = (newDocumentWidth / oldDocumentWidth);
var newScrollFromLeft = (oldScrollFromLeft * widthRatio);
var newDocumentHeight = $(document).height();
var heightRatio = (newDocumentHeight / oldDocumentHeight);
var newScrollFromTop = (oldScrollFromTop * heightRatio);
$(window).scrollLeft(0); // Needed for button repositioning
$(window).scrollLeft(newScrollFromLeft);
$(window).scrollTop(0); // Needed for button repositioning
$(window).scrollTop(newScrollFromTop);
}
And I used the function in the fit to width button's action:
$('#zoomFitButton').click(function() {
doSomethingThatAffectsScrollPosition(function() {
$('img.preview').css('width', '100%');
});
});
Here is a test page.
I am working on a small jQuery plugin that autoscrolls through a set of overflowing elements within a container div based on the mouse position within that container div.
See the Demo Here
The idea is for this plugin to be an improvement of something I wrote a while ago. See the autoscrolling navigation in the lower left here The old problem with this was that it jumps around when you mouseenter from anywhere but the bottom(javascript perspective) of the container div.
Now everything is working fine with my plugin but when you mouseenter from the top it screws up from time to time(move your mouse in and out fast and it will happen for sure), I think this is because I am getting different values from my mouseenter event and my mousemove event which are both used to calculate how to scroll the inner elements. Here is the function, the rest of the source is pretty small and decently commented.
projList.mousemove(function(e){
//keep it from freaking out when we mouseenter from Top of div
if(enterMouseY > divHeight){
enterMouseY = divHeight;
}
mouseY = e.pageY-projList.offset().top;
//ok that didnt work... try to keep it from freaking out when we mouseenter from Top of div
if (mouseY > divHeight){
mouseY = divHeight;
}
//distnace from top of container div to where our mouse Entered
var distToTop = divHeight - enterMouseY;
//here is the calculation, I parameterize the mouseY pos as a value between 0-1
//0 being where we entered and 1 being the top or bottom of the div
//then multiply that by how much we have to scroll to get to the end of the list
//are we moving up or down
if(mouseY>enterMouseY){
//if up calculate based on Top
var dist =totalScrollDistance * ((mouseY-enterMouseY-projList.offset().top)/(distToTop));
}else if(mouseY<enterMouseY){
//if up calculate based on Bottom
var dist =totalScrollDistance * ((mouseY-enterMouseY-projList.offset().top)/(enterMouseY));
}else if(mouseY = enterMouseY){
var dist = 0;
}
//set the position of the list offsetting wherever we left it
pos = dist+lastPos;
//scroll to that position
projList.scrollTop(pos);
//are we trying to scroll past the scrollable amount
if(pos<0){
pos = 0;
}
if(pos>totalScrollDistance){
pos = totalScrollDistance;
}
$('#div1').text("mouseY: "+ mouseY +" enterMouseY: "+ enterMouseY +" distance:"+ dist.toFixed(1) + " pos:"+ pos.toFixed(1));
});
I solved this problem, there was an error in my calculations, but works how I described above.
You can see it in action here
http://web.archive.org/web/20130529212243/http://www.robincwillis.com/AutoScroll/
I have a number of form fields spanning over the page fold. When pressing the "tab" key to step through each input/select field it sits the next field on the bottom of the page fold.
A few of my fields have tool tips, validation responses and auto suggest boxes that appear below the field. When tabbing to the field, you can't see these elements below the page fold.
Is there a javascript or jQuery script that can vertically centre the screen around a focussed input/textarea/select/button field instead of aligning to the bottom?
You can just bind to the focus event and then calculate the offset of the field and center it on the screen.
$(':input').focus(function(){
var center = $(window).height()/2;
var top = $(this).offset().top ;
if (top > center){
$(window).scrollTop(top-center);
}
});
Same from above with smooth scroll effect
$(':input').focus(function () {
var center = $(window).height() / 2;
var top = $(this).offset().top;
if (top > center) {
$('html, body').animate({ scrollTop: top - center }, 'fast');
}
});
Easiest thing would be to include the jQuery ScrollTo plugin and the jQuery Viewport plugin.
Then wrap every input + related other elements (validation response, ....) in a div.
On focus check if the div is completely visible, if not use scrollTo. Done.
Of course this is a bit of a bloat but if you can live with the 2 more dependencies and an additional ~4kb this should work without doing the calculations yourself.