On Github davideast / evolution-of-web-apps
It governs what we do today
Learn from our mistakes
Learn from the innovations
Review good and bad parts
HTTP, HTML, & Early Browsers
The original idea behind the Web was to collaborate and cross reference research documents between a small network of scientists
Tim Berners-Lee proposed the "WorldWideWeb" Project
Images... seriously, no images
POST request... not even that
Streaming video to 40 million people - (Netflix)
Managing a digital farm - (Farmville)
Simple request, response protocol that served static documents
Berners-Lee was a research scientist, to improve HTTP & HTML he asked the early, yet fervent community
Mosaic released, the first widely used browser
CGI (Common Gateway Interface) standard formalized
This gave us the ability to render HTML on the server
Rasmus Lerdorf creates the first version of PHP
The web was created
Emphasis on openness
Functionality was extremely limited
Standards? I do what I want
Marc Andreessen leaves Mosaic to form Netscape
Netscape Navigator is released in December of 1994
Netscape's success draws Microsoft to the web
Internet Explorer is released
Implemented features at will
JavaScript is released in Netscape 2
Microsoft released JScript
The first emergence of interactivity of an HTML page
var ns6=document.getElementById&&!document.all var ie=document.all var customcollect=new Array() var i=0 function init() { if (ie){ while (eval("document.all.jiggle"+i)!=null){ customcollect[i]= eval("document.all.jiggle"+i) i++ } } else if (ns6) { while (document.getElementById("jiggle"+i)!=null){ customcollect[i]= document.getElementById("jiggle"+i) i++ } } }
ECMAScript standard would not formalize until 1997
JavaScript hit the scene
JavaScript hit the scene, twice
Competition outweighed standards compliance
More client-side sadness
Since there was no DOM standard, both Netscape and Microsoft had different DOM-like implementations
Standard
var elem = document.getElementById('jiggle');
IE
var elem = document.all.jiggle;
Netscape
var elem = document.layers.jiggle;
DOM Level 1 was standardized by the W3C
Provided a uniform way to access HTML elements
var elem = document.getElementById('jiggle');
Neither Netscape or IE would support DOM Level 1 until 2000
DOM Level 2
Specified events on DOM Elements
Standard
document.addEventListener('click', function(e){ console.log(e); // local event var elem = event.target; // element the initiated the event e.stopPropagation(); // stop event bubbling }, false); // control capture phase
IE
document.attachEvent('onclick', function () { console.log(window.event); // global event object var elem = window.event.srcElement; // element the initiated the event window.event.cancelBubble = true; // // stop event bubbling }); // no support for capture phase
<button onclick="clicked(event);"> Click </button>
function clicked(theEvent) { var clickEvent, target; // is it local or global? clickEvent = window.event ? window.event : theEvent; // get the target event if( clickEvent.target ) { target = clickEvent.target; } else if( clickEvent.srcElement ) { target = clickEvent.srcElement; } // stop event bubbling if( clickEvent.stopPropagation ) { clickEvent.stopPropagation(); } else if ( clickEvent.cancelBubble ) { clickEvent.cancelBubble = true; } }
Until IE9 implemented DOM Level 2 standards
It may seem easy to dislike IE, but...
The Web Outlook Team developed the XMLHTTP wrapper back in 1998
Get partial changes rather then request the entire page
Websites can become web apps
Major differences in event model
There would not be a standard for XHR until 2006
HTML lacked native functionality for video, audio, and animation
AJAX
Fragmented event model
Reliance on Plugins
Are you $(document).ready() for this?
John Resig begins the jQuery Project
jQuery 1.0 is released
jQuery made us all forget about the terrible inconsistencies
Event Handling
$('#btAdd').click(function(e) { console.log(e); // jQuery event: adheres to W3C standards e.stopPropagation(); // handle event bubbling var orginalEvent = e.originalEvent, // access to original event target = e.target; // dom element that initiated the event });
AJAX Methods
var ajaxSettings = { url: 'http://mysite.com/data', method: 'GET', success: function(data) { $('#dataDisplay').text(data); } }; $.ajax(ajaxSettings);
Opera proposes the video tag
W3C published the HTML5 working draft
Chrome supports the video tag
... but not well organized
$('#omg').promise('.me-you-wont-do-this')
$(function(){ $('select[name=customerId]').on('click', function(){ var $container = $(this).parent() .parent() .parent() .parent() .parent() .parent(); }); });
$.get('this/out-of-here')
$(function () { // what is this even tool-tipping?? $('#btCreate').tooltip(); $('#btCreate').live('click', function (e) { var $this = $(this), $parent = $this.parent(), // seriously, we're grabbing the parent? $container = $('#main-container'); // hope this id doesn't change var heroWidth = $parent.width(), containerHeight = $container.outerHeight(true), //what is this element? name = $('input[type="text"]#txtAlbumName').val(), // where is this coming from? $errorMessage = $('.error-message'), // Ah yes, adhoc XHR calls $request = $.post('/Albums/CreateAlbum', { albumName: name }); $request.success(function (result) { $errorMessage.slideUp(); $parent.css("position", "absolute"); $parent.css("width", heroWidth); $container.height(containerHeight); $parent.animate({ "margin-top": '-1000px' }, 1000, 'easeInExpo', function () { $parent.remove(); $container.height("auto"); $('#slide-albums').after ($(result)) .hide() .fadeIn(4000); }); }); $request.error(function(error) { $errorMessage .children() .remove(); $.each(result, function (key, obj) { $errorMessage .append($("<p></p>") .text(obj.message)) }); $errorMessage .hide() .slideDown(); }); });
IE versions 6-8 held nearly 60% of market share in June of 2009
jQuery abstracted browser inconsistencies
HTML5 support began
Primitive DOM manipulation
Legacy browser use was astonishing
Structure & Evergreen Browsers
{{#items}} {{#first}} <li><strong>{{name}}</strong></li> {{/first}} {{#link}} <li><a href="{{url}}">{{name}}</a></li> {{/link}} {{/items}}
Let's MV* Everything
IE10 released with auto updates
But the data has to come from somewhere
http://api.myapp.com/users/
http://api.myapp.com/users/last
http://api.myapp.com/users/email
Increase in client-side power
HTML5 support through Evergreen Browsers
Repeated code on client and server
Repeated code on client and server
API all the things
UI/UX
Domain logic
There's a Backend as a Service (BaaS) for that
A powerful API to store and sync your data in realtime
angular.module('myApp', ['firebase']) // your back-end is right here .factory('Backend', function() { return new Firebase('https://east.firebaseio.com/'); }) .controller('TodoCtrl', function($scope, Backend) { $scope.newTodo = ''; $scope.todos = $firebase(Backend); $scope.add = function() { $scope.todos.$add($scope.newTodo); }; });
We've come a long way
The web started simple
Browser Wars placed competition over compliance
Features improved, but standards lacked
jQuery helped smooth out inconsistencies
Better structure with JS Frameworks
Clients are powerful with Evergreen Browsers
APIs allow us to create powerful cross-platform apps
ajaxpageclass.connect = function (pageurl, divId) { var page_request = false var bustcacheparameter = "" if (window.XMLHttpRequest && !document.all) // if Mozilla, Safari etc (skip IE7, as object is buggy in that browser) page_request = new XMLHttpRequest() else if (window.ActiveXObject) { // if IE6 or below try { page_request = new ActiveXObject("Msxml2.XMLHTTP") } catch (e) { try { page_request = new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {} } } else return false document.getElementById(divId).innerHTML = this.loadstatustext //Display "fetching page message" page_request.onreadystatechange = function () { ajaxpageclass.loadpage(page_request, divId) } if (this.ajaxbustcache) //if bust caching of external page bustcacheparameter = (pageurl.indexOf("?") != -1) ? "&" + new Date().getTime() : "?" + new Date().getTime() page_request.open('GET', pageurl + bustcacheparameter, true) page_request.send(null) } // source: http://www.dynamicdrive.com/dynamicindex17/ajaxpaginate/ajaxpagination.js