building evented single page applications
TRANSCRIPT
building evented single-page applications
Sunday, September 13, 2009
1. who2. why3. demo4. how
Sunday, September 13, 2009
1. whoSunday, September 13, 2009
chancellorhttp://orderedlist.com/
Sunday, September 13, 2009
professorhttp://teaching.johnnunemaker.com/
Sunday, September 13, 2009
i’m not perfect
Sunday, September 13, 2009
2. whySunday, September 13, 2009
because?
Sunday, September 13, 2009
because?
Sunday, September 13, 2009
speedonly send what changes
across the wire
Sunday, September 13, 2009
perceived speed
Sunday, September 13, 2009
interactivity
Sunday, September 13, 2009
experiencebut the greatest of these is...
Sunday, September 13, 2009
3. demoSunday, September 13, 2009
http://peoplebase.com/ http://harmonyapp.com/
Sunday, September 13, 2009
4. howSunday, September 13, 2009
goals
Sunday, September 13, 2009
no reloads
Sunday, September 13, 2009
no reloadshistory/refresh
Sunday, September 13, 2009
no reloadshistory/refresheasy
Sunday, September 13, 2009
#Sunday, September 13, 2009
no reloadshistory/refresheasy
Sunday, September 13, 2009
no reloadshistory/refresheasy
Sunday, September 13, 2009
no reloadshistory/refresheasy
Sunday, September 13, 2009
no reloadshistory/refresheasy
Sunday, September 13, 2009
the end
Sunday, September 13, 2009
no reloads
Sunday, September 13, 2009
<a href="#/items">Items</a>
Sunday, September 13, 2009
$("a[href^='#/']").live('click', function (event) { var $link = $(this); window.location.hash = $link.attr('href'); $(document).trigger('hashchange'); return false;});
Sunday, September 13, 2009
$(document).bind('hashchange', Layout.reload);
Sunday, September 13, 2009
var Layout = { reload: function() { Layout.load(window.location.hash); }};
Sunday, September 13, 2009
var Layout = { load: function(path, options) { path = path.replace(/^#/, ''); // trigger path loading events $.ajax({ url : path, dataType : 'json', success : function(json) { Layout.onSuccess(json); // trigger path success events if (options && options.success) { options.success(); } }, complete : function() { if (options && options.complete) { options.complete(); } } }); }};
Sunday, September 13, 2009
var Layout = { load: function(path, options) { path = path.replace(/^#/, ''); $(document).trigger('path:loading', [path]); $(document).trigger('path:loading:' + path); $.ajax({ url: path, dataType: 'json', success: function(json) { Layout.onSuccess(json); $(document).trigger('path:success', [path, json]); $(document).trigger('path:success:' + path, [json]); if (options && options.success) { options.success(); } }, complete: function() { if (options && options.complete) { options.complete(); } } }); }};
Sunday, September 13, 2009
var Layout = { onSuccess: function(json) { Layout.applyJSON(json); // trigger layout success },};
Sunday, September 13, 2009
no reloads
Sunday, September 13, 2009
history/refresh
Sunday, September 13, 2009
setInterval(function() { var hash_is_new = window.location.hash && window.currentHash != window.location.hash; if (hash_is_new) { window.currentHash = window.location.hash; Layout.handlePageLoad(); }}, 300);
Sunday, September 13, 2009
#/org/groups/12/45/new
Sunday, September 13, 2009
org groups 12 45 new
Sunday, September 13, 2009
org groups 12 45 new
Sunday, September 13, 2009
org groups 12 45 new
Sunday, September 13, 2009
org groups 12 45 new
Sunday, September 13, 2009
org groups 12 45 new
Sunday, September 13, 2009
org groups 12 45 new
Sunday, September 13, 2009
var Layout = { handlePageLoad: function() { var segments = window.location.hash.replace(/^#\//, '').split('/'), total = segments.length, path = ''; function loadSectionsInOrder() { var segment = segments.shift(); path += '/' + segment; var onComplete = function() { var loaded = total - segments.length, finished = loaded == total; if (!finished) { loadSectionsInOrder(); } }; Layout.load(path, {complete: onComplete}); } loadSectionsInOrder(); }};
Sunday, September 13, 2009
var Layout = { handlePageLoad: function() { var segments = window.location.hash.replace(/^#\//, '').split('/'), total = segments.length, path = ''; $(document).trigger('page:loading'); function loadSectionsInOrder() { var segment = segments.shift(); path += '/' + segment; var onComplete = function() { var loaded = total - segments.length, finished = loaded == total; $(document).trigger('page:progress', [total, loaded]); if (finished) { $(document).trigger('page:loaded'); } else { loadSectionsInOrder(); } }; Layout.load(path, {complete: onComplete}); } loadSectionsInOrder(); }};
Sunday, September 13, 2009
$(document).bind('page:progress', function(e, total, loaded) { if (total != loaded) { var final_width = 114, new_width = (loaded/total) * final_width; $('#loading_progress').animate({width: new_width+'px'}, 200); } }); $(document).bind('page:loading', function() { $('#harmony_loading').show(); $('#loading_progress').css('width', 0); }); $(document).bind('page:loaded', function() { $('#loading_progress').animate({width:'114px'}, 300, 'linear', function() { $('#harmony_loading').hide(); }); });
Sunday, September 13, 2009
history/refresh
Sunday, September 13, 2009
easy
Sunday, September 13, 2009
rule #1: abuse events for better code separation
and easier customizationhttp://orderedlist.com/articles/jquery-evented-programming-primer
Sunday, September 13, 2009
$('form').live('submit', function(event) { var $form = $(this); $form.ajaxSubmit({ dataType: 'json', beforeSend: function() { // trigger before send }, success: function(json) { // if errors, show them, else apply json and reset form }, error: function(response, status, error) { // trigger error }, complete: function() { // trigger complete } }); return false;});
Sunday, September 13, 2009
$('form').live('submit', function(event) { var $form = $(this); $form.ajaxSubmit({ dataType: 'json', beforeSend: function() { $form.trigger('form:beforeSend'); }, success: function(json) { if (json.errors) { $form.showErrors(json.errors); } else { Layout.onSuccess(json); $form.trigger('form:success', [json]); $form.resetForm(); } }, error: function(response, status, error) { $form.trigger('form:error', [response, status, error]); }, complete: function() { $form.trigger('form:complete'); } }); return false;});
Sunday, September 13, 2009
var Site = { onCreateSuccess: function(event, json) { Sidebar.highlight($('#site_' + json.id)) Layout.updateHashWithoutLoad(window.location.hash.replace(/new$/, json.id)); }, onUpdateSuccess: function(event, json) { Sidebar.highlight($('#site_' + json.id)) }};
$('form.new_site').live('form:success', Site.onCreateSuccess);$('form.edit_site').live('form:success', Site.onUpdateSuccess);
Sunday, September 13, 2009
var Field = { onCreateSuccess: function(event, json) { $('#list_section_' + json.section_id) .addSectionField(json.field_title.toLowerCase()); }, onUpdateSuccess: function(event, json) { $('#list_section_' + json.section_id) .removeSectionField(json.old_title.toLowerCase()) .addSectionField(json.new_title.toLowerCase()); }};
$('form.new_field') .live('form:success', Field.onCreateSuccess);$('form.edit_field').live('form:success', Field.onUpdateSuccess);
Sunday, September 13, 2009
Layout.applyJSONaccepts json like below and “applies” it to the layout;
gets called with each url load either from click or form
Sunday, September 13, 2009
Layout.applyJSON
{ 'replace': { '#content': '<h1>Heading</h1><p>Yay!</p>' }, 'replaceWith': { '#post_12': '<div class="post">...</div>' }, 'remove': ['#post_11', '#comment_12']}
Sunday, September 13, 2009
rule #2: the url dictates everything
Sunday, September 13, 2009
var Layout = { livePath: function(event, path, callback) { if (typeof(test) === 'string') { $(document).bind('path:' + event + ':' + path, callback); } else { Layout.live_path_regex[event].push([path, callback]); } }};
Sunday, September 13, 2009
Layout.livePath('loading', /\/org\/([^\/]+)([0-9\/]+).*/, Groups.loading);
Layout.livePath('loading', /\/sections\/([0-9]+)$/, Sections.markCurrent);
Layout.livePath('success', '/org/groups', Groups.setup);
Layout.livePath('success', '/sections', Sections.makeSortable);
Layout.livePath('success', /\/admin\/assets(.*)/, Assets.init);
Layout.livePath('success', /\/admin\/items\/(\d+)/, ItemForm.init);
Layout.livePath('success', /\/admin\/items\/([0-9\/]+)/, Items.manageSidebar);
Sunday, September 13, 2009
rule #3: do it live
Sunday, September 13, 2009
$('a.field_form_toggler') .live('click', Fields.toggleAddFieldForm);$('form.new_section') .live('form:success', SectionForm.onCreateSuccess);$('form.edit_section') .live('form:success', SectionForm.onUpdateSuccess);$('form.new_field') .live('form:success', Field.onCreateSuccess);$('form.edit_field') .live('form:success', Field.onUpdateSuccess);$('a.field_destroy') .live('destroy:success', Field.onDestroySuccess);
Sunday, September 13, 2009
easy
Sunday, September 13, 2009