SlideShare a Scribd company logo
Design Patterns for
JavaScript Web Apps
     Stefan Scheidt
OPITZ CONSULTING GmbH
About me ...



stefan.scheidt@opitz-consulting.com
          (@stefanscheidt)
Mission                                      Markets
The company's ambition is to help             Branchspreading
organizations to be better than their         Over 600 customers
competitors.                                                                      29%
                                                                                  Trade / Logistics /
Our services take place in partnership and                    29%                 Supplier
                                              Industry / Services /
are aimed at co-operation of many years.     Telecommunications

                                                                          42%
                                                                          Public Clients / Banks and Insurance
                                                                          Associations and Federations



Portfolio                                    Basic Data
 Business IT Alignment                       Founded in 1990
 Business Information Management             400 employees
 Business Process Management                 8 offices
 Application Development
 SOA and System Integration
 IT Infrastructure Management


                                                                      © OPITZ CONSULTING GmbH 2012           Seite 3
And … who are you?
This talk is about ...

  ... the development of
testable and maintainable
   JavaScript Web Apps
This talk is about ...

  ... the development of
testable and maintainable
   JavaScript Web Apps
Our Sample App ...

http://tigbro.github.com/todo-mobile
https://github.com/tigbro/todo-mobile
Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ CONSULTING - Stefan Scheidt
Software Design
"Multi Page Web App"

Browser                             Server


           HTML-Page
                       Controller   Data     Backend
           UI Values
"AJAX Web App"

Browser                           Server


            Change
AJAX-                Controller            Backend
                                  Data
Engine
            Events
"Single Page Web App"

  Browser             Server




  Controller   Data   Backend
UI Component Libraries
jQuery Mobile




 http://jquerymobile.com/
How can you create this?
<div id="main" data-role="page">
  <div data-role="header">
    <h1>Todos</h1>
    <a href="">Save</a>
    <a href="#settings">Settings</a>
  </div>
  <div data-role="content">
    <div data-role="fieldcontain">
       <form data-ajax="false">
         <input type="text">
       </form>
    </div>
    <fieldset data-role="controlgroup">
       <input type="checkbox" id="todo1"/>
       <label for="todo1">create a mobile todo app</label>
    </fieldset>
  </div>
</div>
                                                 jQuery Mobile Markup
<div id="main" data-role="page">
  <div data-role="header">
    <h1>Todos</h1>
    <a href="">Save</a>
    <a href="#settings">Settings</a>
  </div>
  <div data-role="content">
    <div data-role="fieldcontain">
       <form data-ajax="false">
         <input type="text">
       </form>
    </div>
    <fieldset data-role="controlgroup">
       <input type="checkbox" id="todo1"/>
       <label for="todo1">create a mobile todo app</label>
    </fieldset>
  </div>
</div>
                                                 jQuery Mobile Markup
<div id="main" data-role="page">
  <div data-role="header">
    <h1>Todos</h1>
    <a href="">Save</a>
    <a href="#settings">Settings</a>
  </div>
  <div data-role="content">
    <div data-role="fieldcontain">
       <form data-ajax="false">
         <input type="text">
       </form>
    </div>
    <fieldset data-role="controlgroup">
       <input type="checkbox" id="todo1"/>
       <label for="todo1">create a mobile todo app</label>
    </fieldset>
  </div>
</div>
                                                 jQuery Mobile Markup
<div id="main" data-role="page">
  <div data-role="header">
    <h1>Todos</h1>
    <a href="">Save</a>
    <a href="#settings">Settings</a>
  </div>
  <div data-role="content">
    <div data-role="fieldcontain">
       <form data-ajax="false">
         <input type="text">
       </form>
    </div>
    <fieldset data-role="controlgroup">
       <input type="checkbox" id="todo1"/>
       <label for="todo1">create a mobile todo app</label>
    </fieldset>
  </div>
</div>
                                                 jQuery Mobile Markup
<div id="main" data-role="page">
  <div data-role="header">
    <h1>Todos</h1>
    <a href="">Save</a>
    <a href="#settings">Settings</a>
  </div>
  <div data-role="content">
    <div data-role="fieldcontain">
       <form data-ajax="false">
         <input type="text">
       </form>
    </div>
    <fieldset data-role="controlgroup">
       <input type="checkbox" id="todo1"/>
       <label for="todo1">create a mobile todo app</label>
    </fieldset>
  </div>
</div>
                                                 jQuery Mobile Markup
DOM Transformations
<input type="checkbox" id="todo1"/>
<label for="todo1">create a mobile todo app</label>



<div class="ui-checkbox">
  <input type="checkbox" name="todo.done" id="todo1">
  <label class="ui-btn ui-btn-up-c ui-btn-icon-left
                 ui-btn-corner-all ui-checkbox-off"
          for="todo1" data-theme="c">
    <span class="ui-btn-inner ui-btn-corner-all">
       <span class="ui-btn-text">create a mobile todo app</span>
       <span class="ui-icon ui-icon-checkbox-off
                    ui-icon-shadow"></span>
    </span>
  </label>
</div>

                                     jQuery Mobile Markup Transformation
<input type="checkbox" id="todo1"/>
<label for="todo1">create a mobile todo app</label>



<div class="ui-checkbox">
  <input type="checkbox" name="todo.done" id="todo1">
  <label class="ui-btn ui-btn-up-c ui-btn-icon-left
                 ui-btn-corner-all ui-checkbox-off"
          for="todo1" data-theme="c">
    <span class="ui-btn-inner ui-btn-corner-all">
       <span class="ui-btn-text">create a mobile todo app</span>
       <span class="ui-icon ui-icon-checkbox-off
                    ui-icon-shadow"></span>
    </span>
  </label>
</div>

                                     jQuery Mobile Markup Transformation
Two Way Data Binding
Do it yourself "binding" ...
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
$('#addTodo').submit(function(event) {
    addTodo();
    event.preventDefault();
});

function addTodo() {
    var inputText = $('#inputText').val();
    var list = $('#todos');
    var entryCount = list.find('input').length;
    list.append(entryTemplate(entryCount, inputText));
    list.trigger('create');
    $('#inputText').val('');
}

function entryTemplate(index, name) {
    var id = 'todo' + index;
    return '<input type="checkbox" id="' + id + '"/>' +
           '<label for="' + id + '">' + name + '</label>';
}
Wouldn't this be better ... ?

function TodoController() {
    this.todos = [];
    this.inputText = '';
}

TodoController.prototype.addTodo = function() {
    this.todos.push({
            name: this.inputText,
            done: false
        });
    this.inputText = '';
}
Angular JS

Declarative                       MVC with
UI Templates                      Dependency Injection




Two-Way                           Framework
Data Binding




        http://angularjs.org/#/
Two Way Databinding


       read              read
       write    Data-    write
DOM                              Controller
               binding
       watch             watch
Scopes
                               Scope
                                         Expressions
       $get(<expr>)
                                         'inputText'

                                        'todos.length'
  $set(<expr>, <value>)
                               Object
                                             ...



$watch(<expr>, <callback>)
Demo
<div id="main" data-role="page">
  <div data-role="header">
    <h1>Todos</h1>
    <a href="">Save</a>
    <a href="#settings">Settings</a>
  </div>
  <div data-role="content">
    <div data-role="fieldcontain">
       <form data-ajax="false">
         <input type="text">
       </form>
    </div>
    <fieldset data-role="controlgroup">
       <input type="checkbox" id="todo1"/>
       <label for="todo1">create a mobile todo app</label>
    </fieldset>
  </div>
</div>                                         The DOM
function TodoController() {
    this.todos = [];
    this.inputText = '';
}

TodoController.prototype.addTodo = function() {
    this.todos.push({
            name: this.inputText,
            done: false
        });
    this.inputText = '';
}



                               The Controller
<div data-role="page"                         TodoController Scope
     ng:controller="TodoController">
                                              inputText: 'new todo'
                             create
  <input type="text"                          todos: [...]
         name="inputText"
                                bind
                                       bind
  <div ng:repeat="todo in todos">

                    create                               Repeater Scope
                                                        Repeater Scope
                                                       Repeater Scope
                                               todo: {
                                                todo:
                                              todo: { {
      <input type="checkbox"
             name="todo.done"/>                          done: false
                                                        done: false
                                                       done: false
                                  bind
                                                         name: 'makemoney'
                                                        name: 'makemoney'
                                                       name: 'makemoney'
      <label>
        {{todo.name}}                              }
      </label>
                                bind          }}
We are almost there, but ...
jQuery Mobile & AngularJS

        The problem:

       DOM transformations
done by jQuery Mobile and AngularJS
      need to be coordinated!
jQuery Mobile & AngularJS

       Our Solution:

 jQuery Mobile Angular Adapter
jQuery Mobile Angular Adapter

 Integration of jQuery Mobile & AngularJS

  Extentions for mobile web development

            Open source on GitHub

https://github.com/tigbro/jquery-mobile-angular-adapter
Dependency Injection
Dependency Injection is a design pattern
whose purpose is to reduce the dependencies
          between components.


It delegates the responsibility for creation and
 wiring of objects to an externaly configurable
                  framework.


                    http://de.wikipedia.org/wiki/Dependency_Injection
Dependency Injection is a design pattern
whose purpose is to reduce the dependencies
          between components.


It delegates the responsibility for creation and
 wiring of objects to an externaly configurable
                  framework.


                    http://de.wikipedia.org/wiki/Dependency_Injection
Sample: Calling the backend

var readUrl = 'https://secure.openkeyval.org/';

TodoController.prototype.refreshTodos() {
    var self = this;
    read(readUrl, function(response) {
        self.todos = response;
    });
}
Sample: Calling the backend

var readUrl = 'https://secure.openkeyval.org/';

TodoController.prototype.refreshTodos() {
    var self = this;
    read(readUrl, function(response) {
        self.todos = response;
    });
}
Sample: Calling the backend

var readUrl = 'https://secure.openkeyval.org/';

function read(key, success) {
    var url = readUrl + key;
    waitdialog.show();
    jsonp(url, function(data) {
        success(data);
        waitdialog.hide();
    });
}
Sample: Calling the backend

var readUrl = 'https://secure.openkeyval.org/';

function read(key, success) {
    var url = readUrl + key;
    waitdialog.show();
    jsonp(url, function(data) {
        success(data);
        waitdialog.hide();
    });
}
Sample: Calling the backend

var readUrl = 'https://secure.openkeyval.org/';

function read(key, success) {
    var url = readUrl + key;
    waitdialog.show();
    jsonp(url, function(data) {
        success(data);
        waitdialog.hide();
    });
}
Sample: Calling the backend

                                                   waitDialog
todoController           todoStore                 key     value
key              value   key          value        ...     ...
refreshToDos ...         read         ...
todoStore                waitDialog
                         jsonp                     jsonp
                                                   key     value
                                                   ...     ...

             created                  created by
            with "new"                 Factories
Sample: Calling the backend

                                                  waitDialog
todoController               todoStore            key     value
key              value       key          value   ...     ...
refreshToDos ...             read         ...
todoStore                    waitDialog
                             jsonp                jsonp
                                                  key     value
                                                  ...     ...
                             created by
                         Dependency Injection
Angular: DI for Services
angular.service('jsonp', jsonpFactory);
angular.service('waitdialog', waitdialogFactory);
Angular: DI for Services
angular.service('jsonp', jsonpFactory);
angular.service('waitdialog', waitdialogFactory);

function todoStoreFactory() {
    function read(key, success) { ... }
    // ...
    return {
        read: read
        // ...
    }
}
Angular: DI for Services
angular.service('jsonp', jsonpFactory);
angular.service('waitdialog', waitdialogFactory);

function todoStoreFactory(jsonp, waitdialog) {
    function read(key, success) { ... }
    // ...
    return {
        read: read,
        // ...
    }
}
todoStoreFactory.$inject = ['jsonp', 'waitdialog'];
Angular: DI for Services
angular.service('jsonp', jsonpFactory);
angular.service('waitdialog', waitdialogFactory);

function todoStoreFactory(jsonp, waitdialog) {
    function read(key, success) { ... }
    // ...
    return {
        read: read
        // ...
    }
}
todoStoreFactory.$inject = ['jsonp', 'waitdialog'];
angular.service('todoStore', todoStoreFactory);
Angular: DI for Controller

// ...
angular.service('todoStore', ...);
Angular: DI for Controller

// ...
angular.service('todoStore', ...);

function TodoController(todoStore) {
  // do something with todoStore ...
}
TodoController.$inject = ['todoStore'];
Summary


There are quite a lot of useful design patterns
for the development of JavaScript Web Apps!


                  Use them!
Summary



     Libraries and Frameworks
can help you to get your stuff done!
In the hive 11: nectar and pollen
      by Max xx, http://www.flickr.com/photos/max_westby/4567762490

                                     Books
By Rodrigo Galindez, http://www.flickr.com/photos/rodrigogalindez/4637637337/

                              IMG_1300-Edit
  by Susan E Adams, http://www.flickr.com/photos/susanad813/3912914836/

                                  Doble Via
     by amslerPIX, http://www.flickr.com/photos/amslerpix/6242266697/

                            MacBook Pro Keyboard
by superstrikertwo, http://www.flickr.com/photos/superstrikertwo/4989727256/

                            Stubborn Last Drop
  by RogueSun Media, http://www.flickr.com/photos/shuttercat7/627798443/
The End ...
@stefanscheidt
   @tigbro

More Related Content

PDF
Building iPhone Web Apps using "classic" Domino
PDF
Polymer
PDF
Create a mobile web app with Sencha Touch
PDF
Improving state of M2 front-end - Magento 2 Community Project
PDF
[FEConf Korea 2017]Angular 컴포넌트 대화법
PDF
A mobile web app for Android in 75 minutes
PPTX
Migration to jQuery 3.5.x
PDF
After max+phonegap
Building iPhone Web Apps using "classic" Domino
Polymer
Create a mobile web app with Sencha Touch
Improving state of M2 front-end - Magento 2 Community Project
[FEConf Korea 2017]Angular 컴포넌트 대화법
A mobile web app for Android in 75 minutes
Migration to jQuery 3.5.x
After max+phonegap

What's hot (20)

PDF
QCon 2015 - Thinking in components: A new paradigm for Web UI
PDF
Before there was Hoop Dreams, there was McDonald's: Strange and Beautiful
PDF
GDI Seattle - Intro to JavaScript Class 4
PPTX
J Query (Complete Course) by Muhammad Ehtisham Siddiqui
PDF
Creating GUI Component APIs in Angular and Web Components
PDF
Accessible Salesforce
PDF
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
PDF
Creating GUI container components in Angular and Web Components
PPTX
jQuery Mobile Introduction ( demo on EZoapp )
KEY
WordCamp Denver 2012 - Custom Meta Boxes
PPTX
APIs for catalogs
PDF
Dig Deeper into WordPress - WD Meetup Cairo
PPTX
AngularJS On-Ramp
PDF
Java Web Development with Stripes
PDF
jQuery: Nuts, Bolts and Bling
PDF
Introduction to Web Components
PPTX
jQuery Presentasion
KEY
Html5 For Jjugccc2009fall
PDF
Vaadin DevDay 2017 - Web Components
PPTX
Educate 2017: Customizing Authoring: How our APIs let you create powerful sol...
QCon 2015 - Thinking in components: A new paradigm for Web UI
Before there was Hoop Dreams, there was McDonald's: Strange and Beautiful
GDI Seattle - Intro to JavaScript Class 4
J Query (Complete Course) by Muhammad Ehtisham Siddiqui
Creating GUI Component APIs in Angular and Web Components
Accessible Salesforce
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
Creating GUI container components in Angular and Web Components
jQuery Mobile Introduction ( demo on EZoapp )
WordCamp Denver 2012 - Custom Meta Boxes
APIs for catalogs
Dig Deeper into WordPress - WD Meetup Cairo
AngularJS On-Ramp
Java Web Development with Stripes
jQuery: Nuts, Bolts and Bling
Introduction to Web Components
jQuery Presentasion
Html5 For Jjugccc2009fall
Vaadin DevDay 2017 - Web Components
Educate 2017: Customizing Authoring: How our APIs let you create powerful sol...
Ad

Similar to Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ CONSULTING - Stefan Scheidt (20)

PDF
HTML5 and Mobile
PDF
HTML5 New and Improved
PDF
混搭移动开发:PhoneGap+JQurey+Dreamweaver
PDF
HTML5 and the dawn of rich mobile web applications pt 2
PPSX
Introduction to Html5
PPTX
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012
PPTX
jQuery Mobile
PDF
Pengenalan AngularJS
PDF
Once Source to Rule Them All
PPTX
Adobe & HTML5
PPTX
One Size Fits All
KEY
jQuery: Tips, tricks and hints for better development and Performance
PPTX
Angular directive filter and routing
PPTX
JQuery Mobile UI
PDF
iWebkit
TXT
Xxx
PDF
E2 appspresso hands on lab
PDF
E3 appspresso hands on lab
PDF
Effective Android Data Binding
PPTX
jQuery Mobile - Desenvolvimento para dispositivos móveis
HTML5 and Mobile
HTML5 New and Improved
混搭移动开发:PhoneGap+JQurey+Dreamweaver
HTML5 and the dawn of rich mobile web applications pt 2
Introduction to Html5
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012
jQuery Mobile
Pengenalan AngularJS
Once Source to Rule Them All
Adobe & HTML5
One Size Fits All
jQuery: Tips, tricks and hints for better development and Performance
Angular directive filter and routing
JQuery Mobile UI
iWebkit
Xxx
E2 appspresso hands on lab
E3 appspresso hands on lab
Effective Android Data Binding
jQuery Mobile - Desenvolvimento para dispositivos móveis
Ad

More from OPITZ CONSULTING Deutschland (20)

PDF
OC|Webcast: Grundlagen der Oracle Lizenzierung
PDF
OC|Webcast "Java heute" vom 28.09.2021
PDF
OC|Webcast "Java heute" vom 24.08.2021
PDF
OC|Webcast "Daten wirklich nutzen"
PDF
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
PDF
OC|Webcast "Willkommen in der Cloud!"
PDF
OC|Webcast "Die neue Welt der Virtualisierung"
PDF
10 Thesen zur professionellen Softwareentwicklung
PDF
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
PDF
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
PDF
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
PDF
OC|Webcast: Grundlagen der Oracle-Lizenzierung
PDF
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
PDF
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
PDF
OC|Weekly Talk The Power of DevOps…
PDF
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
PDF
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
PDF
OC|Weekly Talk - Digitales Coaching & Smart Sparring
PDF
OC|Weekly Talk - Beratung remote
PDF
Effiziente Betriebsoptimierung durch Cloud Nutzung
OC|Webcast: Grundlagen der Oracle Lizenzierung
OC|Webcast "Java heute" vom 28.09.2021
OC|Webcast "Java heute" vom 24.08.2021
OC|Webcast "Daten wirklich nutzen"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
OC|Webcast "Willkommen in der Cloud!"
OC|Webcast "Die neue Welt der Virtualisierung"
10 Thesen zur professionellen Softwareentwicklung
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Grundlagen der Oracle-Lizenzierung
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Weekly Talk The Power of DevOps…
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Beratung remote
Effiziente Betriebsoptimierung durch Cloud Nutzung

Recently uploaded (20)

PDF
Review of recent advances in non-invasive hemoglobin estimation
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Machine learning based COVID-19 study performance prediction
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Modernizing your data center with Dell and AMD
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
cuic standard and advanced reporting.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
Review of recent advances in non-invasive hemoglobin estimation
Digital-Transformation-Roadmap-for-Companies.pptx
The Rise and Fall of 3GPP – Time for a Sabbatical?
20250228 LYD VKU AI Blended-Learning.pptx
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
Unlocking AI with Model Context Protocol (MCP)
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Diabetes mellitus diagnosis method based random forest with bat algorithm
Understanding_Digital_Forensics_Presentation.pptx
Machine learning based COVID-19 study performance prediction
NewMind AI Monthly Chronicles - July 2025
Modernizing your data center with Dell and AMD
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
cuic standard and advanced reporting.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Reach Out and Touch Someone: Haptics and Empathic Computing

Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ CONSULTING - Stefan Scheidt

  • 1. Design Patterns for JavaScript Web Apps Stefan Scheidt OPITZ CONSULTING GmbH
  • 3. Mission Markets The company's ambition is to help  Branchspreading organizations to be better than their  Over 600 customers competitors. 29% Trade / Logistics / Our services take place in partnership and 29% Supplier Industry / Services / are aimed at co-operation of many years. Telecommunications 42% Public Clients / Banks and Insurance Associations and Federations Portfolio Basic Data  Business IT Alignment  Founded in 1990  Business Information Management  400 employees  Business Process Management  8 offices  Application Development  SOA and System Integration  IT Infrastructure Management © OPITZ CONSULTING GmbH 2012 Seite 3
  • 4. And … who are you?
  • 5. This talk is about ... ... the development of testable and maintainable JavaScript Web Apps
  • 6. This talk is about ... ... the development of testable and maintainable JavaScript Web Apps
  • 7. Our Sample App ... http://tigbro.github.com/todo-mobile https://github.com/tigbro/todo-mobile
  • 10. "Multi Page Web App" Browser Server HTML-Page Controller Data Backend UI Values
  • 11. "AJAX Web App" Browser Server Change AJAX- Controller Backend Data Engine Events
  • 12. "Single Page Web App" Browser Server Controller Data Backend
  • 15. How can you create this?
  • 16. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 17. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 18. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 19. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 20. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 22. <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> jQuery Mobile Markup Transformation
  • 23. <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> jQuery Mobile Markup Transformation
  • 24. Two Way Data Binding
  • 25. Do it yourself "binding" ...
  • 26. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 27. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 28. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 29. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 30. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 31. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 32. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 33. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 34. Wouldn't this be better ... ? function TodoController() { this.todos = []; this.inputText = ''; } TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; }
  • 35. Angular JS Declarative MVC with UI Templates Dependency Injection Two-Way Framework Data Binding http://angularjs.org/#/
  • 36. Two Way Databinding read read write Data- write DOM Controller binding watch watch
  • 37. Scopes Scope Expressions $get(<expr>) 'inputText' 'todos.length' $set(<expr>, <value>) Object ... $watch(<expr>, <callback>)
  • 38. Demo
  • 39. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> The DOM
  • 40. function TodoController() { this.todos = []; this.inputText = ''; } TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; } The Controller
  • 41. <div data-role="page" TodoController Scope ng:controller="TodoController"> inputText: 'new todo' create <input type="text" todos: [...] name="inputText" bind bind <div ng:repeat="todo in todos"> create Repeater Scope Repeater Scope Repeater Scope todo: { todo: todo: { { <input type="checkbox" name="todo.done"/> done: false done: false done: false bind name: 'makemoney' name: 'makemoney' name: 'makemoney' <label> {{todo.name}} } </label> bind }}
  • 42. We are almost there, but ...
  • 43. jQuery Mobile & AngularJS The problem: DOM transformations done by jQuery Mobile and AngularJS need to be coordinated!
  • 44. jQuery Mobile & AngularJS Our Solution: jQuery Mobile Angular Adapter
  • 45. jQuery Mobile Angular Adapter Integration of jQuery Mobile & AngularJS Extentions for mobile web development Open source on GitHub https://github.com/tigbro/jquery-mobile-angular-adapter
  • 47. Dependency Injection is a design pattern whose purpose is to reduce the dependencies between components. It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
  • 48. Dependency Injection is a design pattern whose purpose is to reduce the dependencies between components. It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
  • 49. Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; }); }
  • 50. Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; }); }
  • 51. Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 52. Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 53. Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 54. Sample: Calling the backend waitDialog todoController todoStore key value key value key value ... ... refreshToDos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created created by with "new" Factories
  • 55. Sample: Calling the backend waitDialog todoController todoStore key value key value key value ... ... refreshToDos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created by Dependency Injection
  • 56. Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory);
  • 57. Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory() { function read(key, success) { ... } // ... return { read: read // ... } }
  • 58. Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read, // ... } } todoStoreFactory.$inject = ['jsonp', 'waitdialog'];
  • 59. Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read // ... } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todoStore', todoStoreFactory);
  • 60. Angular: DI for Controller // ... angular.service('todoStore', ...);
  • 61. Angular: DI for Controller // ... angular.service('todoStore', ...); function TodoController(todoStore) { // do something with todoStore ... } TodoController.$inject = ['todoStore'];
  • 62. Summary There are quite a lot of useful design patterns for the development of JavaScript Web Apps! Use them!
  • 63. Summary Libraries and Frameworks can help you to get your stuff done!
  • 64. In the hive 11: nectar and pollen by Max xx, http://www.flickr.com/photos/max_westby/4567762490 Books By Rodrigo Galindez, http://www.flickr.com/photos/rodrigogalindez/4637637337/ IMG_1300-Edit by Susan E Adams, http://www.flickr.com/photos/susanad813/3912914836/ Doble Via by amslerPIX, http://www.flickr.com/photos/amslerpix/6242266697/ MacBook Pro Keyboard by superstrikertwo, http://www.flickr.com/photos/superstrikertwo/4989727256/ Stubborn Last Drop by RogueSun Media, http://www.flickr.com/photos/shuttercat7/627798443/