SlideShare una empresa de Scribd logo
1 de 68
Brew up a Rich
Web Application
with Cappuccino
Howard M. Lewis Ship
TWD Consulting
hlship@comcast.net
                       1   © 2009 Howard Lewis Ship
Three 'C's,
 Two 'P's,
  One 'N'
     2   © 2009 Howard Lewis Ship
Agenda
• Why Cappuccino?
• Getting Started
• Objective-J
• Running as a Web App
• Window Resizing &
  Remote Communication
• Cappuccino Pitfalls




                         3   © 2009 Howard Lewis Ship
Why Cappuccino?

          4       © 2009 Howard Lewis Ship
5   © 2009 Howard Lewis Ship
6   © 2009 Howard Lewis Ship
❝If you need web applications that offer
the same user experience as a desktop
app would, then Cappuccino is for you. If
you truly believe that the classic web
development "components" - the usual
HTML/CSS/Javascript horror shop -
simply stinks, then you are going to be
delighted about Cappuccino, too.❞


Holger Jahn
                    7               © 2009 Howard Lewis Ship
Getting Started

            8     © 2009 Howard Lewis Ship
Download
   http://cappuccino.org/download/




                                     Click Here




                    9                  © 2009 Howard Lewis Ship
Install Tools
                     sudo ./install-tools




                10                    © 2009 Howard Lewis Ship
Tools Install
• Pre-Requisites

  • Mac or Linux Helps!

  • Cygwin for Windows

  • Ruby & Rake

•cd Tools ; sudo ./install-tools

• Tools & Frameworks installed to   /usr/local/share


• Must add /usr/local/share/bin to $PATH

                              11                       © 2009 Howard Lewis Ship
Create Example
                capp gen example




           12                  © 2009 Howard Lewis Ship
Generated Files

Info.plist         Application startup information

main.j             main() method for application

AppController.j    Application controller (builds initial UI)

index.html         Launches application

index-debug.html   Launches application (debug mode)

Rakefile            Rake build file

Frameworks         Copy of /usr/local/share/objj/lib/Frameworks

Resources          Resources (images, etc.) available to application




                                    13                            © 2009 Howard Lewis Ship
Configuration
/*
 * AppController.j
 * example
 *
 * Created by You on July 14, 2009.
 * Copyright 2009, Your Company All rights
reserved.
 */


• capp config key value              Stored in ~/.cappconfig
  • user.name
  • user.email
  • organization.name
  • organization.email
  • organization.url
  • organization.identifier

                                        14                    © 2009 Howard Lewis Ship
View Example App




           15      © 2009 Howard Lewis Ship
Objective-J

              16   © 2009 Howard Lewis Ship
Lineage




          17   © 2009 Howard Lewis Ship
Objective-C




          +                =

       Preprocessor




                      18       © 2009 Howard Lewis Ship
Objective-J Syntax
        Java Syntax                                             Objective-J Syntax

        window.orderFront();                                   [window orderFront];

        icon.moveToXY(100, 200);                               [icon moveToX:100 Y:200];




                                                                 method moveToX:Y:

        Java Syntax                                             Objective-J Syntax

        new JFrame();                                          [[CPWindow alloc] init];

        new JFrame("Toolbox");                                 [[CPWindow alloc] initWithTitle:"Toolbox"];




                                                          Class name
                                                                              Class method

        Java Syntax                                            Objective-J Syntax

        this.setNeedsDisplay(true);                            [self setNeedsDisplay:YES];




Cheat Sheet: this ➠ self, true ➠ YES, false ➠ NO, null ➠ nil        19                              © 2009 Howard Lewis Ship
Defining Classes
                                                Base class
      PageView.j

     @import <AppKit/CPView.j>

     @implementation PageView : CPView
     {
       CALayer _rootLayer;
     }

     // Methods defined here

     @end


                   Convention: instance variables
                   start with underscore




                                      20                     © 2009 Howard Lewis Ship
Defining Methods
- for instance method                 type of parameter
+ for class method
                     PageView.j

                 - (id)initWithFrame:(CGRect)aFrame
                 {
                   self = [super initWithFrame:aFrame];

                     if (self)
  Return type        {
                       _rootLayer = [CALayer layer];
                       [self setWantsLayer:YES];
                       [self setLayer:_rootLayer];
                       [_rootLayer setBackgroundColor:[CPColor whiteColor]];
                       [_rootLayer setNeedsDisplay];
                     }

                     return self;
                 }




                                              21                               © 2009 Howard Lewis Ship
No
Namespaces
    22   © 2009 Howard Lewis Ship
Cappuccino User Interfaces




                                                                          M
                                                                             ac
                                                                                  O
                                                                                      nl
                                                                                         y
                     UI Object properties and connections




                          +                             =
  Controller Class             Interface Builder File        Running User Interface



                                   [CPBundle loadCibNamed:owner:loadDelegate:]
                                   Instantiates & connects




                                           23                             © 2009 Howard Lewis Ship
Actions and Outlets

                                              triggerClicked:




               AppController




@implementation AppController : CPObject
{
    CPWindow    theWindow;
    CPTextField outputField;
}

…

- (void)triggerClicked:(id)sender
{
    [outputField setObjectValue:"You clicked it!"];
}

@end




                                                      24        © 2009 Howard Lewis Ship
capp gen BasicControls -t NibApplication




              25                 © 2009 Howard Lewis Ship
26   © 2009 Howard Lewis Ship
Be 1
                         N

                          ta 5
                           ov
http://280atlas.com/




                 27    © 2009 Howard Lewis Ship
Running as a Web App
Using Maven & Jetty




                      28   © 2009 Howard Lewis Ship
29   © 2009 Howard Lewis Ship
Creating a Web App
• mvn archetype:generate
  • #18 (basic web application)
• Edit pom.xml:
     <plugins>
       <plugin>
         <groupId>org.mortbay.jetty</groupId>
         <artifactId>jetty-maven-plugin</artifactId>
         <configuration>
           <requestLog implementation="org.eclipse.jetty.server.NCSARequestLog">
             <append>true</append>
           </requestLog>
         </configuration>
       </plugin>
     </plugins>


• capp gen src/main/webapp/app
• mvn jetty:run
• Open http://localhost:8080/app

                                       30                                © 2009 Howard Lewis Ship
Creating a simple calculator




                31             © 2009 Howard Lewis Ship
Cappuccino Classes
                                    CPObject




                               CPResponder
                      undoManager : CPUndoManager
                              menu : CPMenu
                        nextResponder : CPResponder




                CPView                                CPWindow
             hidden : BOOL                         fullBridge : BOOL
                                                    frame : CGRect
       - addSubview:CPView : void
                                                         level : int
             - display : void
                                                     visible : BOOL
                                                 contentView : CPView
                                               backgroundColor : CPColor
                                                  hasShadow : BOOL
                                                     title : CPString
               CPControl



                                                       CPPanel


                                       32                                  © 2009 Howard Lewis Ship
Cappuccino Classes
                                              CPControl
                                              action : SEL
                                               target: id
                                           enabled : BOOL
                                          highlighted : BOOL
                                            objectValue : id
                                            floatValue: float
                                         doubleValue : double
                                             intValue : int
                                  - initWithFrame:CGFrame : CPControl




                  CPButton                                              CPTextField

               title : CPString                                      editable : BOOL
                                                                      secure: BOOL
             - sizeToFit : void                                      bezeled : BOOL
    + buttonWithTitle:CPString : CPButton
                                                          + labelWithTitle:CPString : CPTextField




                                                    33                                              © 2009 Howard Lewis Ship
Adding Controls




 AppController.j

 - (void)applicationDidFinishLaunching:(CPNotification)aNotification
 {
   var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero()
                    styleMask:CPBorderlessBridgeWindowMask],
       contentView = [theWindow contentView];

     _display = [CPTextField labelWithTitle:"(placeholder)"];
     [_display setBezeled:YES];
     [_display sizeToFit];

     [contentView addSubview:_display];

     [theWindow orderFront:self];
 }



                                          34                                © 2009 Howard Lewis Ship
Utility Methods

     AppController.j

     - (void)add:(CPView)subview
     {
       [_contentView addSubview:subview];
     }

     - (CPButton)makeButton:value at:(CGRect)frame
     {
       var button = [[CPButton alloc] initWithFrame:frame];

         [button setTitle:value.toString()];

         [self add:button];

         return button;
     }




                                  35                          © 2009 Howard Lewis Ship
More Controls
          AppController.j

             _display = [CPTextField labelWithTitle:"(placeholder)"];
             [_display setFrame:CGRectMake(5, 5, 180, 30)]
             [_display setBezeled:YES];

             [self add:_display];

             [self      makeButton:7 at:CGRectMake(5, 35, 40, 25)];
             [self      makeButton:8 at:CGRectMake(50, 35, 40, 25)];
             [self      makeButton:9 at:CGRectMake(95, 35, 40, 25)];
             [self      makeButton:"*" at:CGRectMake(140, 35, 40, 25)];

             [self      makeButton:4 at:CGRectMake(5, 65, 40, 25)];
             [self      makeButton:5 at:CGRectMake(50, 65, 40, 25)];
             [self      makeButton:6 at:CGRectMake(95, 65, 40, 25)];
             [self      makeButton:"-" at:CGRectMake(140, 65, 40, 25)];

             [self      makeButton:1 at:CGRectMake(5, 95, 40, 25)];
             [self      makeButton:2 at:CGRectMake(50, 95, 40, 25)];
             [self      makeButton:3 at:CGRectMake(95, 95, 40, 25)];
             [self      makeButton:"+" at:CGRectMake(140, 95, 40, 25)];

             [self makeButton:0 at:CGRectMake(5, 125, 85, 25)];
             [self makeButton:"." at:CGRectMake(95, 125, 40, 25)];
             [self makeButton:"=" at:CGRectMake(140, 125, 40, 25)];




                             36                                 © 2009 Howard Lewis Ship
Local vars have no type




                      - (CPButton)makeDigit:(int)value at:(CGRect)frame
                      {
      Should be var     CPButton button = [self makeButton:value at:frame
                                           action:@selector(digit:)];

                          [button setTag:value];

                          return button;
                      }




                              37                               © 2009 Howard Lewis Ship
Local vars have no type




                       - (CPButton)makeDigit:(int)value at:(CGRect)frame
                       {
       Should be var     CPButton button = [self makeButton:value at:frame
                                            action:@selector(digit:)];

                           [button setTag:value];

                           return button;
                       }




      Not helpful!
                               38                               © 2009 Howard Lewis Ship
Client Exception — Safari




                39          © 2009 Howard Lewis Ship
Client Exception — Safari




                40          © 2009 Howard Lewis Ship
Fleshed-Out Calculator
       AppController.j

          _display = [CPTextField labelWithTitle:""];
          [_display setAlignment:CPRightTextAlignment];
          [_display setFrame:CGRectMake(1, 5, 183, 30)]
          [_display setBezeled:YES];

          [self add:_display];

          [self makeButton:"C" atX:0 y:0 action:@selector(clear:)];

          [self      makeButton:"/"    atX:3   y:0   action:@selector(div:)];
          [self      makeButton:"*"    atX:3   y:1   action:@selector(mult:)];
          [self      makeButton:"-"    atX:3   y:2   action:@selector(minus:)];
          [self      makeButton:"+"    atX:3   y:3   action:@selector(plus:)];

          [self makeDigit:7 atX:0 y:1];
          [self makeDigit:8 atX:1 y:1];
          [self makeDigit:9 atX:2 y:1];

          …

          [[self makeButton:"=" atX:3 y:4 action:@selector(compute:)]
           setDefaultButton:YES];




                                  41                                       © 2009 Howard Lewis Ship
Utility Methods
AppController.j

- (CPButton)makeButton:(id)value atX:(int)x y:(int)y action:(SEL)action
{
  var frame = CGRectMake(45 * x + 5, 30 * y + 35, 40, 24);
  var button = [[CPButton alloc] initWithFrame:frame];

    [button setTitle:value.toString()];

    [button setTarget:self];
    [button setAction:action];

    [self add:button];

    return button;
}

- (CPButton)makeDigit:(id)value atX:(int)x y:(int)y
{
  return [self makeButton:value atX:x y:y action:@selector(digit:)];
}




                                          42                              © 2009 Howard Lewis Ship
Action Methods
                           @selector(digit:)

AppController.j

- (void)digit:(CPButton)source
{
  var digit = [source title];

    if (_value == "" && digit == "0") return;

    _value = _sign + _value + digit;
    _sign = "";

    [_display setStringValue:_value];
}

- (void)clear:(id)source
{
  [self reset];
}




                                          43    © 2009 Howard Lewis Ship
Nesting Controllers

            44        © 2009 Howard Lewis Ship
HUD Panel




            45   © 2009 Howard Lewis Ship
Main UI


                                                              Top level window
AppController.j

- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
  var window = [[CPWindow alloc] initWithContentRect:CGRectMakeZero()
                                 styleMask:CPBorderlessBridgeWindowMask],
      contentView = [window contentView];

    var button = [CPButton buttonWithTitle:@"Calculator"];

    [button setFrameOrigin:CGPointMake(60, 40)];

    [contentView addSubview:button];

    [button setTarget:self];
    [button setAction:@selector(raiseCalculatorPanel:)];

    [window orderFront:self];
}




                                          46                                © 2009 Howard Lewis Ship
Creating CalcController

     AppController.j

     …
     @import "CalcController.j"

     @implementation AppController : CPObject
     {
       CalcController _calcController;
     }

     …

     - (void)raiseCalculatorPanel:(id)sender
     {
       if (_calcController == nil)
         _calcController = [[CalcController alloc] init];

         [_calcController show];
     }

     @end




                                   47                       © 2009 Howard Lewis Ship
CalcController UI
CalcController.j

- (id)init
{
  self = [super init];

    _panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 184, 184)
                 styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask];

    _contentView = [_panel contentView];

    [_panel setTitle:"Calculator"];

    _display = [CPTextField labelWithTitle:""];
    [_display setAlignment:CPRightTextAlignment];
    [_display setFrame:CGRectMake(1, 5, 183, 30)]
    [_display setBezeled:YES];

    [self add:_display];

    [self makeButton:"C" atX:0 y:0 action:@selector(clear:)];

     …

    return self;
}




                                             48                                  © 2009 Howard Lewis Ship
Window Resizing &
Remote Communication
          49      © 2009 Howard Lewis Ship
50   © 2009 Howard Lewis Ship
Twitter Panel UI
TwitterController.j

_panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 245, 184)
   styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask | CPResizableWindowMask];

[_panel setTitle:@"Twitter"];

var label = [CPTextField labelWithTitle:"User:"];
[label setFrame:CGRectMake(3, 7, 50, 24)];
[label setTextColor:[CPColor whiteColor]];

_field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200];

[_field setFrame:CGRectMake(40, 0, 200, 28)];
[_field setTarget:self];
[_field setAction:@selector(startSearch:)];

var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)];

[scrollView setAutohidesScrollers:YES];

var content = [_panel contentView];

[content addSubview:label];
[content addSubview:_field];
[content addSubview:scrollView];




                                            51                                © 2009 Howard Lewis Ship
52   © 2009 Howard Lewis Ship
Autoresize Flags
 Containing CPView

                                        CPViewMinYMargin




                          CPView




                                            HeightSizable
       CPViewMinXMargin                                     CPViewMaxXMargin




                                              CPView
                          CPViewWidthSizable




                                        CPViewMaxYMargin




                                   53                                          © 2009 Howard Lewis Ship
Autoresizing
TwitterController.j

[_panel setTitle:@"Twitter"];
[_panel setMinSize:CGSizeMake(245, 184)];

var label = [CPTextField labelWithTitle:"User:"];
[label setFrame:CGRectMake(3, 7, 50, 24)];
[label setTextColor:[CPColor whiteColor]];

_field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200];

[_field        setFrame:CGRectMake(40, 0, 200, 28)];
[_field        setTarget:self];
[_field        setAction:@selector(startSearch:)];
[_field        setAutoresizingMask:CPViewWidthSizable];

var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)];

[scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];

[scrollView setAutohidesScrollers:YES];
[scrollView setBackgroundColor:[CPColor whiteColor]];




                                                       Temporary

                                                  54                         © 2009 Howard Lewis Ship
55   © 2009 Howard Lewis Ship
CPCollectionView

 TwitterController.j

    var itemPrototype = [[CPCollectionViewItem alloc] init];
    [itemPrototype setView:[[TwitView alloc] init]];

    _timelineView = [[CPCollectionView alloc]
      initWithFrame:CGRectMake(0, 0, CGRectGetWidth(scrollViewBounds) - 2, 0)];
    [_timelineView setItemPrototype:itemPrototype];
    [_timelineView setDelegate:self];
    [_timelineView setMaxNumberOfColumns:1];

    [_timelineView setAutoresizingMask:CPViewWidthSizable];

    [_scrollView setDocumentView:_timelineView];




                                       56                                 © 2009 Howard Lewis Ship
JSON ➠ Image & Label
{
    "title" : "Mmm - biscuits and gravy, in my hometown, with the woman I love.",
    …
    "user" : {
      "profile_image_url" :
          "http://a3.twimg.com/profile_images/71386417/scott_davis_2009_normal.jpg",
      …
    }
}


                    TwitView.j

                    - (void)setRepresentedObject:(JSONObject)obj
                    {
                      if (!_label)
                      {
                        …
                      }

                       [_imageView setImage:[[CPImage alloc]
                         initByReferencingFile:obj.user.profile_image_url
                         size:CPSizeMake(55, 55)]];
                       [_label setStringValue:obj.text];
                    }
                    @end




                                               57                                © 2009 Howard Lewis Ship
Sending the Search Request

                                       Cached file (to avoid authentication)
TwitterController.j

- (void)startSearch:(id)sender
{
  var url = "twitter/statuses/friends_timeline/" + [_field stringValue] + ".json";

    var request = [CPURLRequest requestWithURL:url];
    [CPURLConnection connectionWithRequest:request delegate:self];
}


                                                Who to notify when data arrives




                                           58                                 © 2009 Howard Lewis Ship
Handling the Response


TwitterController.j

- (void)connection:(CPURLConnection)connection didReceiveData:(CPString)data
{
  var timeline = JSON.parse(data);

    [_timelineView setContent:timeline];
}

- (void)connection:(CPURLConnection)connection didFailWithError:(CPString)error
{
  CPLog.error(error);
}


                           TwitView.j

                           - (void)setRepresentedObject:(JSONObject)obj
                           {
                             ...
                           }
                           @end


                                             59                                © 2009 Howard Lewis Ship
Cappuccino
Pitfalls
    60       © 2009 Howard Lewis Ship
Documentation




           61   © 2009 Howard Lewis Ship
Mac-Centric




              62   © 2009 Howard Lewis Ship
Compilation
Exceptions

              63   © 2009 Howard Lewis Ship
Client-Side Efficiency




             64         © 2009 Howard Lewis Ship
Wrap Up

          65   © 2009 Howard Lewis Ship
http://github.com/hlship/nfjs-cappuccino


                    66              © 2009 Howard Lewis Ship
http://cappuccino.org

          67       © 2009 Howard Lewis Ship
Image Credits
  © 2008 nalungaard
  http://www.flickr.com/photos/nalundgaard/2587677285/
                                                      © 2005 Michael Sarver
                       http://www.flickr.com/photos/michaelsarver/44302391/
  © 2007 Till Krech
  http://www.flickr.com/photos/extranoise/487179535/
                                                        © 2009 Phill Davison
                         http://www.flickr.com/photos/phill_dvsn/3771462059/
  © 2007 Howard Gees
  http://www.flickr.com/photos/cyberslayer/952153409/
                                                      © 2006 Tyler Hawkins
                              http://www.flickr.com/photos/m4m/279364376/
  © 2009 Harald
  http://www.flickr.com/photos/haarald/3227728698/
                                                  © 2006 Brittney Bush Bollay
                              http://www.flickr.com/photos/tzofia/247056173/




                                      68                                        © 2009 Howard Lewis Ship

Más contenido relacionado

La actualidad más candente

CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...Chris Richardson
 
Multi level hierarchy
Multi level hierarchyMulti level hierarchy
Multi level hierarchymyrajendra
 
Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19CodelyTV
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmersAlexander Varwijk
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
 
Groovy, Transforming Language
Groovy, Transforming LanguageGroovy, Transforming Language
Groovy, Transforming LanguageUehara Junji
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java DevelopersYakov Fain
 
Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)Stephen Chin
 
Google Developer Fest 2010
Google Developer Fest 2010Google Developer Fest 2010
Google Developer Fest 2010Chris Ramsdale
 
XML-Free Programming
XML-Free ProgrammingXML-Free Programming
XML-Free ProgrammingStephen Chin
 
Zend Framework Foundations
Zend Framework FoundationsZend Framework Foundations
Zend Framework FoundationsChuck Reeves
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Ryan Weaver
 
Google io bootcamp_2010
Google io bootcamp_2010Google io bootcamp_2010
Google io bootcamp_2010Chris Ramsdale
 

La actualidad más candente (18)

CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
 
Multi level hierarchy
Multi level hierarchyMulti level hierarchy
Multi level hierarchy
 
WCLA12 JavaScript
WCLA12 JavaScriptWCLA12 JavaScript
WCLA12 JavaScript
 
Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19Back to the basics: Modelando nuestro dominio #scbcn19
Back to the basics: Modelando nuestro dominio #scbcn19
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014AngularJS - TechTalk 3/2/2014
AngularJS - TechTalk 3/2/2014
 
CDI in JEE6
CDI in JEE6CDI in JEE6
CDI in JEE6
 
Groovy, Transforming Language
Groovy, Transforming LanguageGroovy, Transforming Language
Groovy, Transforming Language
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
 
Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)Visage Android Hands-on Lab (OSCON)
Visage Android Hands-on Lab (OSCON)
 
Google Developer Fest 2010
Google Developer Fest 2010Google Developer Fest 2010
Google Developer Fest 2010
 
XML-Free Programming
XML-Free ProgrammingXML-Free Programming
XML-Free Programming
 
Zend Framework Foundations
Zend Framework FoundationsZend Framework Foundations
Zend Framework Foundations
 
intellimeet
intellimeetintellimeet
intellimeet
 
Angular beans
Angular beansAngular beans
Angular beans
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
 
Google io bootcamp_2010
Google io bootcamp_2010Google io bootcamp_2010
Google io bootcamp_2010
 

Destacado

Animation Restaurant2
Animation Restaurant2Animation Restaurant2
Animation Restaurant2tunk
 
Smart phone development
Smart phone developmentSmart phone development
Smart phone developmentMyles Eftos
 
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeansJava Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeansIMC Institute
 
การจัดกิจกรรมการเรียนรู้ใน Web Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodoการจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web Application : EdmodoNunta Petman
 
Hybrid vs Native vs Web Apps
Hybrid vs Native vs Web AppsHybrid vs Native vs Web Apps
Hybrid vs Native vs Web AppsPoluru S
 
สร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆสร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆUtain Wongpreaw
 
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04Jenchoke Tachagomain
 
Dream mx
Dream mxDream mx
Dream mxphochai
 
Web Based Application Development with Open Source
Web Based Application Development with Open SourceWeb Based Application Development with Open Source
Web Based Application Development with Open SourceRachabodin Suwannakanthi
 

Destacado (13)

Animation Restaurant2
Animation Restaurant2Animation Restaurant2
Animation Restaurant2
 
Web app
Web appWeb app
Web app
 
Smart phone development
Smart phone developmentSmart phone development
Smart phone development
 
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeansJava Web Programming [Servlet/JSP] Using GlassFish and NetBeans
Java Web Programming [Servlet/JSP] Using GlassFish and NetBeans
 
การจัดกิจกรรมการเรียนรู้ใน Web Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodoการจัดกิจกรรมการเรียนรู้ใน Web  Application : Edmodo
การจัดกิจกรรมการเรียนรู้ใน Web Application : Edmodo
 
lesson1 JSP
lesson1 JSPlesson1 JSP
lesson1 JSP
 
Hybrid vs Native vs Web Apps
Hybrid vs Native vs Web AppsHybrid vs Native vs Web Apps
Hybrid vs Native vs Web Apps
 
Java Web programming Using NetBeans
Java Web programming Using NetBeansJava Web programming Using NetBeans
Java Web programming Using NetBeans
 
สร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆสร้าง Soap web services ง่ายๆ
สร้าง Soap web services ง่ายๆ
 
lesson4 JSP
lesson4 JSPlesson4 JSP
lesson4 JSP
 
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
การพัฒนาเอกสารออนไลน์ขั้นสูง Lect 04
 
Dream mx
Dream mxDream mx
Dream mx
 
Web Based Application Development with Open Source
Web Based Application Development with Open SourceWeb Based Application Development with Open Source
Web Based Application Development with Open Source
 

Similar a Brew up a Rich Web Application with Cappuccino

Build your operator with the right tool
Build your operator with the right toolBuild your operator with the right tool
Build your operator with the right toolRafał Leszko
 
Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!Rafał Leszko
 
The WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsThe WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsHaim Michael
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containersinside-BigData.com
 
Making a small QA system with Docker
Making a small QA system with DockerMaking a small QA system with Docker
Making a small QA system with DockerNaoki AINOYA
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundryrajdeep
 
Hybrid App using WordPress
Hybrid App using WordPressHybrid App using WordPress
Hybrid App using WordPressHaim Michael
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure ProgrammingHoward Lewis Ship
 
Cloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex HenevaldCloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex Henevaldbuildacloud
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesPavol Pitoňák
 
When Smalltalk Meets the Web
When Smalltalk Meets the WebWhen Smalltalk Meets the Web
When Smalltalk Meets the WebESUG
 
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache CordovaHazem Saleh
 
Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Chris Ramsdale
 
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationEWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationRob Tweed
 
Docker presentasjon java bin
Docker presentasjon java binDocker presentasjon java bin
Docker presentasjon java binOlve Hansen
 
Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up	Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up droidcon Dubai
 

Similar a Brew up a Rich Web Application with Cappuccino (20)

Build your operator with the right tool
Build your operator with the right toolBuild your operator with the right tool
Build your operator with the right tool
 
Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!
 
The WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsThe WebView Role in Hybrid Applications
The WebView Role in Hybrid Applications
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containers
 
Making a small QA system with Docker
Making a small QA system with DockerMaking a small QA system with Docker
Making a small QA system with Docker
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundry
 
Hybrid App using WordPress
Hybrid App using WordPressHybrid App using WordPress
Hybrid App using WordPress
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure Programming
 
Pyramid deployment
Pyramid deploymentPyramid deployment
Pyramid deployment
 
Cloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex HenevaldCloud Application Blueprints with Apache Brooklyn by Alex Henevald
Cloud Application Blueprints with Apache Brooklyn by Alex Henevald
 
Deep Dive - CI/CD on AWS
Deep Dive - CI/CD on AWSDeep Dive - CI/CD on AWS
Deep Dive - CI/CD on AWS
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile Devices
 
When Smalltalk Meets the Web
When Smalltalk Meets the WebWhen Smalltalk Meets the Web
When Smalltalk Meets the Web
 
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
 
Cicd.pdf
Cicd.pdfCicd.pdf
Cicd.pdf
 
Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010
 
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD ApplicationEWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
EWD 3 Training Course Part 5a: First Steps in Building a QEWD Application
 
Docker presentasjon java bin
Docker presentasjon java binDocker presentasjon java bin
Docker presentasjon java bin
 
Node.js Workshop
Node.js WorkshopNode.js Workshop
Node.js Workshop
 
Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up	Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up
 

Más de Howard Lewis Ship

Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEBHoward Lewis Ship
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestHoward Lewis Ship
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserHoward Lewis Ship
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapModern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapHoward Lewis Ship
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHoward Lewis Ship
 
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Howard Lewis Ship
 
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveArduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveHoward Lewis Ship
 
Clojure: Towards The Essence of Programming
Clojure: Towards The Essence of ProgrammingClojure: Towards The Essence of Programming
Clojure: Towards The Essence of ProgrammingHoward Lewis Ship
 
Tapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseTapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseHoward Lewis Ship
 
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Howard Lewis Ship
 
Tapestry: State of the Union
Tapestry: State of the UnionTapestry: State of the Union
Tapestry: State of the UnionHoward Lewis Ship
 
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Howard Lewis Ship
 

Más de Howard Lewis Ship (16)

Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEB
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To Test
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapModern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter Bootstrap
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
 
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
 
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveArduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
 
Clojure: Towards The Essence of Programming
Clojure: Towards The Essence of ProgrammingClojure: Towards The Essence of Programming
Clojure: Towards The Essence of Programming
 
Codemash-Clojure.pdf
Codemash-Clojure.pdfCodemash-Clojure.pdf
Codemash-Clojure.pdf
 
Codemash-Tapestry.pdf
Codemash-Tapestry.pdfCodemash-Tapestry.pdf
Codemash-Tapestry.pdf
 
Tapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseTapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting Ease
 
Clojure Deep Dive
Clojure Deep DiveClojure Deep Dive
Clojure Deep Dive
 
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)
 
Cascade
CascadeCascade
Cascade
 
Tapestry: State of the Union
Tapestry: State of the UnionTapestry: State of the Union
Tapestry: State of the Union
 
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
 

Último

SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 

Último (20)

SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 

Brew up a Rich Web Application with Cappuccino

  • 1. Brew up a Rich Web Application with Cappuccino Howard M. Lewis Ship TWD Consulting hlship@comcast.net 1 © 2009 Howard Lewis Ship
  • 2. Three 'C's, Two 'P's, One 'N' 2 © 2009 Howard Lewis Ship
  • 3. Agenda • Why Cappuccino? • Getting Started • Objective-J • Running as a Web App • Window Resizing & Remote Communication • Cappuccino Pitfalls 3 © 2009 Howard Lewis Ship
  • 4. Why Cappuccino? 4 © 2009 Howard Lewis Ship
  • 5. 5 © 2009 Howard Lewis Ship
  • 6. 6 © 2009 Howard Lewis Ship
  • 7. ❝If you need web applications that offer the same user experience as a desktop app would, then Cappuccino is for you. If you truly believe that the classic web development "components" - the usual HTML/CSS/Javascript horror shop - simply stinks, then you are going to be delighted about Cappuccino, too.❞ Holger Jahn 7 © 2009 Howard Lewis Ship
  • 8. Getting Started 8 © 2009 Howard Lewis Ship
  • 9. Download http://cappuccino.org/download/ Click Here 9 © 2009 Howard Lewis Ship
  • 10. Install Tools sudo ./install-tools 10 © 2009 Howard Lewis Ship
  • 11. Tools Install • Pre-Requisites • Mac or Linux Helps! • Cygwin for Windows • Ruby & Rake •cd Tools ; sudo ./install-tools • Tools & Frameworks installed to /usr/local/share • Must add /usr/local/share/bin to $PATH 11 © 2009 Howard Lewis Ship
  • 12. Create Example capp gen example 12 © 2009 Howard Lewis Ship
  • 13. Generated Files Info.plist Application startup information main.j main() method for application AppController.j Application controller (builds initial UI) index.html Launches application index-debug.html Launches application (debug mode) Rakefile Rake build file Frameworks Copy of /usr/local/share/objj/lib/Frameworks Resources Resources (images, etc.) available to application 13 © 2009 Howard Lewis Ship
  • 14. Configuration /* * AppController.j * example * * Created by You on July 14, 2009. * Copyright 2009, Your Company All rights reserved. */ • capp config key value Stored in ~/.cappconfig • user.name • user.email • organization.name • organization.email • organization.url • organization.identifier 14 © 2009 Howard Lewis Ship
  • 15. View Example App 15 © 2009 Howard Lewis Ship
  • 16. Objective-J 16 © 2009 Howard Lewis Ship
  • 17. Lineage 17 © 2009 Howard Lewis Ship
  • 18. Objective-C + = Preprocessor 18 © 2009 Howard Lewis Ship
  • 19. Objective-J Syntax Java Syntax Objective-J Syntax window.orderFront(); [window orderFront]; icon.moveToXY(100, 200); [icon moveToX:100 Y:200]; method moveToX:Y: Java Syntax Objective-J Syntax new JFrame(); [[CPWindow alloc] init]; new JFrame("Toolbox"); [[CPWindow alloc] initWithTitle:"Toolbox"]; Class name Class method Java Syntax Objective-J Syntax this.setNeedsDisplay(true); [self setNeedsDisplay:YES]; Cheat Sheet: this ➠ self, true ➠ YES, false ➠ NO, null ➠ nil 19 © 2009 Howard Lewis Ship
  • 20. Defining Classes Base class PageView.j @import <AppKit/CPView.j> @implementation PageView : CPView { CALayer _rootLayer; } // Methods defined here @end Convention: instance variables start with underscore 20 © 2009 Howard Lewis Ship
  • 21. Defining Methods - for instance method type of parameter + for class method PageView.j - (id)initWithFrame:(CGRect)aFrame { self = [super initWithFrame:aFrame]; if (self) Return type { _rootLayer = [CALayer layer]; [self setWantsLayer:YES]; [self setLayer:_rootLayer]; [_rootLayer setBackgroundColor:[CPColor whiteColor]]; [_rootLayer setNeedsDisplay]; } return self; } 21 © 2009 Howard Lewis Ship
  • 22. No Namespaces 22 © 2009 Howard Lewis Ship
  • 23. Cappuccino User Interfaces M ac O nl y UI Object properties and connections + = Controller Class Interface Builder File Running User Interface [CPBundle loadCibNamed:owner:loadDelegate:] Instantiates & connects 23 © 2009 Howard Lewis Ship
  • 24. Actions and Outlets triggerClicked: AppController @implementation AppController : CPObject { CPWindow theWindow; CPTextField outputField; } … - (void)triggerClicked:(id)sender { [outputField setObjectValue:"You clicked it!"]; } @end 24 © 2009 Howard Lewis Ship
  • 25. capp gen BasicControls -t NibApplication 25 © 2009 Howard Lewis Ship
  • 26. 26 © 2009 Howard Lewis Ship
  • 27. Be 1 N ta 5 ov http://280atlas.com/ 27 © 2009 Howard Lewis Ship
  • 28. Running as a Web App Using Maven & Jetty 28 © 2009 Howard Lewis Ship
  • 29. 29 © 2009 Howard Lewis Ship
  • 30. Creating a Web App • mvn archetype:generate • #18 (basic web application) • Edit pom.xml: <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <requestLog implementation="org.eclipse.jetty.server.NCSARequestLog"> <append>true</append> </requestLog> </configuration> </plugin> </plugins> • capp gen src/main/webapp/app • mvn jetty:run • Open http://localhost:8080/app 30 © 2009 Howard Lewis Ship
  • 31. Creating a simple calculator 31 © 2009 Howard Lewis Ship
  • 32. Cappuccino Classes CPObject CPResponder undoManager : CPUndoManager menu : CPMenu nextResponder : CPResponder CPView CPWindow hidden : BOOL fullBridge : BOOL frame : CGRect - addSubview:CPView : void level : int - display : void visible : BOOL contentView : CPView backgroundColor : CPColor hasShadow : BOOL title : CPString CPControl CPPanel 32 © 2009 Howard Lewis Ship
  • 33. Cappuccino Classes CPControl action : SEL target: id enabled : BOOL highlighted : BOOL objectValue : id floatValue: float doubleValue : double intValue : int - initWithFrame:CGFrame : CPControl CPButton CPTextField title : CPString editable : BOOL secure: BOOL - sizeToFit : void bezeled : BOOL + buttonWithTitle:CPString : CPButton + labelWithTitle:CPString : CPTextField 33 © 2009 Howard Lewis Ship
  • 34. Adding Controls AppController.j - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [theWindow contentView]; _display = [CPTextField labelWithTitle:"(placeholder)"]; [_display setBezeled:YES]; [_display sizeToFit]; [contentView addSubview:_display]; [theWindow orderFront:self]; } 34 © 2009 Howard Lewis Ship
  • 35. Utility Methods AppController.j - (void)add:(CPView)subview { [_contentView addSubview:subview]; } - (CPButton)makeButton:value at:(CGRect)frame { var button = [[CPButton alloc] initWithFrame:frame]; [button setTitle:value.toString()]; [self add:button]; return button; } 35 © 2009 Howard Lewis Ship
  • 36. More Controls AppController.j _display = [CPTextField labelWithTitle:"(placeholder)"]; [_display setFrame:CGRectMake(5, 5, 180, 30)] [_display setBezeled:YES]; [self add:_display]; [self makeButton:7 at:CGRectMake(5, 35, 40, 25)]; [self makeButton:8 at:CGRectMake(50, 35, 40, 25)]; [self makeButton:9 at:CGRectMake(95, 35, 40, 25)]; [self makeButton:"*" at:CGRectMake(140, 35, 40, 25)]; [self makeButton:4 at:CGRectMake(5, 65, 40, 25)]; [self makeButton:5 at:CGRectMake(50, 65, 40, 25)]; [self makeButton:6 at:CGRectMake(95, 65, 40, 25)]; [self makeButton:"-" at:CGRectMake(140, 65, 40, 25)]; [self makeButton:1 at:CGRectMake(5, 95, 40, 25)]; [self makeButton:2 at:CGRectMake(50, 95, 40, 25)]; [self makeButton:3 at:CGRectMake(95, 95, 40, 25)]; [self makeButton:"+" at:CGRectMake(140, 95, 40, 25)]; [self makeButton:0 at:CGRectMake(5, 125, 85, 25)]; [self makeButton:"." at:CGRectMake(95, 125, 40, 25)]; [self makeButton:"=" at:CGRectMake(140, 125, 40, 25)]; 36 © 2009 Howard Lewis Ship
  • 37. Local vars have no type - (CPButton)makeDigit:(int)value at:(CGRect)frame { Should be var CPButton button = [self makeButton:value at:frame action:@selector(digit:)]; [button setTag:value]; return button; } 37 © 2009 Howard Lewis Ship
  • 38. Local vars have no type - (CPButton)makeDigit:(int)value at:(CGRect)frame { Should be var CPButton button = [self makeButton:value at:frame action:@selector(digit:)]; [button setTag:value]; return button; } Not helpful! 38 © 2009 Howard Lewis Ship
  • 39. Client Exception — Safari 39 © 2009 Howard Lewis Ship
  • 40. Client Exception — Safari 40 © 2009 Howard Lewis Ship
  • 41. Fleshed-Out Calculator AppController.j _display = [CPTextField labelWithTitle:""]; [_display setAlignment:CPRightTextAlignment]; [_display setFrame:CGRectMake(1, 5, 183, 30)] [_display setBezeled:YES]; [self add:_display]; [self makeButton:"C" atX:0 y:0 action:@selector(clear:)]; [self makeButton:"/" atX:3 y:0 action:@selector(div:)]; [self makeButton:"*" atX:3 y:1 action:@selector(mult:)]; [self makeButton:"-" atX:3 y:2 action:@selector(minus:)]; [self makeButton:"+" atX:3 y:3 action:@selector(plus:)]; [self makeDigit:7 atX:0 y:1]; [self makeDigit:8 atX:1 y:1]; [self makeDigit:9 atX:2 y:1]; … [[self makeButton:"=" atX:3 y:4 action:@selector(compute:)] setDefaultButton:YES]; 41 © 2009 Howard Lewis Ship
  • 42. Utility Methods AppController.j - (CPButton)makeButton:(id)value atX:(int)x y:(int)y action:(SEL)action { var frame = CGRectMake(45 * x + 5, 30 * y + 35, 40, 24); var button = [[CPButton alloc] initWithFrame:frame]; [button setTitle:value.toString()]; [button setTarget:self]; [button setAction:action]; [self add:button]; return button; } - (CPButton)makeDigit:(id)value atX:(int)x y:(int)y { return [self makeButton:value atX:x y:y action:@selector(digit:)]; } 42 © 2009 Howard Lewis Ship
  • 43. Action Methods @selector(digit:) AppController.j - (void)digit:(CPButton)source { var digit = [source title]; if (_value == "" && digit == "0") return; _value = _sign + _value + digit; _sign = ""; [_display setStringValue:_value]; } - (void)clear:(id)source { [self reset]; } 43 © 2009 Howard Lewis Ship
  • 44. Nesting Controllers 44 © 2009 Howard Lewis Ship
  • 45. HUD Panel 45 © 2009 Howard Lewis Ship
  • 46. Main UI Top level window AppController.j - (void)applicationDidFinishLaunching:(CPNotification)aNotification { var window = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], contentView = [window contentView]; var button = [CPButton buttonWithTitle:@"Calculator"]; [button setFrameOrigin:CGPointMake(60, 40)]; [contentView addSubview:button]; [button setTarget:self]; [button setAction:@selector(raiseCalculatorPanel:)]; [window orderFront:self]; } 46 © 2009 Howard Lewis Ship
  • 47. Creating CalcController AppController.j … @import "CalcController.j" @implementation AppController : CPObject { CalcController _calcController; } … - (void)raiseCalculatorPanel:(id)sender { if (_calcController == nil) _calcController = [[CalcController alloc] init]; [_calcController show]; } @end 47 © 2009 Howard Lewis Ship
  • 48. CalcController UI CalcController.j - (id)init { self = [super init]; _panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 184, 184) styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask]; _contentView = [_panel contentView]; [_panel setTitle:"Calculator"]; _display = [CPTextField labelWithTitle:""]; [_display setAlignment:CPRightTextAlignment]; [_display setFrame:CGRectMake(1, 5, 183, 30)] [_display setBezeled:YES]; [self add:_display]; [self makeButton:"C" atX:0 y:0 action:@selector(clear:)]; … return self; } 48 © 2009 Howard Lewis Ship
  • 49. Window Resizing & Remote Communication 49 © 2009 Howard Lewis Ship
  • 50. 50 © 2009 Howard Lewis Ship
  • 51. Twitter Panel UI TwitterController.j _panel = [[CPPanel alloc] initWithContentRect:CGRectMake(20, 30, 245, 184) styleMask:CPHUDBackgroundWindowMask | CPClosableWindowMask | CPResizableWindowMask]; [_panel setTitle:@"Twitter"]; var label = [CPTextField labelWithTitle:"User:"]; [label setFrame:CGRectMake(3, 7, 50, 24)]; [label setTextColor:[CPColor whiteColor]]; _field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200]; [_field setFrame:CGRectMake(40, 0, 200, 28)]; [_field setTarget:self]; [_field setAction:@selector(startSearch:)]; var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)]; [scrollView setAutohidesScrollers:YES]; var content = [_panel contentView]; [content addSubview:label]; [content addSubview:_field]; [content addSubview:scrollView]; 51 © 2009 Howard Lewis Ship
  • 52. 52 © 2009 Howard Lewis Ship
  • 53. Autoresize Flags Containing CPView CPViewMinYMargin CPView HeightSizable CPViewMinXMargin CPViewMaxXMargin CPView CPViewWidthSizable CPViewMaxYMargin 53 © 2009 Howard Lewis Ship
  • 54. Autoresizing TwitterController.j [_panel setTitle:@"Twitter"]; [_panel setMinSize:CGSizeMake(245, 184)]; var label = [CPTextField labelWithTitle:"User:"]; [label setFrame:CGRectMake(3, 7, 50, 24)]; [label setTextColor:[CPColor whiteColor]]; _field = [CPTextField textFieldWithStringValue:"" placeholder:"Twitter User" width:200]; [_field setFrame:CGRectMake(40, 0, 200, 28)]; [_field setTarget:self]; [_field setAction:@selector(startSearch:)]; [_field setAutoresizingMask:CPViewWidthSizable]; var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 32, 245, 160)]; [scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; [scrollView setAutohidesScrollers:YES]; [scrollView setBackgroundColor:[CPColor whiteColor]]; Temporary 54 © 2009 Howard Lewis Ship
  • 55. 55 © 2009 Howard Lewis Ship
  • 56. CPCollectionView TwitterController.j var itemPrototype = [[CPCollectionViewItem alloc] init]; [itemPrototype setView:[[TwitView alloc] init]]; _timelineView = [[CPCollectionView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(scrollViewBounds) - 2, 0)]; [_timelineView setItemPrototype:itemPrototype]; [_timelineView setDelegate:self]; [_timelineView setMaxNumberOfColumns:1]; [_timelineView setAutoresizingMask:CPViewWidthSizable]; [_scrollView setDocumentView:_timelineView]; 56 © 2009 Howard Lewis Ship
  • 57. JSON ➠ Image & Label { "title" : "Mmm - biscuits and gravy, in my hometown, with the woman I love.", … "user" : { "profile_image_url" : "http://a3.twimg.com/profile_images/71386417/scott_davis_2009_normal.jpg", … } } TwitView.j - (void)setRepresentedObject:(JSONObject)obj { if (!_label) { … } [_imageView setImage:[[CPImage alloc] initByReferencingFile:obj.user.profile_image_url size:CPSizeMake(55, 55)]]; [_label setStringValue:obj.text]; } @end 57 © 2009 Howard Lewis Ship
  • 58. Sending the Search Request Cached file (to avoid authentication) TwitterController.j - (void)startSearch:(id)sender { var url = "twitter/statuses/friends_timeline/" + [_field stringValue] + ".json"; var request = [CPURLRequest requestWithURL:url]; [CPURLConnection connectionWithRequest:request delegate:self]; } Who to notify when data arrives 58 © 2009 Howard Lewis Ship
  • 59. Handling the Response TwitterController.j - (void)connection:(CPURLConnection)connection didReceiveData:(CPString)data { var timeline = JSON.parse(data); [_timelineView setContent:timeline]; } - (void)connection:(CPURLConnection)connection didFailWithError:(CPString)error { CPLog.error(error); } TwitView.j - (void)setRepresentedObject:(JSONObject)obj { ... } @end 59 © 2009 Howard Lewis Ship
  • 60. Cappuccino Pitfalls 60 © 2009 Howard Lewis Ship
  • 61. Documentation 61 © 2009 Howard Lewis Ship
  • 62. Mac-Centric 62 © 2009 Howard Lewis Ship
  • 63. Compilation Exceptions 63 © 2009 Howard Lewis Ship
  • 64. Client-Side Efficiency 64 © 2009 Howard Lewis Ship
  • 65. Wrap Up 65 © 2009 Howard Lewis Ship
  • 66. http://github.com/hlship/nfjs-cappuccino 66 © 2009 Howard Lewis Ship
  • 67. http://cappuccino.org 67 © 2009 Howard Lewis Ship
  • 68. Image Credits © 2008 nalungaard http://www.flickr.com/photos/nalundgaard/2587677285/ © 2005 Michael Sarver http://www.flickr.com/photos/michaelsarver/44302391/ © 2007 Till Krech http://www.flickr.com/photos/extranoise/487179535/ © 2009 Phill Davison http://www.flickr.com/photos/phill_dvsn/3771462059/ © 2007 Howard Gees http://www.flickr.com/photos/cyberslayer/952153409/ © 2006 Tyler Hawkins http://www.flickr.com/photos/m4m/279364376/ © 2009 Harald http://www.flickr.com/photos/haarald/3227728698/ © 2006 Brittney Bush Bollay http://www.flickr.com/photos/tzofia/247056173/ 68 © 2009 Howard Lewis Ship