Ajax Updates |
- iPhone-like Sliding Headers
- Fixed Floating Elements
- DhtmlxLayout – Ajax Web Interface
- DHTMLXTabbar – JavaScript Tabbar Control
- DHTMLX JavaScript Tree Component
Posted: 30 Oct 2009 07:20 AM PDT The iPhone has a few unique UI features, one in particular are the static headings when you're scrolling through a list, so you know the context of the content. We'll see how to create this effect using jQuery. The Effect I can't show you an example in the wild so the screenshot below will have to do for now. As the user swipes through a list, the header for that section of content remains visible at the top of the window. This gives the user context in what they're looking at. One really nice UI effect is when a new heading is just about to replace the existing heading, it pushes the existing heading out of view. It's very subtle and only really visible if you perform the scroll slowly. Unfortunately, for now, we're not replicating subtle part of the effect. What we will do, is when the user is scrolling through an overflowing block of content, the heading for the visible block of content remain at the top. You can see the effect in action in the demo. To create this effect we need to have a fixed position fake header sitting over the content. To do this we're going have to mess around with the DOM using jQuery. We need to wrap the box with another box of the same height and width and give it position: relative so that our fake header can make use of position: absolute and appear to be fixed. Now that this is sitting at the very top level, we need to bring the real headers up over the fake header, so that it appears as if they're pushing the fake out of the way. To achieve this we'll use a z-index on the real headers that is higher than the fake header. However, this causes it's own problems. All the headers now have to be position: absolute to really sit over the fake header, which also means we have to give the element a fixed height and width. This isn't too much of a problem because we can get this information from the original. Now that the headers are position absolute, the text that is sitting next to it falls flush against each other, because the newly positioned headers don't flow in the document. To fix this we need to create a spacer element. In the screencast I mention this might be possible to simplify. You could duplicate the header and insert it after the original header before setting the position: absolute. To be consistent with the screencast, I've stuck with creating the spacer. Finally we need to attach an event handler to the containing box, to say when there is a heading that is exactly aligned with the top of the containing box, to switch in the text from that header in to the fake and move the fake's z-index to be at least one more than the current header (so it sits topmost). < !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <title>Header Slide</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <style type="text/css" media="screen"> .box { margin: 0 auto; height: 400px; width: 400px; position: relative; border: 5px solid #999; } #box { overflow: auto; position: relative; } h2 { background: #999; margin: 0; opacity: 1; padding: 10px; color: #fff; } #box p { margin: 10px; } /* JS required styles */ .box .box { border: 0; } </style> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function () { // 1. grab a bunch of variables var $container = $('#box'); var $headers = $container.find('h2'); var zIndex = 2; var containerTop = $container.offset().top + parseInt($container.css('marginTop')) + parseInt($container.css('borderTopWidth')); var $fakeHeader = $headers.filter(':first').clone(); // 2. absolute position on the h2, and fix the z-index so they increase $headers.each(function () { // set position absolute, etc var $header = $(this), height = $header.outerHeight(), width = $header.outerWidth(); zIndex += 2; $header.css({ position: 'absolute', width: $header.width(), zIndex: zIndex }); // create the white space var $spacer = $header.after('<div />').next(); $spacer.css({ height: height, width: width }); }); // 3. bind a scroll event and change the text of the take heading $container.scroll(function () { $headers.each(function () { var $header = $(this); var top = $header.offset().top; if (top < containerTop) { $fakeHeader.text($header.text()); $fakeHeader.css('zIndex', parseInt($header.css('zIndex'))+1); } }); }); // 4. initialisation $container.wrap('<div class="box" />'); $fakeHeader.css({ zIndex: 1, position: 'absolute', width: $headers.filter(':first').width() }); $container.before($fakeHeader.text($headers.filter(':first').text())); }); </script> </meta></head> <body> <!-- <h1>Fixed Header Slide --> <div class="box" id="box"> <h2>Header 1</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <h2>Header 2</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <h2>Header 3</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <h2>Header 4</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <h2>Header 5</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <h2>Header 6</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> </div> </body> </html> jQuery The jQuery job breaks down in to four parts: 1. Collect the variables we'll need for the effect The completed example is also available if you want to skip through each step. We need to grab jQueryified versions of the container box and headers. We also need to create a clone of the first heading for the fake header. Finally we initialise a z-index and store the top position of the container. At first it looks like .offset().top would do, but we also need to factor in the margin-top and border-top-width, and this gives us the real top position. Of course the whole thing is wrapped in the $(document).ready() method to ensure the code only runs once the DOM is ready. $(document).ready(function () { var $container = $('#box'); var $headers = $container.find('h2'); var $fakeHeader = $headers.filter(':first').clone(); var zIndex = 2; var containerTop = $container.offset().top + parseInt($container.css('marginTop')) + parseInt($container.css('borderTopWidth')); Inserting the Fake Header This is a pretty straight forward process: 1. Wrap the container in a box, in my case I've reused the box class name so that it's the same width and height, but more importantly: position: relative $container.wrap('<div class="box" />'); $fakeHeader.css({ zIndex: 1, position: 'absolute', width: $headers.filter(':first').width() }); $container.before($fakeHeader.text($headers.filter(':first').text())); Absolutely Positioning Headings Since we're absolutely positioning the headings we'll need to manually reset the width of the element. We're also setting a constantly incrementing z-index that the fake header can borrow from to jump above the real heading. Once the headings are absolutely positioning, they no longer affect the flow of the document, and the adjacent elements now sit flush against each other. Now we need to manually correct this issue just using a spacer element. I've created a new empty div element and set the height and width to the outerHeight and outerWidth of the heading. It's important that we select the outerHeight rather than just height because we need to include the margin around that element. I'd suggest that if you're using this technique in a live environment, you can either do it using code (as I have done in this example), or if you're finding that it doesn't match up 100%, you can create a class in your CSS that prepares that spacer, then apply the class to the newly inserted div. $headers.each(function () { var $header = $(this); var height = $header.outerHeight(); var width = $header.outerWidth(); $header.css({ position: 'absolute', width: $header.width(), zIndex: zIndex++ }); // create the white space var $spacer = $header.after('<div />').next(); $spacer.css({ height: height, width: width }); }); Using the Scroll Event to Trigger the Effect As the user scrolls the overflowing container element, we need to track where our fake header is, and once it passes underneath a real header, the fake header will match the text and use a high z-index. To achieve this, we bind a scroll event to the container element, and as it is being scrolled, we loop through the headings checking it's top position. If the top position is less than the top position of the container (remember we included margin and border width to accurately ascertain this), then we copy that heading's details across to the fake heading. The effect that we achieve is that as the fake header passes under the real header, as soon as they're in the same location visually on the page, the fake header pops over the real header giving the illusion that the heading is now locked in position. $container.scroll(function () { $headers.each(function () { var $header = $(this); var top = $header.offset().top; if (top < containerTop) { $fakeHeader.text($header.text()); $fakeHeader.css('zIndex', parseInt($header.css('zIndex'))+1); } }); }); That's all we need. As you'll see with any of these tutorials, we just need to break the task in to smaller tasks and apply the solutions a bit at a time. Check out the final iPhone-like Sliding Headers demo and let me know if you implement this technique in a real web site in the wild. Related Listings:
| |||||
Posted: 30 Oct 2009 07:08 AM PDT On visiting Apple's web site an putting items in my shopping basket, I noticed (an old effect) where the shopping basket would follow me down the page. We'll look at how to replicate the fixed floating sidebars or elements with very little jQuery. Understanding the effect When I scrolled down the Apple store when I had something in my basket I found that the summary and what I had selected would follow me down the page. I've seen this effect before, but often it would be a little jumpy and the element would have to catch up with the scrolling. Apple's version was very smooth and didn't jump when I kept scrolling. Upon firing up Firebug I can see that once the scrollbar gets to the point where the basket is at the top of the page, the basket has a class applied to it which gives it a position: fixed – which explains why it holds still while I continue to scroll down. Like I said, I've seen this effect before, for example on Simon Willison's web site (see the comments form) (one of the speakers for my Full Frontal conference). When I scroll down the page, the comments form can sometimes "play catchup" with the scrolling position, because I suspect the top position is being recalculated (though I've not checked his code to be sure or not). So I've taken the style of Simon's site for the example and added the jQuery we need to make this a nice smooth effect. Since we're solving this effect using position: fixed, IE6 doesn't support this CSS property. I'm not saying that IE6 doesn't matter, but I'm suggesting that this effect isn't a requirement to be able to interact with the site properly, so if IE6 users don't see this extra effect, I'm okay with this. As I explained in the screencast, you'll need to decide this yourself, check your site's demographic, whether it's a personal project, etc. The trick really happens in the CSS here and being able to flip back and forth between absolute positioning and fixed positioning. So I've prepared the layout as such. You guys and gals being designer and front-end types will know how you'll want to style the elements. One trick I did find was that I had to wrap the element that would receive position: fixed in a wrapper with position: absolute so that the left position was again the wrapper rather than the body element. The effect of not having the wrapper, meant that when I switched fixed on the element, it jumped to the left by the amount of padding and margin set on the body element. <style> /* required to avoid jumping */ #commentWrapper { left: 450px; position: absolute; margin-left: 35px; width: 280px; } #comment { position: absolute; top: 0; /* just used to show how to include the margin in the effect */ margin-top: 20px; border-top: 1px solid purple; padding-top: 19px; } #comment.fixed { position: fixed; top: 0; } </style> <div id="comments"> <ol> <li>Here be the comments from visitors...</li> <li>etc...</li> </ol> </div> <div id="commentWrapper"> <div id="comment"> <form> <!-- take their response --> </form> </div> </div> jQuery The jQuery required is very simple to create this effect. Obviously first up, include jQuery: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script> First of all, we need to capture the initial position of the comments form. There's a few parts to this to ensure we get a real number (rather than NaN – not a number), and to ensure we also calculate in the margin-top: var top = $('#comment').offset().top; Next we subtract the margin-top (I've used marginTop in the code below, but they're interchangeable) of our element: var top = $('#comment').offset().top - $('#comment').css('marginTop'); However, the result from the CSS method is "20px", so we need this as a number so we can subtract properly, we'll use parseFloat to achieve this: var top = $('#comment').offset().top - parseFloat($('#comment').css('marginTop')); Finally, if we don't include a margin in the CSS, the result of the CSS method call is auto, which won't parse properly, so we need to replace the text "auto" with the number 0: var top = $('#comment').offset().top - parseFloat($('#comment').css('marginTop').replace(/auto/,0)); This all needs to be done inside once the document has loaded, so we'll wrap all of this in the ready method, and while we're at it we need to bind an event handle when the user scrolls down the page, so we'll attach this when the page has loaded: $(document).ready(function () { var top = $('#comment').offset().top - parseFloat($('#comment').css('marginTop').replace(/auto/,0)); $(window).scroll(function () { // let's do something funky }); }) Within the scroll event handler, we need to: 1. Capture the current scrolled Y position using $(window).scrollTop() Note that since we bind the scroll event to the window object, I've used $(this).scrollTop() (since this is also the window in this case). All of this put together results in: $(document).ready(function () { var top = $('#comment').offset().top - parseFloat($('#comment').css('marginTop').replace(/auto/, 0)); $(window).scroll(function (event) { // what the y position of the scroll is var y = $(this).scrollTop(); // whether that's below the form if (y >= top) { // if so, ad the fixed class $('#comment').addClass('fixed'); } else { // otherwise remove it $('#comment').removeClass('fixed'); } }); }); Related Listings:
| |||||
DhtmlxLayout – Ajax Web Interface Posted: 30 Oct 2009 06:39 AM PDT DhtmlxLayout is a JavaScript DHTML component that provides powerful and efficient solution for building Ajax-enabled web interfaces with ease. This component allows you to programmatically define interface structure, including layout of elements and their sizes. End users can easily resize interface elements, collapse or expand them. Since version 2.0 dhtmlxLayout provides a high level of integration with other DHTMLX components: dhtmlxGrid, dhtmlxTree, dhtmlxWindows, dhtmlxMenu, etc. The components can be integrated both globally for the application and separately for each Layout pane. With a new skin, introduced in version 2.5, all dhtmlx components got slick and clean look which can perfectly match the design of any modern website or application. Using dhtmlxLayout, you can construct sophisticated web interfaces in a simple and convenient way. Since v2.5 the component provides new engine for better performance, and also the abilities to easily detach objects from its panes and adjust its size dynamically to a parent container on the page. Due to extended cross-browser compatibility, the component works perfectly well in all main web browsers (IE, FF, Safari, Opera, Chrome). Features: Related Listings:
| |||||
DHTMLXTabbar – JavaScript Tabbar Control Posted: 30 Oct 2009 06:11 AM PDT DHTMLXTabbar is a JavaScript tabbar control for creating dynamic tabbed-navigation interface. This Ajax-enabled UI component lets you add feature-rich and nice looking tabs to your site or web application. The control can be easily initialized on a web page that makes building of DHTML tabbed interface a breeze. Just assign any elements on your page (for example, DIVs) to the tabs of the Tabbar, and it will automatically do all the work for you – the component will switch these elements, displaying them by clicking on the corresponding tab. Tabs can be left, right, top or bottom aligned. You can define tabs appearance according to different visual styles (predefined or your own). Cross-browser compatible, XML driven, fully configurable, with rich javascript API, dhtmlxTabbar provides a simple but powerful solution for building client-side navigation. Together with other dhtmlx components: dhtmlxTree, dhtmlxGrid/TreeGrid, dhtmlxMenu, and dhtmlxToolbar – it constitutes ready to use basis for any AJAX driven web based application. Since v2.5 dhtmlxTabbar not only provides a single command integration with other DHTMLX components, but also offers unified API similar to other container components (e.g. layout, accordion, etc.) for adding/removing objects into the tabs. Besides, version 2.5 introduces better performance due to the decreased number of loaded images. Related Listings:
| |||||
DHTMLX JavaScript Tree Component Posted: 30 Oct 2009 05:57 AM PDT dhtmlxTree (DHTML extensions Tree) is a feature rich JavaScript tree menu that allows you to effortlessly create attractive and fast-loading hierarchical interfaces with cross-browser compatibility, AJAX support, in-line node editing, and drag-n-drop capabilities. Rich client-side API provides complete control over the tree appearance and behaviour. Since version 2.5, in addition to the existing functional API, dhtmlxTree also provides object constructor that allows developers to define object properties within a single command. Special techniques implemented into the component make loading of really big trees fast and effective. Smart Rendering – allows avoiding performance problems in trees with great number of nodes per level. Advanced drag-and-drop makes it possible to drag items not just within one tree, but between different ones (even if trees are located in different frames or iframes). The tree implements AJAX model of data processing which allows the tree content to be updated seamlessly without reloading the entire webpage. All changes performed in the tree on the client-side can be saved to the database automatically in real time. Being built into your web site or application, this DHTML tree provides high-performing navigation system. Tree nodes can be loaded dynamically on demand from XML stream, therefore dhtmlxTree works effectively with large amounts of data and handles almost unlimited number of nodes. Distributed parsing functionality allows this treeview component to load tree levels with hundreds of nodes asynchronously. When the node is open, only the first portion of sub-nodes is displayed, then others are dynamically processed and displayed by the same portions on demand. Since v2.0 dhtmlx components, including dhtmlxTree, introduce the possibility to be easily organized within a common application interface with the help of dhtmlxLayout. With a new skin, introduced in version 2.5, the components got slick and clean look which can perfectly match the design of any modern website or application. Related Listings:
|
You are subscribed to email updates from Ajax Updates To stop receiving these emails, you may unsubscribe now. | Email delivery powered by Google |
Google Inc., 20 West Kinzie, Chicago IL USA 60610 |
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.