Hiding and showing div during page scroll on iphone - javascript

Need to display an element (div) ontop of webpage. During scroll the element should disappear and reappear after scroll ends.
To add to the complexity:
our code is a guest code (thus we cannot manipulate DOM structure etc).
our code is intended to work on iPhone/iPad (mobile Safari browser)
We've tried to listen to touchstart event on document / body and hide the element (div) in our dedicated handler. However, in some sites, (when DOM structure becomes reasonably complex) the scroll response time increases significantly, even if handler implementation is entirely empty.
We are looking for the proper way to manage the element (re)appearance with a minimal affect of the user experience while scrolling.

I would think Javascript is your best solution. You can dynamically insert your DIV to any content using document.createElement, then also add some javascript to listen for onScroll...
You could even populate the DIV using custom HTML built from the native code if you want.
Any help?

I don't know if you are a jQuery user, but this .scroll() function may help you do exactly what you want to do. Check out the demo to see how it works.
http://api.jquery.com/scroll/

In recent iOS version (5.x) fixed positioning (position:fixed in CSS) is fluently supported, so that your element will be positioned on screen coordinates. That might be a good starting point for solving your troubles.

Related

custom scrollbar not working on touch device

following problem. im using a simple jquery plugin located here
it works fine so far, problem is when im testing it on a touch device (eg ipad2) its not possible to scroll within a div. it does not work with 2 finger swipe too!
i guess the behaviour is not the same to the "standard" scrollbar. but is there any solution to make this touchable?
im in the testing phase, which means the body code is pretty simple
$(document).ready(function() {
function appenddiv() {
var $scrolling = $('<div id="test" class="scrolling">A lot of text in here ...<div id="scroll2"><img src="../images/31670035.jpg"></div></div>');
$scrolling.appendTo($('#container')).scrollbar();
}
$('#scrollbar-link').on('click', function() {
appenddiv();
});
});
<body>
Klick mich!
<div id="container">
</div>
</body>
Do i need something like a "touchable" script which makes it possible to swipe the scroller?
Thanks
:-) Yes, this is definetly an issue...
The root problem is the following:
To create custom scrollbars you need to make DIV overflow: hidden - to hide sys scrollbars. This is OK. BUT on mobile (iPad too) devices from this point your DIV will not be scrollable. It will be (only), if you use overflow: auto ... This is logical - more or less. But drives you to the headache you have now :-)
So, you have to make a choice at this point..
a) you forget your custom scrollbar on touch devices - keep overflow: auto there
b) you implement a drag&drop feature manually - if you detect a mobile device
version b) would be tricky - again. since the event we know as "mousedown" event works differently on touchscreens. There is not only one mousedown - in fact there may be an array of "mousedown"s since you touche the screen with your finger, then you touch the screen with another finger, and so on... so on touchscreens this is a touch[] array...makes sense absolutely, but complicates things...
Either way, I don't know about any less complex solutions... If anyone does, I'm curious about that too!! :-)
We did a lot of testing and put many effort into this issue (and to other issues too) while was working on our NiceScrollbars library project...
I'm here if you would like to discuss this problem deeper! Will try to help
Either way, I don't know about any less complex solutions... If anyone
does, I'm curious about that too!! :-)
In theory, we could add a div with opacity=0.000000000001, z-index -1 (-1 index from the original div. i.e. the original div has a z-index of 10, then the new div would have a z-index of 9) and scroll=auto. The new div would be a copy of the div with scroll=hidden attributes in terms of content and css.
The scroll event would fire via the hidden div and then update the visible div.
Too bad we have to go to that extend, but it seems to be another clean solution/hack beside the fact that you have to duplicate the content or create an element that holds the content height.

Force javascript to run *before* browser redraw (jsFiddle example)

I am building a little web based application using an HTML table. One unusual property of this table is that it has fixed top row and left column (similar to excel). I accomplished this using a little jQuery and CSS.
The problem is, the jQuery event that triggers my code is the $(window).scroll event, and evidently most browsers (Chrome and IE) redraw the page before the code that is called by this event is finished running. As a result, the left column and top row take a split second to "catch up" to the rest of the table.
I've provided a stripped down jsFiddle example in order to show you my problem. Note: The lag isn't very noticeable when the table is so small and (relatively speaking) empty of content. Nevertheless, it is there (assuming you aren't using firefox). Is there any way to get rid of this lag?
Thanks!
Just an idea, but maybe worth considering: You could try using requestAnimationFrame as described in this article (or in a similar way). That might smooth out the update/"lag" issues.
I didn't get this to work with either the scroll event or with requestAnimationFrame. What I ended up doing is attaching to the mousewheel event, which fires before scrolling and rendering has happend. If the scroll event is going downward, I can apply the appropriate class in time for rendering.

How to emulate this javascript functionality (movable div and saved positions)

I have seen a feature on a site I would like to emulate. I have intermediate php skill but am a novice javascript user. The feature is the site content displayed in divs which can be moved around on the screen and their position saved using cookies. This site: [url]www.nowgamer.com[/url] is where I saw it (latest podcasts, videos, reviews etc with filter)
How would I go about achieving this through javscript? I want to know how to connect javascript with the cookie so that the positions of the square divs are saved, as are the preferences of the content filter on each div. How can I achieve this?
Would this be a big job? Thank you for any help, I am working independently on this in my spare time so your contribution with advice is my lifeline.
As Zoidberg commented, its easy with JQuery or Yui, or any other javascript library that provides drag & drop functionality. They are almost easy to configure, checking at demo they give. They also expose certain events like beforeDrag, afterDrag, onDrop, etc. where you can fire a simple js function check the elements' dropped position store it in cookies. For setting cookies, there are world of code on internet.
Also, you might want to check floating absolute/relative positioning css, if your DOM divs are going to be floating around the page.
GoodLuck.
simplyharsh has the proper answer, but I'd like to expand on it a bit:
The basics of a draggable div aren't too complicated. You attach an onclick handler to initiate the dragging. Internally, that's accomplished by changing the div's CSS so it's position: absolute. Then you start monitoring mouse movements (basically onmousemove) and changing the div's top and left according to the movements you've captured.
Dropping is a bit more complicated. You can always just release the mouse and leave the div wherever you ended up moving it, but that leaves it absolutely positioned and therefore outside of normal document flow. But dropping it "inside" some other element means a lot of prep work.
Because of how mouseover/mouseout/mouseenter events work, they WON'T work while you're dragging an element - you've got your draggable div under the mouse at all times, so there's no mouseenter/leave events being fired on the rest of the page. jquery/mootools and the like work around it letting you specify drop zones. The locations/sizes of these zones are precalculated and as you're dragging. Then, as you're dragging, the dragged object's position is compared to these precalculated drop zone locations for every move event. If you "enter" one of those zones, then internally the libraries fire their mouseenter/mouseleave/mouseover events to simulate an actual mouseenter/leave/over event having occured.
If you drop inside a zone, the div gets attached as a child of that zone. If you drop outside, then it will usually "snap back" to where it was when you initiated the drag.
Resizing is somewhat similar, except you're adjusting height and width instead of top and left.

How can I temporarily prevent a scrollable div from scrolling?

Here is my current situation:
I have a web page containing a couple scrollable divs. Each of those divs contains a number of objects. I am using YUI to display popup menus of actions that can be performed on each object. Each object has its own menu associated with it that is constructed and displayed dynamically. The popup menus can be large and can overlap the bounds of the scrollable div.
From what I believe are issues with focus (the menus must be accessible), when I hover the mouse over an action that lies on top of an edge of the scrollable div, the div automatically scrolls, moving the content but leaving the menu stationary. Trying to move the menu dynamically when this happens is not something I want to do as I believe it would provide a poor user experience.
So I need to prevent this focused menu from scrolling the div. My idea for providing the best user interface is to prevent these inner divs from scrolling when a menu is open. This leaves the menu positioned in the optimal location to show the user which item is being acted upon. If the user wants to scroll the box, they can click to close the menu and then scroll normally.
How can I do this? I need a solution that works across the major browsers.
My first thought was to listen to the onscroll event for that particular element. Unfortunately, there does not seem to be an easy way from there to just prevent the scrolling from happening. For one, my JavaScript event code appears to execute after the actual scrolling has occurred.
Then, I thought that since my code is being run after the object has scrolled, I could just reset obj.scrollTop and obj.scrollLeft. Sure enough, this appears to work, though I am worried that on slow browsers the user will see the content inside the div "jump around". Also, it would be really nice if the amount the element scrolls is part of the event object. Is it stuck in there somewhere? I'm looking for an alternative to having to store the scrollTop and scrollLeft variables for this element and then using them while the scrolling is temporarily disabled.
What is the best way to solve this entire problem?
I agree with Anthony regarding the presentation of the functionality you're trying to disallow. If you're going to disable scrolling, then you should make that part of the page visually disabled or removed.
To that end, you can position a semi-transparent div on top of the scrollable div in question, which would capture the mouse events and visually show that the scrollable div is inactive for now. It would be hard to make cross-browser compatible and wouldn't be perfect, but then again very few client-side tricks like this are.
The simple answer is no you can't do this. Its doubly no if you want a cross-browser solution.
Providing the user with the clear affordance that something can be scrolled then denying them that is just plain poor UI design.
Ok so after your edit it turns out you are not actually trying to prevent the user from scrolling.
The main answer remains true though. It sounds as though the focus is going to rectangle (probably an anchor?) that is not fully in view and causes a scroll. Is there a reason this rectangle must get the focus? For accessibility?
What if you didn't have overflow: scroll and instead you used overflow: hidden and provided scroll up/down buttons that allowed the user to scroll when necessary? These buttons could of course be disabled easily.
Though it may not be the answer you are looking for, if you are to set the display value of the div to 'none' while the page loads (from the server) and then have an event wired to the page load (either pageLoad in ajax.net or attach it to the onload event via javascript) that will make the div display set to 'block' .. that would ensure that slower browsers wouldn't see the div 'jumping around' (could even put a 'loading' image in the div to show users it's doing something and not just invisible)
sorry i couldn't provide a more complex/fluent solution.
I found a way to work around this issue. By removing the menu element from the scrollable div and then appending it directly to document.body, the browsers all stop trying to scroll the div to reveal the focused element (even though the element is already completely visible).
Thanks to all for your time and your answers!

innerHTML manipulation in JavaScript

I am developing a web page code, which fetches dynamically the content from the server and then places this content to container nodes using something like
container.innerHTML = content;
Sometimes I have to overwrite some previous content in this node. This works fine, until it happens that previous content occupied more vertical space then a new one would occupy AND a user scrolled the page down -- scrolled more than new content would allow, provided its height.
In this case the page redraws incorrectly -- some artifacts of the old content remain. It works fine, and it is even possible to get rid of artifacts, by minimizing and restoring the browser (or force the window to be redrawn in an other way), however this does not seem very convenient.
I am testing this only under Safari (this is a iPhone-optimized website).
Does anybody have the idea how to deal with this?
The easiest solution that I have found would be to place an anchor tag <a> at the top of the div you are editing:
<a name="ajax-div"></a>
Then when you change the content of the div, you can do this to have the browser jump to your anchor tag:
location.hash = 'ajax-div';
Use this to make sure the user isn't scrolled down too far when you update the content and you shouldn't get the issue in the first place.
(tested in the latest FF beta and latest safari)
It sounds like the webkit rendering engine of Safari is not at first recognizing the content change, at least not fully enough to remove the previous html content. Minimizing and then restoring the windows initiates a redraw event in the browser's rendering engine.
I think I would explore 2 avenues: first could I use an iframe instead of the current 'content' node? Browsers expect IFrames to change, however as you're seeing they're not always so good at changing content of DIV or other elements.
Secondly, perhaps by modifying the scroll position as suggested earlier. You could simply move the scroll back to 0 as suggested or if that is to obtrusive you could try to restore the scroll after the content change. Subtract the height of the old content node from the current scroll position (reseting the browser's scroll to the content node's 0), change the node content, then add the new node's height to the scroll position.
Palehorse is right though (I can't vote his answer up at the moment - no points) an abstraction library like jQuery, Dojo, or even Prototype can often help with these matters. Especially if you see your page / site moving beyond simple DOM manipulation you'll find the tools and enhancements provided by libraries to be a huge help.
It sounds like you are having a problem with the browser itself. Does this problem only occur in one browser?
One thing you might try is using a lightweight library like jQuery. It handles browser differences fairly nicely. To set the inner HTML for a div with the ID of container you would simply write this:
$('#container').html( content );
That will work in most browsers. I do not know if it will fix your problem specifically or not but it may be worth a try.
Would it work to set the scroll position back to the top (element.scrollTop = 0; element.scrollLeft = 0; by heart) before replacing the content?
Set the element's CSS height to 'auto' every time you update innerHTML.
I would try doing container.innerHTML = ''; container.innerHTML = content;

Categories