UIWebView scrollTo should behave smoothly - javascript

I do not know if i asked correctly in Question Title, but here i am going to describe in brief
I have an UIWebView and loading the content based on div and each div has unique id on loadRequest.
As though my content was too large so i break down into pieces and loading the remaining content once you tap on 'Read More'
This 'Read More' event fire on autoscroll which i am handling through javascript. so once that event is fired it just append data (for which i have another method) by using window.location.href = div1+div2(its just an example).
Now the main problem is when i scrollDown and wherver i get the 'Read More' message and it auto fire then it adds the data to the current div and show (User feel its an continue reading) but when
I scroll towards to up
It behaves weired because it just append the data to the div and scroll to setYScroll(updatedlocation);
updatedlocation is used for when we are adding the content to the div and it should scroll to the same position where the user was.
so lets start with an example, assume currently i am reading the div2 and when i scroll up'Read More' events fired and add div1 to div2 and then web view delegate shouldStartLoadWithRequest called.
so every time its update the content to div2 when you are scrolling up but first it takes me the previous s location of div1 and then take me to div2 location where i was currently reading.
so it feel like really weired, suddenly it takes me to somewhere for a while and take me to my current position within friction of second
I tried with this solution,
I thought to take the screen shot and create an imageView with that screenshot image of the current UIWebView and put on webview whenever 'Read More' event is happening. once the web view loading is done remove the imageView and display the webview.
but this is happening in the same way, the problem is every thing is happening under the webview delegate. i still could not figure out whats happening? The solution of this problem am i on right trackj or is there any better solution for that

I have a similar situation. What I do is have two UIWebViews on top of each other. When it is time to update one view, I grab the scroll position, load the new data in the hidden UIWebView, when the other UIWebView is done loading its data it sets its scroll position to the current scroll position of the first webview, then hides the first webview and unhides itself.
Its pretty seamless and works very well.

I suspect that the "jump" you experience depends on the fact that the web view is fully redrawn (and we all know that UIWebView is slow).
So, I see 2 options:
implement the "Read more" mechanics fully in javascript by means of Ajax;
instead of loading data into the view using loadRequest, make a NSConnection to that url and then update the web view by injecting in it the HTML you got from NSConnection through stringByEvaluatingJavaScriptFromString.
The second option is possibly nicer because it is fully SDK based, but you will readily see that it is far more complex than the first one. The two of them will work and I am pretty sure that will give you the kind of smooth behavior you are after.

If I understand your question correctly it sounds like you're trying to implement your own handling of the "infinite scroll" concept.
It might be worth your while to check out one of the many infinite scroll libraries that are already out there. If one doesn't fit your requirements perfectly you might find the inspiration you need to fix the one you have now.

Related

How to implement "Skip to content" accessibility functionality on React?

When we are using keyboard only and tab through the website, the first anchor link for "Skip to a content" is shown to skip the navigation and focus to the main content which makes the web page accessible. It is easy to add such a feature on multi-page website where there is full page reload and the focus for the page resets. I am looking similar behavior on the React. How can we implement such behavior on a Single page application built on React?
I disagree with Graham that you shouldn't need a skip to content link. In a SPA, when the user navigates to a new "page," the focus remains on the link that was pressed. Every time your user wants to navigate, they're going to have to go through the remaining nav menu to get at the content.
You could either move focus to the beginning of the document so they hit your 'skip to content' link each time (has its merits because it's most like multi-page apps which they're likely to be familiar with) or move it to the content body itself and save them a click (seems more streamlined to me, but might be unfamiliar to your users).
componentDidMount() {
setTimeout(() => document.getElementById('your-element-of-choice').focus(), 0)
}
I'm leaning toward the latter, but this will work either way you decide to implement it. Don't forget to set the tab index on the element you want to focus on to -1 as well.
You shouldn't need a skip to content link on a SPA other than the one you already have (for first time load for return visitors).
Skip to content is for when you click a link to a new page, it helps avoid having to listen to the menu every time you navigate.
With a SPA that isn't an issue as everything is done via AJAX, when I click a link a region on the page will get updated with new content.
All you need to do is move focus to the region that is being updated from the menu item.
Certain screen readers will need explicit ARIA Live Regions in order to register the new content so make sure you test it with a screen reader.
Where you will run into accessibility problems pretty fast in SPAs are when you start thinking about delays.
What happens if I click that link and the page takes 3 seconds to load?
What happens if the page doesn't load at all?
Those are your bigger challenges with a SPA.

Preventing re-paint in Google Chrome via CSS/JS/etc

Is it possible to cause Google Chrome to prevent painting... as in, to keep the page exactly the same, no animations or content changes.
The reason I ask is because I have created an extension for people who find it difficult to read webpages when things are animating/flashing/changing/etc.
It currently works by taking a screenshot and layering it over the page (position absolute, with a high value z-index).
But because captureVisibleTab cannot capture the whole page (issue 45209), the screenshot needs to be re-created every time the user scrolls the page.
However the change in iOS 8 Safari to not pause printing while scrolling got me thinking there may be another way around this by trying to emulate the pre iOS 8 behaviour (something I preferred, as Reader View does not always work, or stop animated gifs).
You cannot stop the execution thread, its browser who decides it.
However to prevent CPU Cycles What chrome does is, Pauses the javascript execution thread when window is blurred. But since you are showing captured with higher z-index you window will still be active.
One possible way :
Disable the script for that url when the page is loaded.
You might miss the dynamic content but as you asked "no animations or content changes". Any dom or style manipulations by javscript causes repaint of the page. Disabling it might be one solution. However not pretty sure about how to stop css animations.
I have also seen extensions that can capture full webpage image or pdf. you can capture the full page and show them irrelevant of whatever changing in the background

jquery AJAX backbutton problems

This is a bit weird to explain so ill do my best.
Im working on a mobile site that im trying to shape into an ios app (eventually).
On this page i have a menu button that on click, shows/hides menu.
Everything for the most part is working but, the problem is that when you click on the "back" button and the browser runs out of previous locations to go back to, the menu button breaks. When you click it, nothing happens. it behaves as though nothing is there.
The errors go like this, if on index(or first page), you click ONE link to go forward, and then on the browser hit the back button, it breaks instantly.
If your on the index, and hit for example, 5 links in any order(essentially you went forward 5xs) and thereafter, you hit back up to 4xs, the menu still works....you can essentially keep pressing links forward and be fine, hit back as far as you want and stop short one less than the total times you went forward and still be fine.
As soon as you hit the maximum backs, and theres nothing left in the history of page locations to go back to, the menu then breaks.
here is the link of this dummy site im working on (on my server)
NOTE: to test, when it loads, manually shrink the browser to about 400 width so you can see the page take effect.
EDIT** woops forgot the link
http://somdowprod.net/4testing/mobile/less1.html
and here is my code
javascript:(i left comments in there, so you can see where my logic is at...maybe im going about it wrong?)
// JavaScript Document
$(document).ready(function(){
var newHash = "";
var menuBtn = $('.leftButton');
//~~~~~~~~~~~~~~~~~~~~~~~~~~~menu show/hide
menuBtn.click( menuShowHide);
//===========================//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~MENU SHOW / HIDE
function menuShowHide(){
$('#menu').toggleClass();
// if($('#menu').css("display") == "none"){
// $('#menu').css("display","block");
// } else {
// $('#menu').css("display","none");
// }
scroll(0,0);
}
//===========================//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ACTIONS FOR THE is-loaded trick.
function isLoaded(){
$('#progress').remove();
}
//===========================//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ACTIONS FOR THE HOME PAGE
if(newHash == ""){
$('body').append('<div id="progress">Loading...</div>');//attach this div which is made to look like a loading bubble.
$('#contentHere').load('index.html #content', isLoaded);//load the content div from the index.html file
}
//===========================//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~Load the clicked content into my container via jQuery AJAX
$('#menu a').click(function(){
menuShowHide();
window.location.hash = $(this).attr('href');
return false; //doesnt let the link jump to a new page
});
$(window).bind('hashchange',function(){
newHash = window.location.hash.substring(1);
$('body').append('<div id="progress">Loading...</div>');//attach this div which is made to look like a loading bubble.
$('#contentHere').load(newHash, isLoaded);
//console.log(newHash);
});
//===========================//
});
Anyone have any ideas as to whats making the menu break? Thanks in advanced.
The hashchange event is known to be unpredictable with the browsers back button.
Here's what's happening. When you back all the way to the beginning, the whole less.html page is being loaded into its own 'contentHere' container, and since document.ready won't be called on this subpage, no menuButton.click handler will be assigned to the links, so clicking them will not do anything.
Although being able to use your browsers back and forward buttons on asynchronous changes would be a neat feature, I don't think people would miss it enough for you to try to hack a workaround. People are used to not being able to use the back and forward button on asynchronously loaded content. They would try it once, see that it takes them to your site's referrer, hit forward, and subconciously make a mental note to use your menu instead of the back and forward buttons.
Probably a better suggestion, however, is to get rid of the AJAX feature altogether and let the links act the way that people expect them to. Okay, so you lose the cool 'Loading' modal and you save the user a tiny bit of time, but then you aren't confusing people's expectations about your interface.
Edit: to answer your question below, instead of using load() to get static content (which is overkill), put all of the content as sections in your less.html file and hide/unhide it using the menu selections. Here are two ways to accomplish this, each with their own advantages and disadvantages:
Fix your header with CSS (including the menu) (example: lifeinthegrid.com/simple-css-fixed-header/) and then make your menu links normal anchor links with no JavaScript event handler. When you click a link in the menu, the content jumps to that section and because your header is fixed, it has the feel of being a very fast httpRequest. Advantages: minimal JavaScript, the browser's back and forward buttons will work. Disadvantages: fixed elements are a nuisance on older smartphones, the next section might sneak into the bottom of the viewport and ruin the illusion. Solution: put more space between them.
The other method is to use show()/hide() on the different content sections. So let's say you click 'about us'. All of the sections are hidden and the 'about us' content is shown. Advantages: It's not as annoying as a fixed element, you can spice it up with FadeIn()/FadeOut() or other JQuery animation effects. Disadvantages: your browsers history will not track these changes unless you do some window.location hackery.

Repainting a page in Chrome?

I've been looking at using a script I've found online (here) as a basis for a website I'm looking to create. It has an issue in Chrome in that the page wont scroll once a link is clicked, however if I resize the window just a tiny bit the page "repaints" - I think this is the right term - and all is well again.
Is there anyway to do a repaint like this? I don't mean refresh :)! Sorry if this seems a bit vauge, if you try this link in chrome, press one of the links in the header and you'll see the problem when trying to then scroll.
Initially I'm thinking there might be some javascript I can call at the end of switching pages that repaints the page.
Thanks
You could try doing something like this after the slide has completely transitioned to a new page:
Since you've commented that it didn't work as I originally suggested, here's a way to "encourage" Chrome to do the hide/display trick:
$(".slide.loaded.prev").css("display", "none");
setTimeout(function() {
$(".slide.loaded.prev").css("display","");
});
or you could try this:
var slide=$(".slide.loaded.prev");
slide.css("display", "none").height(); // just get the height to trigger a relayout.
slide.css("display", "");
The above code simply finds the previously visible slide, sets the CSS property display to none (hiding it completely) and then removes it. This trick worked when using the Chrome developer tools.
It appears that the scroll bar is for the previous "slide" in Chrome. By toggling the display of the slide briefly, the scrollbar is hidden under the now current "slide's" content.

How to set a default location of a scrollbar

in my web page there is a chat window. When the chat's log is filled out, the user uses scrollbar in order to navigate between messages. I want my chat frame to present always the last message that is located at the bottom. How can I do this using CSS, JavaScript?
Thanks,
Tomer
Even thou is not a tag on your question here is a jQuery solution i use for my chat web app:
//Where chat_message_tray is the scrollable div in your chat
function chat_scroll(chat_messages_tray){
var scroll_amount = $(chat_messages_tray).attr("scrollHeight") - $(chat_messages_tray).height();
$(chat_messages_tray).animate({ scrollTop: scroll_amount}, 500);
}
DOM elements (the good ones, anyway) support a method called scrollIntoView(). If you have a reference to the DOM element corresponding to the last chat entry (a <div> or whatever) you can use scrollIntoView() to tell the browser that its surrounding content should be scrolled in order to make the <div> visible.
Now, with some complicated (or not-so-complicated, maybe; perhaps just unlucky) page layouts, I've had to contend with Internet Explorer wanting to scroll the wrong thing, or just do something weird to the page. The nature of a thing like scrollIntoView() is such that you're letting the browser decide exactly how it wants to do that scrolling. Generally, with fairly simple content in a simple scrolling container (one with "overflow: auto" and a fixed height, basically), it does work however.
http://radio.javaranch.com/pascarello/2005/12/14/1134573598403.html
3rd result from Google - 'div scrollbar bottom'

Categories