Slide parent DIV to top when input field is selected - javascript

When someone clicks on a specific input field on my website, particularly on a mobile device, I need the parent div of the input field to slide to the top of the page. I need this because the keyboard that pops up covers the entire div below the input field, which is showing the user the items that they are filtering through. I've laid out the problem below graphically. I'd appreciate some guidance here :)
Starting state:
Finished state:

something like this oughtta do:
$('input').focus(function (event) {
var offset = $('header').height();
$('body, html').animate({
scrollTop : offset
})
})
JSBin

Related

On input click, keep input field visible when virtual keyboard

I got a challange here and would like to get some help from your experience.
This app has floating (sticky) header (where you see store details and the tabs with Details and Contacts) and also a floating (sticky) bottom bar and the content scrolls behind them.
When a user clicks on an input field the virtual keyboard shows up.
The problem is, when the virtual keyboard shows up, if the input field is in a place where the bottom bar will stay, the input stays covered by the bottom bar.
For example the city field was near the center and the user clicked it, the virtual keyboard is shown and the input field for city is covered by the floating bottom bar.
The expected result was that the city field should be placed right above the BottomBar.
I am using window resize event to detect when the keyboard shows up. I am also using a document.querySelector(":focus") to detect the item "clicked" and checking if it's an input or textarea using the nodeName.
I have tried to apply element.scrollIntoView({block: "center"}); but if the element is initially at the center of the screen it will not scroll and will be covered by the bottom bar when the virtual keyboard shows up.
This is the javascript I am applying currently:
var inputs = document.querySelectorAll("input, textarea");
var container = document.querySelector(".screen > .content");
window.addEventListener("resize", function(e) {
var targetEl = document.querySelector(":focus");
var bottomBar = document.querySelector(".bottom-bar-wrapper");
if(targetEl.nodeName.toLowerCase() === "input" || targetEl.nodeName.toLowerCase() === "textarea") {
var scrollY = Math.floor(targetEl.getBoundingClientRect().top + targetEl.getBoundingClientRect().height + bottomBar.getBoundingClientRect().height);
container.scrollTo(0, scrollY);
}
});
It's the solution that has worked best so far but not sure if it's the more eloquent one.
The challenge part is that when a user is already typing on an input and click on another input the scroll calculations return wrong values and it scrolls to a very strange position where the clicked input is not even close.
What can be happening for the position of the elements to return wrong values?
How would you approach this?
I've created a mockup on JSFiddle that kind of replicates the issue, html and css wise.
https://jsfiddle.net/marioandrade/L5f2n3vm/14/
Thanks for your help in advance.

Angular js do not scroll when list element height change

I have a list of elements. Each element has an expanded and collapsed state.
When user expands one of the element, all other elements need to collapse. The list is inside a div which could be scrolled to allow seeing the entire list.
element 1
element 2
element 3
element 4
element 5
Lets say, element 1 is in expanded state. When I expand element 3, I collapse element 1. The problem is that when I do that, element 3 scrolls up. I want to avoid this and position element 3 to same position.
This is a pseudo code. There could be some minor syntax errors, but do ignore them, since my actual code has lot more going on and I don't want to paste the entire thing here.
The controller will include expand function like:
public expandElement(currentElement: any, previousElement: any) {
// get the height of previous element
var scrollOffset: number = angular.element("#" + this.getAnchorId(previousElement).offsetHeight;
// this function will collapse the element decreasing the height of it
previousElement.collapse();
// scroll to the newly expanded element
this.$timeout(() => {
var anchorId: string = this.getAnchorId(element);
var element = angular.element("#" + anchorId)[0];
var offset = element.getBoundingClientRect().top + scrollOffset;
this.$anchorScroll.yOffset = offset;
this.$location.hash(anchorId);
this.$anchorScroll();
});
previousElement = currentElement;
}
The html will look something like:
<div ng-repeat="element in listElements"
id="{{getAnchorId(element)}}">
<my-directive ng-click="expandElement(element, previousElement)"></my-directive>
</div>
This currently is not working at all, but even if I get it to work, there would be a small UI jump that could happen. I want to avoid scroll completely.
Is there another easy way to just block the scroll when angular expands an element?
Appreciate the help.
Thanks!
I got your problem, but i have one question. Consider you have more elements in the list and you will expand say 50th element then it has to scroll the main container to show the content of that expanded panel, i think it is the desired functionality in the scroll. I know i am not answering your question but, just thought of reconsidering it.
Probably you have to save scroll position and after click function got triggered change the scroll position back to saved state. There could be flick effect. If you want to hide the flick effect, hide the div show with a slow animation. Hope it helps.

Scrollup to textarea when keyboard is up

In my ToDo list app, I have a text area that is appended at the end of the list. The problem right now is that when I tap on the textarea, the keboard shows up but the textarea is behind the keyboard and the page doesnt scrollup unless I start typing. As you can imagine, this is not a good UX.
How do I scrollup to the textarea as soon as the keyboard shows up?
EDIT: This is an observation in the simulator version 2.0
I fixed it by scrolling to the container's bottom for onClick event:
$(document).on("click", "#new_todo_item",function(){ // scroll to bottom when clicked on input textarea
$("#todo_list_container").animate({ scrollTop: $(document).height()+$(document).height() }, 1000);
});
I had to add up $(document).height()+$(document).height() since one height didnt really scroll to the bottom. The downside is that there is no animation now.

jQuery scrolling out of view issue

I am working on building a schedule. So far it's pretty straight-forward. There is one bit of functionality I am having issues with.
I have an ul that has a fixed height to allow scrolling. There are "Labels" (li.dayLabel) withing the ul that separate the hours. What I am trying to do is to have it so that when a label is scrolled out of view it will change the text in the placeholder to it's text. Then once that works, I need it to work in reverse. So when they label scrolls back into view it updates the placeholder. Basically, I am trying to make the placeholder be a title for the available items until another label is then scrolled out of view. This is for scrolling from the top. So as you scroll down the list the placeholder is meant to be a title for the section you are viewing until you reach another section and it takes its place. Then when you scroll back down I need it to replace the text with the previous li.dayLabel so the sections stay organized. I hope this makes sense.
You can see what I am trying to do by looking at the original that I am basing this off of. Notice how the placeholder changes as you scroll down the list and changes back when you scroll back up.
Demo: jsFiddle // Note: line 54 is the part that is in question
I originally used:
$(".snlf-schedule-list li.dayLabel:visible:first").text();
as the :first selector is suppose to only match a single element.
I later tried:
$(".snlf-schedule-list li.dayLabel:visible").filter(":eq(0)")
as this is suppose to be the same thing.
It seems that when an element is out of view it still is considered :visible I believe this is my issue.
Am I doing this completely wrong? I was under the impression that when you scroll an element like this it should no longer be :visible. After reading the documentation I have learned that this is not the correct selector to use.
It would appear that scrollTop is how I should be doing this. Now I have used scrollTop for scrolling down pages to disable animations when not in view but I am not clear on how to untilize this for a ul with scrollbars.
I tried:
var _first = $('li.dayLabel:first'); // next element to scroll out of view?
if( $(this).scrollTop() > (_first.offset().top+_first.height())) {
// Out of view
console.log("out");
} else {
// in view
console.log("in");
}
Updated Demo: jsFiddle
But it seems to be redundant as it's already calculating the first element so I am not sure how to get the correct element (the next one that's about to scroll out of view.) Then I need this to work when they scroll back up...
Any insight on this is much appreciated. Hopefully it's something simple I am just over complicating or missing completely.
Thanks,
Jeremy
The solution for my case was:
// Set placeholder text on scroll
var _scrollCagePositionTop = $(".snlf-schedule-list").offset().top;
var _first = $('li.dayLabel:first'); // first dayLabel element
$(".snlf-schedule-list").scroll(function(){
var _lastOffText = $(_first).text();
$("li.dayLabel").each(function() {
if ($(this).offset().top < _scrollCagePositionTop) {
_lastOffText = $(this).text();
}
});
$("#schedule-placeholder").text(_lastOffText);
});
What I did was set the known position of the top of the scroll cage (_scrollCagePositionTop)
When the user scrolls I set a variable _lastOffText that keeps track of the last item text content when scrolled out of view (less offset top than the palceholder). I then set this value to the placeholder.
This method allows me to have the proper text in my placeholder when the user scrolls up or down.
To fix the issue of an empty placeholder when the user scrolls back to the top I just set the default of _lastOffText to be the text of the first label ($(_first).text())
Hope others find this useful.
Here is the working demo: jsFiddle Final

How to scroll down the page when a covered input box is focused?

Take a look at this page.
I have a page with a lower 'floating' fixed-position div that's covering some portion of the screen bottom of the screen, with a high z-index, and a bunch of input boxes.
The problem is that when one of the lower input boxes are focused, by pressing TAB, their content is partly hidden by the div. I would like to detect when lower input boxes are focused, and scroll the page down "just enough" to bring them to a visible spot.
Is there a clean way to do this?
Edit: my solution seems to work except for browser zoom. Try it at zoom 144% for example. Any ideas on how to fix?
element.scrollIntoView();
supported in all mayor browsers ie-6-7-8-9-10 firefox, webkit
or:
element.focus(); element.blur();
Here is a solution by a friend of mine.
Seems to work well across browsers.
There still is one minor annoyance that the element has a larger border when selected, and part of that enlarged bordered remains hidden. I could always just add an extra pixel or two to the scroll, but I'm sure there must be a more elegant solution.
Ripper234's solution worked well for me. The following solution is for anyone whose field is covered by an element above it (such as a fixed nav) rather than below it.
I've also animated it using jQuery and added a padding variable which is useful if you have a label above the field that you want to show, or want to center the field (just set padding to half of screen height).
var navHeight = 200;
var padding = 25;
$('input').on('focus', function() {
try {
var elemTop = $(this).offset().top;
var maxVisible = $(document).scrollTop() + navHeight;
if (elemTop < maxVisible) {
$("html, body").animate({ scrollTop: elemTop - navHeight - padding }, 250);
}
} catch (e) {
console.log("Error: " + e);
}
});
What if you add an onfocus handler on each textbox and verify whether their position is too close/far to the "bottom-box" element and when so you change the position of this div element accordingly (move it down/up).
I would just use Z-index to pop the focused input above the fixed div
I don't think there is any common way of moving the screen down, maybe I'm wrong..
perhaps you can do it with in-page links like this as they are designed to pull the screen down, use JQuery to say "when this input is in focus go to the corresponding anchor point"
<input type="text" />

Categories