progressive vs non-progressive development
Progressive Enhancement will not only help you to support different levels of context – it can also help you during development. So let’s look at an example again (here is an overview).
What we see here is just a simple way of displaying content that might be transformed to tabs.
<div class="FlowTabs"> <h4 class="Tab">Short Text</h4> <div class="TabContent">Lorem ipsum dolor [...]</div> <h4 class="Tab">Long Text</h4> <div class="TabContent">Sed ut perspiciatis [...]</div> </div>
The h4 could be the title and the div could be the content. So without any js magic it’s just a header and some content below. It’s clear that the h4 is the header for the following text. It’s just simple.
MooTools Tabs
Now let’s look at the MooTools version. The HTML just remains the same. Some modifications to the css so it’s look a little bit more like tabs. [this is just an example, no style contest.. :p]
The actual javascript is really boring:
window.addEvent('domready', function() {
$require(MPR.path + 'Tabs/FlowTabs/FlowTabs.inline.js');
var myTabs = new FlowTabs.inline( $$('.FlowTabs .Tab'), $$('.FlowTabs .TabContent') );
});
Just include the class and say we should get the tabs from “.Tab” and the content from “.TabContent”. If we wanted you could easily change this. Say we want to use the first h6 as title and the first div as content (without the classes) we only need to change the class call to “new FlowTabs.inline( $$(’.FlowTabs h6′), $$(’.FlowTabs > div’) );”. So we are pretty flexible and can use this in different situation with the same progressive Enhancement functionality. [ok, class creation takes some time - but once you have it it's so nice
- I wrote this class just as an example for this, but I might release it at some point...]
jQuery Tabs
This was pretty easy right? Let’s assume we we want to change the javascript Framework (for whatever reason). Now this is usually a pretty bad day for us developers – means a lot of work and recreate all that stuff (if we wanna do it right and don’t use 2 Frameworks at the same time). However with progressive Enhancement half the work is already done. The style, the content, multi-language support… – all that is already working. We just need to recreate the behavior. I had no “real” glue about jQuery but I had it done within less than half an hour. Just take a look at the progressive Enhancement version with jQuery.
$('.FlowTabs').prepend('<div class="inlineTabTabs clearfix"></div>');
var tabContainers = $('.FlowTabs .TabContent');
$('.FlowTabs .Tab').each( function(index) {
$('.inlineTabTabs').append(this);
$(this).click( function() {
tabContainers.hide();
tabContainers.filter(':eq(' + index + ')').show();
$('.FlowTabs .Tab').removeClass('act');
$(this).addClass('act');
return false;
})
}).filter(':eq(0)').click();
The code may not be the nicest and there a certainly some ways to make it more flexible like we can do this with MooTool classes, but I got it to work within a short time and it looks and feels exactly the same. I would say progressive Enhancement at it best
. Now you may wonder why I didn’t used the jQuery UI Tabs. It’s for a simple reason – it’s no real progressive Enhancement (in the way I think of it). First the tabs are in a separate ul, li list at the top of all the content. So if you have no javascript all the tab titles will be disconnected from their content. Furthermore the the “headers” (tabs-title) are links and connected with their content through anchors. So this link href=”#myTabContent” will open the tab with the id=”myTabContent”. There are 2 reasons why I don’t like this: First I don’t want to create all this id’s and second why use links? there is no page to go to… ok, it makes partly sense because the “headers” are disconnected with there content, but that’s just an excuse for the first mistake so we certainly can do better right?
ExtJS Tabs
Now I tried to create the same effect with ExtJS, I was quite motivated as MooTools and jQuery went so smoothly. However the closest to progressive Enhancement I could come up with is more or less progressive Enhancement. Let’s take a closer look.
Ext.onReady(function(){
var tabs = new Ext.TabPanel({
applyTo: 'FlowTabs',
activeTab: 0,
deferredRender: false,
autoTabs: true
});
});
Now with this “autoTabs: true” the TabPanel actually looks for ‘<div class="x-tab" title="myTabTitle">’ and create Tabs from it. It’s easy and again I don’t need to write many javascript. However I had to change my HTML so it’s not progressive Enhancement. Furthermore the title for the tab is not well displayed without javascript. Also I included the the 532KB ext-all.js and a 81KB ext-all.css, both minified. This quite some stuff and it doesn’t even let me choose which tabs and content is taken. Wow and yeah it looks different. I didn’t tried to style it accordingly as I had to change my original 4 lines (from the top – [basic]) to those 2 lines:
<div class="x-tab" title="Short Text">Lorem ipsum dolor [...]</div> <div class="x-tab" title="Long Text">Sed ut perspiciatis [...]</div>
and after the Ext.TabPanel has transformed it to 49(!!) HTML lines. You can either look at the code in firebug or look at this page where you can see the output code. ok, this was a little bit to much for me, so I guess maybe I would need to create my own Ext widget to make it work, but if I need to write my own code I (me personally) wouldn’t choose ExtJS. [I might be completely wrong here, as I don't know Ext well enough. However it seems like it works quite different than MooTools or jQuery]
Update: you can of course create your own script – Thomas Fritz was nice enough to provide an example. So it really just depends on your personal preference what Framework you wanna choose.
non-progressive ExtJS
Now let’s take the other way around. We just start with a Javascript Version by ExtJS.
Ext.onReady(function(){
var tabs = new Ext.TabPanel({
renderTo: 'FlowTabs',
activeTab: 0,
plain:true,
defaults:{autoHeight: true},
items:[
{title:'Short Text', html: 'Lorem ipsum dolor [...]'},
{title:'Long Text', html: 'Sed ut perspiciatis [...]'}
]
});
});
All the content is in the javascript so we don’t have any html-content that’s sent by the server. All the transformation from the content (JSON to HTML) is done by javascript. If you don’t have javascript you see a white page. It’s so not progressive Enhancement :p. Whenever I want to change content I need to change the javascript (but hey, I don’t need to change the html… :p). I don’t like this way but whatever.
non-progressive MooTools
Here we go, so now we have this start from a non-progressive page. I want to port it to another Javascript Framework. So now where do I start. hmmm yeah right – at the beginning? I don’t have any html I could take as a base. So I need to recreate everything from scratch again. So let’s just do it:
var items = [
{title:'Short Text', html: 'Lorem ipsum dolor [...]'},
{title:'Long Text', html: 'Sed ut perspiciatis [...]'}
];
var container = new Element('div', { 'class' : 'FlowTabs' });
$each( items, function(el) {
container.grab( new Element('h4', { 'class': 'Tab', html: el.title }) );
container.grab( new Element('div', { 'class': 'TabContent', html: el.html }) );
});
$require(MPR.path + 'Tabs/FlowTabs/FlowTabs.inline.js');
var myTabs = new FlowTabs.inline( container.getElements('.Tab'), container.getElements('.TabContent') );
container.inject( $('FlowTabs') );
ok, I cheated a little. I just create the basic html from above – this time simply with javascript. Strange right? So now I have all this virtual dom element and here comes again a little MooTools magic (sorry for being biased :p). Even though nothing is in the dom, we can still create the object and hand the class the “virtual” items. Afterward we inject only the already modified html.
I didn’t tried to create it again with jQuery as I think it’s just not worth my time. It’s worthless time as progressive Enhancement is just way better.
Conclusion
I’m more than ever confident that progressive Enhancement is the way to use javascript. And I just need to quote Jeremy Keith with: “Think about Ajax from the start but don’t implement it until the very end.” I can really recommend the first part of this speak (about the first 20 minutes).
I also believe that there are currently only a few javascript “plugins” around that make use of “real” progressive Enhancement and that’s really sad as it saves time and give your content some sort of universality. Even if all the design all the behavior changes, your true content will always stay the same.
If there where a package based javascript library that would follow true progressive Enhancement with the same amount of features as the current ExtJS framework than I might not need to write this article (if anyone knows something just let me know). I doubt it so I will just try to create such a library (just step by step) and I think the perfect base for something like this is MooTools.
Update: so here we are again – thx to an example from Peter Fritz every Framework just masters all the requirements. So yet again it’s just your personal preference what Framework you choose.
Apples and oranges!
What you did with jQuery was to grapple about with the DOM structure first using the ubiquitour dollar-does-everything function with lots of pugly code. You had to change the document!
Well, if you’re going to do that, how about the elegant:
Ext.onReady(function(){var tabs = new Ext.TabPanel({
applyTo: Ext.getBody().child(".FlowTabs"),
width: 450,
height: 300,
deferredRender: false,
activeTab: 0,
frame: true,
autoTabs: true,
autoTabSelector: 'div.TabContent'
});
Ext.getBody().select('.FlowTabs .Tab').each(function(t, composite, idx) {
t.remove();
tabs.items.get(idx).setTitle(t.dom.innerHTML);
});
});
preserve
spaces
?
Do not get me wrong. I think jQuery and also MooTools are great JS Librarys which i personally would use in my own projects. BUT you can not compare it that simple with ExtJS with a simple Tab example and make conclusions about ExtJS when you only want _SIMPLE_ Tabs.
Here is an example which is “more” comparable with yours: http://fritzthomas.com/files/extjs-progressive-enhancement-example/
I let you draw your own conclusions about it.
thx “Animal” and “Fritz Thomas” for your comments. I agree that I’m a little wrong here – I didn’t spent enough time to figure out ExtJS and I treated it wrong. I’m sorry about that and I have updated the post…
PS: the code tag doesn’t work in the comments (sorry…)
The thing about ExtJs is that it is not designed to “spice up” (progressively enhance) old fashioned “web sites” by poking a few whizzy widgets into dead HTML.
ExtJs is designed for creating *applications*
It is a complete UI solution which creates a dynamically layed out UI from the document.body all the way down a managed Container->Component hierarchy.
So a TabPanel is not a simple few divs. A TabPanel uses a “CardLayout” layout manager to manage the visibility of it child Components.
Each of these Components may be a flat piece of HTML, but it may also be a Container (containing other Components arranged in a border layout with resizable regions), or a GridPanel, or a TreePanel or a DataView, or a FormPanel etc…
If the TabPanel is a child of a layout which resizes, then it cascades the resize down through all descendant Containers.
All the content does *not* have to be in Javascript.
Just use the contentEl config in each of those child tabs instead of the html config!
You are really posting things saying how it’s bad, but you aren’t in possession of all the facts!
And in http://www.delusionworld.com/files/progressive-vs-non-progressive-development/non-progressive.ExtJS.html you don’t even *try* to pull the existing HTML into tabs.
Plus the tab-sprite.gif is 404, so the tabs that you *do* create correctly don’t have a correct appearance.
*hehe* in the non-progressive version I didn’t wanted to get any content from HTML as it should be non-progressive.
and for these example I didn’t care about any appearance – it’s just an example.
and what’s the deal If I just pull some things from the HTML? Either pull all (progressive Enhancement) or not (non-progressive). With progressive Enhancement my js can stay always the same even if the data changes. With non-progressive it’s the other way around.
I personally don’t want to create dynamic javascript – but that’s maybe just me. That’s the reason why I’m no so into ExtJS but I’m sure many don’t mind. And as I stated above choosing your Javascript Framework is just a personal matter so everyone should be fine..