SlideShare une entreprise Scribd logo
1  sur  70
Télécharger pour lire hors ligne
Tobias	
  Bosch	
  &	
  
Stefan	
  Scheidt	
  /	
  OPITZ	
  CONSULTING	
  GmbH	
  

JavaScript	
  Data	
  Binding	
  
mit	
  jQuery	
  Mobile	
  
Wer	
  sind	
  wir?	
  

 tobias.bosch@opitz-­‐consulQng.com	
  
              (@Qgbro)	
  
                 	
  
stefan.scheidt@opitz-­‐consulQng.com	
  
            (@beezlebug)	
  
                 	
  
Märkte                             Kunden                                               Leistungs-              Fakten
                                                                                        angebot
n Java                            n Branchen-                                         n IT-Strategie         n Gründung 1990
n SOA                                übergreifend                                      n Beratung             n 400 Mitarbeiter
n ORACLE                          n Über 600                                          n Implementierung      n 8 Standorte in D/
n BI/DWH                             Kunden                                            n Betrieb                 PL
n Outtasking                                                                           n Training
                                 Industrie / Versorger /          Handel / Logistik /
                                   Telekommunikation              Dienstleistungen
                                                   29%            29%




                                                           42%
                                                Öffentliche Auftraggeber /
                                               Banken & Versicherungen /
                                                   Vereine & Verbände




 Das Bild kann nicht angezeigt
 werden. Dieser Computer
 verfügt möglicherweise über
 zu wenig Arbeitsspeicher, um
 das Bild zu öffnen, oder das
                                                                                                       © OPITZ CONSULTING GmbH 2011   Seite 3
Wer	
  sind	
  Sie?	
  
In	
  diesem	
  Vortrag	
  geht‘s	
  um...	
  
                     	
  
...die	
  Entwicklung	
  testbarer	
  und	
  
  wartbarer	
  mobiler	
  Web-­‐Apps	
  
Unser	
  Beispiel	
  
Unser	
  Beispiel...	
  
Mobile	
  Web-­‐Apps	
  
Architektur	
  
"MulQ	
  Page	
  Web	
  App"	
  

Browser	
                                            Server	
  


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

Browser	
                                     Server	
  


               Change	
  
 AJAX-­‐	
                  Controller	
                   Ba
                                             Data	
  
 Engine	
  
               Events	
  
"Single	
  Page	
  Web	
  App"	
  

    Browser	
                   Server	
  




   Controller	
     Data	
     Backend	
  
Bibliotheken	
  
jQuery	
  Mobile	
  




 h=p://jquerymobile.com/	
  
Noch	
  einmal	
  unser	
  Beispiel...	
  
<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	
  
<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-­‐TransformaQon	
  
durch	
  jQuery	
  Mobile	
  
V            orhe
<input	
  type="checkbox"	
  id="todo1"/>	
                                                                              r	
  
<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	
  TransformaIon	
  
<input	
  type="checkbox"	
  id="todo1"/>	
  
<label	
  for="todo1">create	
  a	
  mobile	
  todo	
  app</label>	
  
	
  
	
                                                                                                                  Nach
<div	
  class="ui-­‐checkbox">	
  
                                                                                                                        her	
  
	
  	
  <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	
  TransformaIon	
  
Manuelles	
  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');	
  
	
  	
  	
  	
  $('#input').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');	
  
	
  	
  	
  	
  $('#input').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');	
  
	
  	
  	
  	
  $('#input').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');	
  
	
  	
  	
  	
  $('#input').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');	
  
	
  	
  	
  	
  $('#input').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');	
  
	
  	
  	
  	
  $('#input').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');	
  
	
  	
  	
  	
  $('#input').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');	
  
	
  	
  	
  	
  $('#input').val('');	
  
}	
  
	
  
function	
  entryTemplate(index,	
  name)	
  {	
  
	
  	
  	
  	
  var	
  id	
  =	
  'todo'	
  +	
  index;	
  
	
  	
  	
  	
  return	
  '<input	
  type="checkbox"	
  id="'	
  +	
  id	
  +	
  '"/>'	
  +	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  '<label	
  for="'	
  +	
  id	
  +	
  '">'	
  +	
  name	
  +	
  '</label>';	
  
}	
  
Das	
  Ziel	
  ist	
  aber:	
  
function	
  TodoController()	
  {	
  
	
  	
  	
  	
  this.todos	
  =	
  [];	
  
	
  	
  	
  	
  this.inputText	
  =	
  '';	
  
}	
  
	
  
TodoController.prototype	
  =	
  {	
  
	
  	
  	
  	
  addTodo:	
  function()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.todos.push({	
  
                         	
              	
  name:	
  this.inputText,	
  	
  
                         	
              	
  done:	
  false	
  
                         	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.inputText	
  =	
  '';	
  
	
  	
  	
  	
  }	
  
}	
  
Angular	
  JS	
  

DeclaraQve	
                             MVC	
  with	
  
UI	
  Templates	
                        Dependency	
  InjecQon	
  




Two-­‐Way	
                              Framework	
  
Data	
  Binding	
  




            h=p://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>)	
  
<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>	
                                                                   Das	
  DOM	
  
function	
  TodoController()	
  {	
  
	
  	
  	
  	
  this.todos	
  =	
  [];	
  
	
  	
  	
  	
  this.inputText	
  =	
  '';	
  
}	
  
	
  
TodoController.prototype	
  =	
  {	
  
	
  	
  	
  	
  addTodo:	
  function()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.todos.push({	
  
                         	
              	
  name:	
  this.inputText,	
  	
  
                         	
              	
  done:	
  false	
  
                         	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.inputText	
  =	
  '';	
  
	
  	
  	
  	
  }	
  
}	
  


                                                   Der	
  Controller	
  
<div	
  data-­‐role="page"	
                                             	
  TodoController-­‐Scope	
  
	
  	
  	
  	
  	
  ng:controller="TodoController">	
                    	
  
                                                                         inputText:	
  'new	
  todo'	
  
                                                   erzeugt	
             	
  
    <input	
  type="text"	
  	
                                          todos:	
  [...]	
  
    	
  	
  	
  	
  	
  	
  	
  name="inputText"	
  
                                                        bindet	
  
                                                                 bindet	
  
    <div	
  ng:repeat="todo	
  in	
  todos">	
  

                                      erzeugt	
                                          Repeater	
  SScope	
  
                                                                                          Repeater	
  cope	
  
                                                                         	
   	
   	
   Repeater	
  Scope	
  
                                                                         	
   	
   	
  
                                                                                   todo:	
  {	
  
                                                                              todo:	
  {	
  
                                                                         todo:	
  {	
  
            <input	
  type="checkbox"	
                                            	
  
                                                                         	
   	
  
            	
  	
  	
  	
  	
  	
  	
  name="todo.done"/>	
                       	
  	
  	
  	
  done:	
  false	
  
                                                                              	
  	
  	
  	
  done:	
  false	
  
                                                                         	
  	
  	
  	
  done:	
  false	
  
                                                            bindet	
     	
   	
  
                                                                                   	
  
                                                                                   	
  	
  	
  	
  name:	
  'makemoney'	
  
                                                                              	
  	
  	
  	
  name:	
  'makemoney'	
  
                                                                         	
  	
  	
  	
  name:	
  'makemoney'	
  
            <label>	
                                                              	
  
                                                                         	
   	
  
            	
  	
  {{todo.name}}	
  
            </label>	
  
                                                        bindet	
         }	
  }	
  }	
  
Damit	
  ist	
  das	
  Ziel	
  fast	
  erreicht...	
  
Die	
  DOM-­‐ManipulaQonen	
  von	
  
      jQuery	
  Mobile	
  und	
  Angular	
  JS	
  
müssen	
  "nur	
  noch"	
  koordiniert	
  werden.	
  
Dazu	
  später	
  mehr!	
  
Angular	
  JS	
  

DeclaraQve	
                             MVC	
  with	
  
UI	
  Templates	
                        Dependency	
  InjecQon	
  




Two-­‐Way	
                              Framework	
  
Data	
  Binding	
  




            h=p://angularjs.org/#/	
  
Backend-­‐Anbindung	
  

var	
  readUrl	
  =	
  'https://secure.openkeyval.org/';	
  
var	
  jsonp	
  =	
  ...;	
  
var	
  waitdialog	
  =	
  ...;	
  
	
  
function	
  read(key,	
  success)	
  {	
  
	
  	
  	
  	
  var	
  url	
  =	
  readUrl	
  +	
  key;	
  
	
  	
  	
  	
  waitdialog.show();	
  
	
  	
  	
  	
  jsonp(url,	
  function(data)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  success(data);	
  
	
  	
  	
  	
  	
  	
  	
  	
  waitdialog.hide();	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  });	
  
}	
  
Backend-­‐Anbindung	
  

var	
  readUrl	
  =	
  'https://secure.openkeyval.org/';	
  
var	
  jsonp	
  =	
  ...;	
  
var	
  waitdialog	
  =	
  ...;	
  
	
  
function	
  read(key,	
  success)	
  {	
  
	
  	
  	
  	
  var	
  url	
  =	
  readUrl	
  +	
  key;	
  
	
  	
  	
  	
  waitdialog.show();	
  
	
  	
  	
  	
  jsonp(url,	
  function(data)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  success(data);	
  
	
  	
  	
  	
  	
  	
  	
  	
  waitdialog.hide();	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  });	
  
}	
  
Backend-­‐Anbindung	
  

var	
  readUrl	
  =	
  'https://secure.openkeyval.org/';	
  
var	
  jsonp	
  =	
  ...;	
  
var	
  waitdialog	
  =	
  ...;	
  
	
  
function	
  read(key,	
  success)	
  {	
  
	
  	
  	
  	
  var	
  url	
  =	
  readUrl	
  +	
  key;	
  
	
  	
  	
  	
  waitdialog.show();	
  
	
  	
  	
  	
  jsonp(url,	
  function(data)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  success(data);	
  
	
  	
  	
  	
  	
  	
  	
  	
  waitdialog.hide();	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  });	
  
}	
  
Services	
  und	
  DI	
  mit	
  Angular	
  
angular.service('jsonp',	
  jsonpFactory);	
  
angular.service('waitdialog',	
  waitdialogFactory);	
  
	
  
function	
  todoStoreFactory(jsonp,	
  waitdialog)	
  {	
  
	
  	
  	
  	
  function	
  read(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  function	
  write(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  return	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  read:	
  read,	
  
	
  	
  	
  	
  	
  	
  	
  	
  write:	
  write	
  
	
  	
  	
  	
  }	
  
}	
  
	
  
todoStoreFactory.$inject	
  =	
  ['jsonp',	
  'waitdialog'];	
  
angular.service('todostore',	
  todoStoreFactory);	
  
Services	
  und	
  DI	
  mit	
  Angular	
  
angular.service('jsonp',	
  jsonpFactory);	
  
angular.service('waitdialog',	
  waitdialogFactory);	
  
	
  
function	
  todoStoreFactory(jsonp,	
  waitdialog)	
  {	
  
	
  	
  	
  	
  function	
  read(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  function	
  write(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  return	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  read:	
  read,	
  
	
  	
  	
  	
  	
  	
  	
  	
  write:	
  write	
  
	
  	
  	
  	
  }	
  
}	
  
	
  
todoStoreFactory.$inject	
  =	
  ['jsonp',	
  'waitdialog'];	
  
angular.service('todostore',	
  todoStoreFactory);	
  
Services	
  und	
  DI	
  mit	
  Angular	
  
angular.service('jsonp',	
  jsonpFactory);	
  
angular.service('waitdialog',	
  waitdialogFactory);	
  
	
  
function	
  todoStoreFactory(jsonp,	
  waitdialog)	
  {	
  
	
  	
  	
  	
  function	
  read(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  function	
  write(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  return	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  read:	
  read,	
  
	
  	
  	
  	
  	
  	
  	
  	
  write:	
  write	
  
	
  	
  	
  	
  }	
  
}	
  
	
  
todoStoreFactory.$inject	
  =	
  ['jsonp',	
  'waitdialog'];	
  
angular.service('todostore',	
  todoStoreFactory);	
  
Services	
  und	
  DI	
  mit	
  Angular	
  
angular.service('jsonp',	
  jsonpFactory);	
  
angular.service('waitdialog',	
  waitdialogFactory);	
  
	
  
function	
  todoStoreFactory(jsonp,	
  waitdialog)	
  {	
  
	
  	
  	
  	
  function	
  read(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  function	
  write(...)	
  {	
  ...	
  }	
  
	
  	
  	
  	
  return	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  read:	
  read,	
  
	
  	
  	
  	
  	
  	
  	
  	
  write:	
  write	
  
	
  	
  	
  	
  }	
  
}	
  
	
  
todoStoreFactory.$inject	
  =	
  ['jsonp',	
  'waitdialog'];	
  
angular.service('todostore',	
  todoStoreFactory);	
  
Di	
  für	
  Controller	
  


function	
  TodoController(todoStore)	
  {	
  
	
  	
  ...	
  
}	
  
	
  
TodoController.$inject	
  =	
  ['todoStore'];	
  
Di	
  für	
  Controller	
  


function	
  TodoController(todoStore)	
  {	
  
	
  	
  ...	
  
}	
  
	
  
TodoController.$inject	
  =	
  ['todoStore'];	
  
Di	
  für	
  Controller	
  


function	
  TodoController(todoStore)	
  {	
  
	
  	
  ...	
  
}	
  
	
  
TodoController.$inject	
  =	
  ['todoStore'];	
  
One	
  more	
  thing...	
  
               	
  
IntegraQon	
  von	
  AngularJS	
  
    und	
  jQuery	
  Mobile	
  
jquery-­‐mobile-­‐angular-­‐adapter	
  

KoordinaQon	
  von	
  jQuery	
  Mobile	
  und	
  Angular	
  JS	
  
                           	
  
     Erweiterungen	
  für	
  mobile	
  Web-­‐Apps	
  
                           	
  
                Open	
  Source	
  unter	
  	
  
         heps://github.com/Qgbro/	
  
       jquery-­‐mobile-­‐angular-­‐adapter	
  
Paging	
  in	
  Listen	
  
<div	
  ng:repeat=	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "todo	
  in	
  todos.$paged()">	
  
                         	
  ...	
  
</div>	
  
	
  
<div	
  ng:if=	
  
	
  	
  	
  	
  	
  "todos.$paged().hasMorePages()">	
  
	
  	
  	
  <a	
  href="#"	
  ngm:click=	
  
	
  	
  	
  	
  	
  "todos.$paged().loadNextPage()">	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Load	
  more	
  
	
  	
  	
  </a>	
  
</div>	
  
Paging	
  in	
  Listen	
  
<div	
  ng:repeat=	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "todo	
  in	
  todos.$paged()">	
  
                         	
  ...	
  
</div>	
  
	
  
<div	
  ng:if=	
  
	
  	
  	
  	
  	
  "todos.$paged().hasMorePages()">	
  
	
  	
  	
  <a	
  href="#"	
  ngm:click=	
  
	
  	
  	
  	
  	
  "todos.$paged().loadNextPage()">	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Load	
  more	
  
	
  	
  	
  </a>	
  
</div>	
  
Paging	
  in	
  Listen	
  
<div	
  ng:repeat=	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "todo	
  in	
  todos.$paged()">	
  
                         	
  ...	
  
</div>	
  
	
  
<div	
  ng:if=	
  
	
  	
  	
  	
  	
  "todos.$paged().hasMorePages()">	
  
	
  	
  	
  <a	
  href="#"	
  ngm:click=	
  
	
  	
  	
  	
  	
  "todos.$paged().loadNextPage()">	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Load	
  more	
  
	
  	
  	
  </a>	
  
</div>	
  
Mobile	
  Events	
  

<div	
  id="main"	
  data-­‐role="page"	
  	
  	
  
	
  	
  	
  	
  	
  ng:event="swipeleft:showSettings()">	
  
	
  	
  	
  	
  ...	
  
</div>	
  
	
  
	
  
<div	
  id="settings"	
  data-­‐role="page"	
  	
  
	
  	
  	
  	
  	
  ng:event="swiperight:back()">	
  
	
  	
  	
  	
  ...	
  
</div>	
  
	
  
NavigaQon	
  über	
  Pages	
  
function	
  TodoController(todoStore,	
  activePage)	
  {	
  ...	
  }	
  
	
  
TodoController.prototype	
  =	
  {	
  
	
  	
  	
  	
  onActivate:	
  function(prevscope)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (prevscope	
  &&	
  prevscope.storageKey)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.storageKey	
  =	
  prevscope.storageKey;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.refreshTodos();	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  },	
  
	
  	
  	
  	
  showSettings:	
  function()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.activePage("#settings");	
  
	
  	
  	
  	
  }	
  
};	
  
NavigaQon	
  über	
  Pages	
  
function	
  TodoController(todoStore,	
  activePage)	
  {	
  ...	
  }	
  
	
  
TodoController.prototype	
  =	
  {	
  
	
  	
  	
  	
  onActivate:	
  function(prevscope)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (prevscope	
  &&	
  prevscope.storageKey)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.storageKey	
  =	
  prevscope.storageKey;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.refreshTodos();	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  },	
  
	
  	
  	
  	
  showSettings:	
  function()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.activePage("#settings");	
  
	
  	
  	
  	
  }	
  
};	
  
NavigaQon	
  über	
  Pages	
  
function	
  TodoController(todoStore,	
  activePage)	
  {	
  ...	
  }	
  
	
  
TodoController.prototype	
  =	
  {	
  
	
  	
  	
  	
  onActivate:	
  function(prevscope)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (prevscope	
  &&	
  prevscope.storageKey)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.storageKey	
  =	
  prevscope.storageKey;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.refreshTodos();	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  },	
  
	
  	
  	
  	
  showSettings:	
  function()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.activePage("#settings");	
  
	
  	
  	
  	
  }	
  
};	
  
Wait-­‐Dialog	
  Service	
  
waitDialog.show('loading');	
  
	
  
waitDialog.hide();	
  




waitDialog.show('click	
  to	
  abort',	
  	
  
      	
  onClickCallback);	
  
Fazit	
  


     Auch	
  bei	
  der	
  Entwicklung	
  	
  
      von	
  JavaScript	
  Clients	
  
sollten	
  geeignete	
  Entwurfsmuster	
  
       angewendet	
  werden!	
  
                      	
  
Fazit	
  



Bibliotheken	
  und	
  Frameworks	
  
  helfen	
  bei	
  der	
  Umsetzung!	
  
                     	
  
Fazit	
  

Eine	
  praxiserprobte	
  KombinaQon:	
  
                       	
  
             jQuery	
  Mobile	
  
               +	
  AngularJS	
  
                +	
  Adapter	
  
                       	
  
In	
  the	
  hive	
  11:	
  nectar	
  and	
  pollen	
  
         by	
  Max	
  xx,	
  hep://www.flickr.com/photos/max_westby/4567762490	
  
                                                                	
  
                                                          Books	
  
By	
  Rodrigo	
  Galindez,	
  hep://www.flickr.com/photos/rodrigogalindez/4637637337/	
  
                                                                	
  
Vielen	
  Dank	
  
für	
  Ihr	
  Interesse!	
  
          	
  
       @Qgbro	
  
      @beezlebug	
  

Contenu connexe

Plus de Stefan Scheidt

Understanding the Four Rules of Simple Design
Understanding the Four Rules of Simple DesignUnderstanding the Four Rules of Simple Design
Understanding the Four Rules of Simple DesignStefan Scheidt
 
iOS: Einstieg und Ausblick
iOS: Einstieg und AusblickiOS: Einstieg und Ausblick
iOS: Einstieg und AusblickStefan Scheidt
 
Fruehling fuers iPhone
Fruehling fuers iPhoneFruehling fuers iPhone
Fruehling fuers iPhoneStefan Scheidt
 
Automatischer Build mit Maven
Automatischer Build mit MavenAutomatischer Build mit Maven
Automatischer Build mit MavenStefan Scheidt
 
ipdc10: Spring Backends für iOS Apps
ipdc10: Spring Backends für iOS Appsipdc10: Spring Backends für iOS Apps
ipdc10: Spring Backends für iOS AppsStefan Scheidt
 
WJAX 2010: Spring Backends für iOS Apps
WJAX 2010: Spring Backends für iOS AppsWJAX 2010: Spring Backends für iOS Apps
WJAX 2010: Spring Backends für iOS AppsStefan Scheidt
 

Plus de Stefan Scheidt (7)

Kotlin DSLs
Kotlin DSLsKotlin DSLs
Kotlin DSLs
 
Understanding the Four Rules of Simple Design
Understanding the Four Rules of Simple DesignUnderstanding the Four Rules of Simple Design
Understanding the Four Rules of Simple Design
 
iOS: Einstieg und Ausblick
iOS: Einstieg und AusblickiOS: Einstieg und Ausblick
iOS: Einstieg und Ausblick
 
Fruehling fuers iPhone
Fruehling fuers iPhoneFruehling fuers iPhone
Fruehling fuers iPhone
 
Automatischer Build mit Maven
Automatischer Build mit MavenAutomatischer Build mit Maven
Automatischer Build mit Maven
 
ipdc10: Spring Backends für iOS Apps
ipdc10: Spring Backends für iOS Appsipdc10: Spring Backends für iOS Apps
ipdc10: Spring Backends für iOS Apps
 
WJAX 2010: Spring Backends für iOS Apps
WJAX 2010: Spring Backends für iOS AppsWJAX 2010: Spring Backends für iOS Apps
WJAX 2010: Spring Backends für iOS Apps
 

Java script data binding mit jQuery Mobile

  • 1. Tobias  Bosch  &   Stefan  Scheidt  /  OPITZ  CONSULTING  GmbH   JavaScript  Data  Binding   mit  jQuery  Mobile  
  • 2. Wer  sind  wir?   tobias.bosch@opitz-­‐consulQng.com   (@Qgbro)     stefan.scheidt@opitz-­‐consulQng.com   (@beezlebug)    
  • 3. Märkte Kunden Leistungs- Fakten angebot n Java n Branchen- n IT-Strategie n Gründung 1990 n SOA übergreifend n Beratung n 400 Mitarbeiter n ORACLE n Über 600 n Implementierung n 8 Standorte in D/ n BI/DWH Kunden n Betrieb PL n Outtasking n Training Industrie / Versorger / Handel / Logistik / Telekommunikation Dienstleistungen 29% 29% 42% Öffentliche Auftraggeber / Banken & Versicherungen / Vereine & Verbände Das Bild kann nicht angezeigt werden. Dieser Computer verfügt möglicherweise über zu wenig Arbeitsspeicher, um das Bild zu öffnen, oder das © OPITZ CONSULTING GmbH 2011 Seite 3
  • 5. In  diesem  Vortrag  geht‘s  um...     ...die  Entwicklung  testbarer  und   wartbarer  mobiler  Web-­‐Apps  
  • 8.
  • 11. "MulQ  Page  Web  App"   Browser   Server   HTML-­‐Page   Controller   Data   Backend   UI  Values  
  • 12. "AJAX  Web  App"   Browser   Server   Change   AJAX-­‐   Controller   Ba Data   Engine   Events  
  • 13. "Single  Page  Web  App"   Browser   Server   Controller   Data   Backend  
  • 15. jQuery  Mobile   h=p://jquerymobile.com/  
  • 16. Noch  einmal  unser  Beispiel...  
  • 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  
  • 21. <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. <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  
  • 24. V orhe <input  type="checkbox"  id="todo1"/>   r   <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  TransformaIon  
  • 25. <input  type="checkbox"  id="todo1"/>   <label  for="todo1">create  a  mobile  todo  app</label>       Nach <div  class="ui-­‐checkbox">   her      <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  TransformaIon  
  • 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');          $('#input').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');          $('#input').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');          $('#input').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');          $('#input').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');          $('#input').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');          $('#input').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');          $('#input').val('');   }     function  entryTemplate(index,  name)  {          var  id  =  'todo'  +  index;          return  '<input  type="checkbox"  id="'  +  id  +  '"/>'  +                        '<label  for="'  +  id  +  '">'  +  name  +  '</label>';   }  
  • 34. $('#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');          $('#input').val('');   }     function  entryTemplate(index,  name)  {          var  id  =  'todo'  +  index;          return  '<input  type="checkbox"  id="'  +  id  +  '"/>'  +                        '<label  for="'  +  id  +  '">'  +  name  +  '</label>';   }  
  • 35. Das  Ziel  ist  aber:   function  TodoController()  {          this.todos  =  [];          this.inputText  =  '';   }     TodoController.prototype  =  {          addTodo:  function()  {                  this.todos.push({      name:  this.inputText,        done:  false      });                  this.inputText  =  '';          }   }  
  • 36. Angular  JS   DeclaraQve   MVC  with   UI  Templates   Dependency  InjecQon   Two-­‐Way   Framework   Data  Binding   h=p://angularjs.org/#/  
  • 37. Two-­‐Way  Databinding   read   read   write   Data-­‐ write   DOM   Controller   binding   watch   watch  
  • 38. Scopes   Scope   Expressions   $get(<expr>)   'inputText'   'todos.length'   $set(<expr>,  <value>)   Object   ...   $watch(<expr>,  <callback>)  
  • 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>   Das  DOM  
  • 40. function  TodoController()  {          this.todos  =  [];          this.inputText  =  '';   }     TodoController.prototype  =  {          addTodo:  function()  {                  this.todos.push({      name:  this.inputText,        done:  false      });                  this.inputText  =  '';          }   }   Der  Controller  
  • 41. <div  data-­‐role="page"    TodoController-­‐Scope            ng:controller="TodoController">     inputText:  'new  todo'   erzeugt     <input  type="text"     todos:  [...]                name="inputText"   bindet   bindet   <div  ng:repeat="todo  in  todos">   erzeugt   Repeater  SScope   Repeater  cope         Repeater  Scope         todo:  {   todo:  {   todo:  {   <input  type="checkbox"                      name="todo.done"/>          done:  false          done:  false          done:  false   bindet                name:  'makemoney'          name:  'makemoney'          name:  'makemoney'   <label>            {{todo.name}}   </label>   bindet   }  }  }  
  • 42. Damit  ist  das  Ziel  fast  erreicht...  
  • 43. Die  DOM-­‐ManipulaQonen  von   jQuery  Mobile  und  Angular  JS   müssen  "nur  noch"  koordiniert  werden.  
  • 45. Angular  JS   DeclaraQve   MVC  with   UI  Templates   Dependency  InjecQon   Two-­‐Way   Framework   Data  Binding   h=p://angularjs.org/#/  
  • 46. Backend-­‐Anbindung   var  readUrl  =  'https://secure.openkeyval.org/';   var  jsonp  =  ...;   var  waitdialog  =  ...;     function  read(key,  success)  {          var  url  =  readUrl  +  key;          waitdialog.show();          jsonp(url,  function(data)  {                  success(data);                  waitdialog.hide();                          });   }  
  • 47. Backend-­‐Anbindung   var  readUrl  =  'https://secure.openkeyval.org/';   var  jsonp  =  ...;   var  waitdialog  =  ...;     function  read(key,  success)  {          var  url  =  readUrl  +  key;          waitdialog.show();          jsonp(url,  function(data)  {                  success(data);                  waitdialog.hide();                          });   }  
  • 48. Backend-­‐Anbindung   var  readUrl  =  'https://secure.openkeyval.org/';   var  jsonp  =  ...;   var  waitdialog  =  ...;     function  read(key,  success)  {          var  url  =  readUrl  +  key;          waitdialog.show();          jsonp(url,  function(data)  {                  success(data);                  waitdialog.hide();                          });   }  
  • 49. Services  und  DI  mit  Angular   angular.service('jsonp',  jsonpFactory);   angular.service('waitdialog',  waitdialogFactory);     function  todoStoreFactory(jsonp,  waitdialog)  {          function  read(...)  {  ...  }          function  write(...)  {  ...  }          return  {                  read:  read,                  write:  write          }   }     todoStoreFactory.$inject  =  ['jsonp',  'waitdialog'];   angular.service('todostore',  todoStoreFactory);  
  • 50. Services  und  DI  mit  Angular   angular.service('jsonp',  jsonpFactory);   angular.service('waitdialog',  waitdialogFactory);     function  todoStoreFactory(jsonp,  waitdialog)  {          function  read(...)  {  ...  }          function  write(...)  {  ...  }          return  {                  read:  read,                  write:  write          }   }     todoStoreFactory.$inject  =  ['jsonp',  'waitdialog'];   angular.service('todostore',  todoStoreFactory);  
  • 51. Services  und  DI  mit  Angular   angular.service('jsonp',  jsonpFactory);   angular.service('waitdialog',  waitdialogFactory);     function  todoStoreFactory(jsonp,  waitdialog)  {          function  read(...)  {  ...  }          function  write(...)  {  ...  }          return  {                  read:  read,                  write:  write          }   }     todoStoreFactory.$inject  =  ['jsonp',  'waitdialog'];   angular.service('todostore',  todoStoreFactory);  
  • 52. Services  und  DI  mit  Angular   angular.service('jsonp',  jsonpFactory);   angular.service('waitdialog',  waitdialogFactory);     function  todoStoreFactory(jsonp,  waitdialog)  {          function  read(...)  {  ...  }          function  write(...)  {  ...  }          return  {                  read:  read,                  write:  write          }   }     todoStoreFactory.$inject  =  ['jsonp',  'waitdialog'];   angular.service('todostore',  todoStoreFactory);  
  • 53. Di  für  Controller   function  TodoController(todoStore)  {      ...   }     TodoController.$inject  =  ['todoStore'];  
  • 54. Di  für  Controller   function  TodoController(todoStore)  {      ...   }     TodoController.$inject  =  ['todoStore'];  
  • 55. Di  für  Controller   function  TodoController(todoStore)  {      ...   }     TodoController.$inject  =  ['todoStore'];  
  • 56. One  more  thing...     IntegraQon  von  AngularJS   und  jQuery  Mobile  
  • 57. jquery-­‐mobile-­‐angular-­‐adapter   KoordinaQon  von  jQuery  Mobile  und  Angular  JS     Erweiterungen  für  mobile  Web-­‐Apps     Open  Source  unter     heps://github.com/Qgbro/   jquery-­‐mobile-­‐angular-­‐adapter  
  • 58. Paging  in  Listen   <div  ng:repeat=                          "todo  in  todos.$paged()">    ...   </div>     <div  ng:if=            "todos.$paged().hasMorePages()">        <a  href="#"  ngm:click=            "todos.$paged().loadNextPage()">                        Load  more        </a>   </div>  
  • 59. Paging  in  Listen   <div  ng:repeat=                          "todo  in  todos.$paged()">    ...   </div>     <div  ng:if=            "todos.$paged().hasMorePages()">        <a  href="#"  ngm:click=            "todos.$paged().loadNextPage()">                        Load  more        </a>   </div>  
  • 60. Paging  in  Listen   <div  ng:repeat=                          "todo  in  todos.$paged()">    ...   </div>     <div  ng:if=            "todos.$paged().hasMorePages()">        <a  href="#"  ngm:click=            "todos.$paged().loadNextPage()">                        Load  more        </a>   </div>  
  • 61. Mobile  Events   <div  id="main"  data-­‐role="page"                ng:event="swipeleft:showSettings()">          ...   </div>       <div  id="settings"  data-­‐role="page"              ng:event="swiperight:back()">          ...   </div>    
  • 62. NavigaQon  über  Pages   function  TodoController(todoStore,  activePage)  {  ...  }     TodoController.prototype  =  {          onActivate:  function(prevscope)  {                  if  (prevscope  &&  prevscope.storageKey)  {                          this.storageKey  =  prevscope.storageKey;                          this.refreshTodos();                  }          },          showSettings:  function()  {                  this.activePage("#settings");          }   };  
  • 63. NavigaQon  über  Pages   function  TodoController(todoStore,  activePage)  {  ...  }     TodoController.prototype  =  {          onActivate:  function(prevscope)  {                  if  (prevscope  &&  prevscope.storageKey)  {                          this.storageKey  =  prevscope.storageKey;                          this.refreshTodos();                  }          },          showSettings:  function()  {                  this.activePage("#settings");          }   };  
  • 64. NavigaQon  über  Pages   function  TodoController(todoStore,  activePage)  {  ...  }     TodoController.prototype  =  {          onActivate:  function(prevscope)  {                  if  (prevscope  &&  prevscope.storageKey)  {                          this.storageKey  =  prevscope.storageKey;                          this.refreshTodos();                  }          },          showSettings:  function()  {                  this.activePage("#settings");          }   };  
  • 65. Wait-­‐Dialog  Service   waitDialog.show('loading');     waitDialog.hide();   waitDialog.show('click  to  abort',      onClickCallback);  
  • 66. Fazit   Auch  bei  der  Entwicklung     von  JavaScript  Clients   sollten  geeignete  Entwurfsmuster   angewendet  werden!    
  • 67. Fazit   Bibliotheken  und  Frameworks   helfen  bei  der  Umsetzung!    
  • 68. Fazit   Eine  praxiserprobte  KombinaQon:     jQuery  Mobile   +  AngularJS   +  Adapter    
  • 69. In  the  hive  11:  nectar  and  pollen   by  Max  xx,  hep://www.flickr.com/photos/max_westby/4567762490     Books   By  Rodrigo  Galindez,  hep://www.flickr.com/photos/rodrigogalindez/4637637337/    
  • 70. Vielen  Dank   für  Ihr  Interesse!     @Qgbro   @beezlebug