SlideShare a Scribd company logo
1 of 53
Download to read offline
MONTREAL 1/3 JULY 2011




Ajax.framework:
Under the Hood
Chuck Hill
Global Village Consulting, Inc.
WOWODC 2011
Session Overview
•   My Goals

•   Outline:

    •   Ajax vs Classical WebObjects

    •   How Things Work vs Just Works

    •   Building Blocks

    •   Case Study

•   No JSON
A Word on our Sponsors

•   Jean-Francois Veillette

•   Anjo Krank

•   Mike Schrag

•   the rest of us

•   you
A Word on JavaScript
•   Not a toy scripting language

•   NOT Java, “Lisp in C’s clothing”

•   functional programming

•   loose “duck” typing and prototypal inheritance

•   dynamic objects

•   Douglas Crockford and Yahoo
Classical Request/Response Loop
Ajax R-R in a Nutshell
New R-R Loop Phase
•   handleRequest

•   replaces action method

•   returns response for Ajax request

•   called by invokeAction

    •   ... at the right time!

•   takeValues→invokeAction→handleRequest→appendToResponse?’

•   returns AjaxResponse (important!)
Ajax Action R-R Loop
•   “The Basic”

•   takeValues

•   invokeAction

•   handleRequest

•   whatever

•   can return JS, HTML, or nothing

•   client-side result varies
Ajax Update R-R Loop
•   “The Meat Lover’s”

•   ...?_u=MyContainerID&1239887663

•   invokeAction

•   handleRequest

•   AjaxResponse.generateResponse

•   invokeAction (yes! again!)

•   handleRequest (on AUC)

•   appendChildrenToResponse (AUC)
Ajax Submit, Action, & Update
•   “All Dressed”

•   takeValuesFromRequest

•   invokeAction

•   handleRequest

•   AjaxResponse.generateResponse

•   invokeAction (yes! again!)

•   handleRequest (on AUC)

•   action method (result discarded)

•   appendChildrenToResponse (AUC)
Ajax Replace R-R Loop
•   “Poutine Pizza”

•   ...?_r=true&1239887663

•   takeValuesFromRequest

•   invokeAction

•   handleRequest

•   action method (component) returned as replacement)

•   intuitive, but may be dangerous
Special Ajax Classes

•   AjaxRequestHandler: don’t store page

•   ERXAjaxApplication: no takeVlaues for ?_u=xxx&2309482093

•   ERXAjaxSession: Ajax Page Caching

•   ERXAjaxContext: partial form submits

•   AjaxResponse: generateResponse→invokeAction for AUC
Classical Page Caching
Ajax Page Caching
Support Classes

•   AjaxComponent

•   AjaxDynamicElement

•   AjaxUtils

•   AjaxOptions, AjaxOption, AjaxConstantOption, AjaxValue
AjaxComponent

•   WOComponent replacement

•   Stateful

•   Mostly familiar usage

•   handleRequest

•   addRequiredWebResources
AjaxDynamicElement
•   WODynamicGroup replacement

•   Stateless

•   Harder to use than WOComponent

•   Binding and template access

•   handleRequest

•   addRequiredWebResources
AjaxUtils
•   createResponse

•   javascriptResponse

•   Add JS and CSS resources (via ERXResponseRewriter)

•   shouldHandleRequest

•   binding convenience with JSON parsing

•   response generation

•   updateDomElement

•   redirecting

•   etc. seek and ye shall find
JavaScript/JSON Value Encoding


new Ajax.Request('/some_url', {
   method: 'get',
   parameters: {company: 'example', limit: 12}
 });
AjaxValue

•   converts to JavaScript/JSON format

•   type-aware value

•   type guessing ability
•   javascriptValue


•   [a, b, ...], {a:b; ...}, escaping in strings etc.
AjaxOption.Type


•   simple enumeration

•   AjaxValue data types

•   update if you extend AjaxValue
AjaxOption
•   named for Prototype parameter “options”

•   bridge from bindings to JavaScript

•   component or dynamic element

•   Parameters

    •   JavaScript Name

    •   Type

    •   Binding Name

    •   Default Value
AjaxConstantOption

•   Used for computed values
    public AjaxConstantOption(
        String    javaScriptName,
        Object    constantValue,
        Type      type)
AjaxOptions
•   with an S

•   collection of key-value pairs

•   used as component* or class

•   *component usage likely buggy

•   works with StringBuffer and WOResponse

•   works best with
    AjaxOption.createAjaxOptionsDictionary
AjaxOptions Usage

  public NSDictionary createAjaxOptions(WOComponent component) {
	 NSMutableArray<AjaxOption> list = new NSMutableArray<AjaxOption>();
	 list.addObject(new AjaxOption("frequency", AjaxOption.NUMBER));
	 list.addObject(new AjaxOption("onLoading", AjaxOption.SCRIPT));
	 list.addObject(new AjaxOption("evalScripts", Boolean.TRUE, AjaxOption.BOOLEAN));
  ...
	 NSMutableDictionary<String, String> options =
   AjaxOption.createAjaxOptionsDictionary(list, component, associations());
	 return options;
}

response.appendContentString("AUC.registerPeriodic('" +
id + "'," + canStop + "," + stopped + ",");
AjaxOptions.appendToResponse(options, response, context);
response.appendContentString(");");
Part II



•   Being the Second Part
Twenty Steps to WO-Ajax

•   Who loves ya baby?

•   From discovery to commit

•   slowly

•   in 20 steps
Step 1: Review and Plan

•   Find something

•   See if it is worth using

•   Plan how you will use it
Step 2: Check that License


•   Licenses like the GPL are best avoided

•   For Wonder: BSD, MIT or Apache 2 are preferred

•   For your own projects consider the terms
Step 3: Download Source Files

•   Determine JavaScript files needed

•   Often component specific and supporting
Step 4: Download Resources

•   Get example HTML from demo source

•   CSS files

•   Image resources

•   License file

•   Other resources?
Step 5: Start Small
•   AjaxComponent or
    AjaxDynamicElement?

•   Ajax, ERCoolComponents, or
    private?

•   Create class and/or .wo

•   Add JS, CSS, images, etc to
    WebServerResources
Step 6: addRequiredWebResources

protected void addRequiredWebResources(WOResponse response, WOContext context) {

    addScriptResourceInHead(context, response, "Ajax", "controls.js");
    addScriptResourceInHead(context, response, "Ajax", "prototype.js");

    addScriptResourceInHead(context, response,
        "ERCoolComponents", "Rating/livepipe.js");
    addScriptResourceInHead(context, response,
        "ERCoolComponents", "Rating/rating.js");
    addStylesheetResourceInHead(context, response,
        "ERCoolComponents", "Rating/rating.css");

}
Step 7: Static appendToResponse

public void appendToResponse(WOResponse response, WOContext context) {

    super.appendToResponse(response, context);

    response.appendContentString("<div id="rating_one" class="rating_container">");
    response.appendContentString("</div>");

    response.appendContentString("<script type="text/javascript">");
    response.appendContentString("var rating_one = new Control.Rating('rating_one');");
    response.appendContentString("</script>");

}
Step 8: handleRequest

public WOActionResults handleRequest(WORequest request, WOContext context) {

    System.out.println("CCRating " + request.headers());

    return null;
}
Step 9: Initial Testing

•   Smoke Test Time!

•   Is control rendered correctly?

•   Does CSS load?

•   Are images visible?

•   Does it “work” client side?
Step 10: Check Client Side Errors

•   Use FireBug or Safari Web Inspector

•   Look for errors in JavaScript console

•   Look for resources that fail to load
Step 11: Update Paths in CSS
Resource paths in CSS are likely wrong:

background-image:url(/stylesheets/rating.gif);

These are resolved (by Wonder) relative to the CSS
file’s location:

background-image:url(rating.gif);
Step 12a: First Dynamic Steps
public void appendToResponse(WOResponse response, WOContext context) {

 super.appendToResponse(response, context);

 String id = (String) valueForBinding(
     "id",
     ERXWOContext.safeIdentifierName(context, false),
     context.component());

 response.appendContentString("<div ");

 appendTagAttributeToResponse(response, "id", id);
 appendTagAttributeToResponse(response, "class", "rating_container");

 response.appendContentString("></div>");
Step 12b: First Dynamic Steps
appendToResponse continued...



response.appendContentString("<script type="text/javascript">");
response.appendContentString("var ");
response.appendContentString(id);
response.appendContentString(" = new Control.Rating('");
response.appendContentString(id);
response.appendContentString("'); </script>");
}
Step 13a: Rating Options
<script type="text/javascript">

  var e_1_0_0_1_3_7 = new Control.Rating('e_1_0_0_1_3_7',
          {value: 5,
           min:   2,
           max:   8}
       );

</script>
Step 13b: Rating Options
      response.appendContentString("'); </script>");

    response.appendContentString("', ");
    AjaxOptions.appendToResponse(createOptions(context), response, context);
    response.appendContentString("); </script>");
}

protected NSMutableDictionary createOptions(WOContext context) {
    NSMutableArray ajaxOptionsArray = new NSMutableArray();
    ajaxOptionsArray.addObject(new AjaxOption("min", AjaxOption.NUMBER));
    ajaxOptionsArray.addObject(new AjaxOption("max", AjaxOption.NUMBER));
    ajaxOptionsArray.addObject(new AjaxOption("value", AjaxOption.NUMBER));
    return AjaxOption.createAjaxOptionsDictionary(
            ajaxOptionsArray, context.component(), associations());
}
Step 14: Rest of Bindings
  ajaxOptionsArray.addObject(new AjaxOption("capture", AjaxOption.BOOLEAN));
ajaxOptionsArray.addObject(new AjaxOption("classNames", AjaxOption.DICTIONARY));

ajaxOptionsArray.addObject(
    new AjaxOption("input", "inputId", null, AjaxOption.STRING));

ajaxOptionsArray.addObject(new   AjaxOption("multiple", AjaxOption.BOOLEAN));
ajaxOptionsArray.addObject(new   AjaxOption("rated", AjaxOption.BOOLEAN));
ajaxOptionsArray.addObject(new   AjaxOption("reverse", AjaxOption.BOOLEAN));
ajaxOptionsArray.addObject(new   AjaxOption("updateOptions", AjaxOption.DICTIONARY));

ajaxOptionsArray.addObject(
    new AjaxOption("updateParameterName", "formValueName", null, AjaxOption.STRING));
Step 15a: Server Interaction
  ajaxOptionsArray.addObject(
  new AjaxOption("updateParameterName", "formValueName", null, AjaxOption.STRING));

ajaxOptionsArray.addObject(
    new AjaxConstantOption("updateParameterName", "formValueName",
        formValueName(context), AjaxOption.STRING));

ajaxOptionsArray.addObject(new AjaxConstantOption("updateUrl",
    AjaxUtils.ajaxComponentActionUrl(context), AjaxOption.STRING));

protected String formValueName(WOContext context) {
    return (String)valueForBinding(
    "formValueName",
    id(context) + "_value",
    context.component());
Step 15b: Server Interaction
    public WOActionResults handleRequest(WORequest request, WOContext context) {
      System.out.println("CCRating " + request.headers());
      System.out.println("CCRating " + request.uri());
      System.out.println("CCRating " + request.formValues());

     Object ratingValue = request.formValueForKey(formValueName(context));

     if (ratingValue instanceof String) {
         ratingValue = Integer.valueOf((String)ratingValue);
     }

     setValueForBinding(ratingValue, "value", context.component());

     return null;
}
Step 16: WO Integration: action Binding
public WOActionResults handleRequest(WORequest request, WOContext context) {
    Object ratingValue = request.formValueForKey(formValueName(context));
    if (ratingValue instanceof String) {
        ratingValue = Integer.valueOf((String)ratingValue);
    }
    setValueForBinding(ratingValue, "value", context.component());

    // Nothing gets returned to the client from the CCRating action so we
    // discard any result from firing the action binding
    if (hasBinding("action")) {
        valueForBinding("action", context.component());
    }

    return null;
}
Step 17a: WO Integration: Form Input
    protected boolean actAsInput(WOContext context) {
      return booleanValueForBinding("actAsInput", true, context.component());
}

protected NSMutableDictionary createOptions(WOContext context) {
...
    if ( ! actAsInput(context)) {
        ajaxOptionsArray.addObject(new AjaxConstantOption("updateUrl",
            AjaxUtils.ajaxComponentActionUrl(context), AjaxOption.STRING));
    }
    else {
        ajaxOptionsArray.addObject(new AjaxConstantOption("input",
            id(context) + "_input", AjaxOption.STRING));
    }
Step 17b: WO Integration: Form Input
  public void appendToResponse(WOResponse response, WOContext context) {
...
if (actAsInput(context)) {
    response.appendContentString("<input ");

      appendTagAttributeToResponse(response, "type", "hidden");

      appendTagAttributeToResponse(response, "id", id + "_input");
      appendTagAttributeToResponse(response, "name", formValueName(context));

      appendTagAttributeToResponse(response, "value",
          valueForBinding("value", context.component()));

      response.appendContentString("/>");
...
}
Step 17c: WO Integration: Form Input
    public void takeValuesFromRequest(WORequest request, WOContext context) {
      if (actAsInput(context)) {
          setValueFromFormValue(request, context);
      }
      super.takeValuesFromRequest(request, context);
}

protected void setValueFromFormValue(WORequest request, WOContext context) {
    Object ratingValue = request.formValueForKey(formValueName(context));
    if (ratingValue instanceof String) {
        ratingValue = Integer.valueOf((String)ratingValue);
    }
    setValueForBinding(ratingValue, "value", context.component());
}
Step 18: Clean and Document

•   Remove debugging code

•   General code clean-up and refactoring

•   JavaDocs for class

•   JavaDocs for methods, @param, @return
Step 19: @binding JavaDocs
  * @binding value the value to show in the ratings widget and the value set
                 when the user selects a different rating

* @binding actAsInput optional, default is <code>true</code>, if false updates
                      the value binding when clicked and optionally calls action
                      method

* @binding action optional, action method to fire when rating changed.   Ignored
                  if actAsInput is <code>true</code> or unbound

* @binding min optional, the value sent to the server when the lowest rating is
               selected, indirectly controls the number of rating points displayed
Step 20: Create .api File
MONTREAL 1/3 JULY 2011




Q&A
Ajax.framework: Under the Hood

Chuck Hill
Global Village Consulting

More Related Content

What's hot

R Visualizations in SAP Analytics Cloud
R Visualizations in SAP Analytics CloudR Visualizations in SAP Analytics Cloud
R Visualizations in SAP Analytics CloudGeetha Madhuri
 
Creating Modern UI PowerBuilder Framework using native objects
Creating Modern UI PowerBuilder Framework using native objectsCreating Modern UI PowerBuilder Framework using native objects
Creating Modern UI PowerBuilder Framework using native objectszulmach .
 
Intro on Oracle Application express - APEX
Intro on Oracle Application express - APEXIntro on Oracle Application express - APEX
Intro on Oracle Application express - APEXLino Schildenfeld
 
Microsoft dynamics ax 2012 development introduction part 2/3
Microsoft dynamics ax 2012 development introduction part 2/3Microsoft dynamics ax 2012 development introduction part 2/3
Microsoft dynamics ax 2012 development introduction part 2/3Ali Raza Zaidi
 
Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)
Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)
Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)ssuser337865
 
Integrating powl with web dynpro abap.
Integrating powl with web dynpro abap.Integrating powl with web dynpro abap.
Integrating powl with web dynpro abap.Adesh Chauhan
 
Oracle APEX for Beginners
Oracle APEX for BeginnersOracle APEX for Beginners
Oracle APEX for BeginnersDimitri Gielis
 
OAuth with Salesforce - Demystified
OAuth with Salesforce - DemystifiedOAuth with Salesforce - Demystified
OAuth with Salesforce - DemystifiedCalvin Noronha
 
Configure iis to access your website using an ip address
Configure iis to access your website using an ip addressConfigure iis to access your website using an ip address
Configure iis to access your website using an ip addressbirhanu atnafu
 
Salesforce Streaming event - PushTopic and Generic Events
Salesforce Streaming event - PushTopic and Generic EventsSalesforce Streaming event - PushTopic and Generic Events
Salesforce Streaming event - PushTopic and Generic EventsDhanik Sahni
 
Design Pattern For C# Part 1
Design Pattern For C# Part 1Design Pattern For C# Part 1
Design Pattern For C# Part 1Shahzad
 
Spring framework Controllers and Annotations
Spring framework   Controllers and AnnotationsSpring framework   Controllers and Annotations
Spring framework Controllers and AnnotationsAnuj Singh Rajput
 
Asp.net web api
Asp.net web apiAsp.net web api
Asp.net web apiBinu Bhasuran
 
Adobe AEM - From Eventing to Job Processing
Adobe AEM - From Eventing to Job ProcessingAdobe AEM - From Eventing to Job Processing
Adobe AEM - From Eventing to Job ProcessingCarsten Ziegeler
 
UDA-Componentes RUP. Autocomplete
UDA-Componentes RUP. AutocompleteUDA-Componentes RUP. Autocomplete
UDA-Componentes RUP. AutocompleteAnder Martinez
 
SAP ODATA Overview & Guidelines
SAP ODATA Overview & GuidelinesSAP ODATA Overview & Guidelines
SAP ODATA Overview & GuidelinesAshish Saxena
 

What's hot (20)

R Visualizations in SAP Analytics Cloud
R Visualizations in SAP Analytics CloudR Visualizations in SAP Analytics Cloud
R Visualizations in SAP Analytics Cloud
 
Creating Modern UI PowerBuilder Framework using native objects
Creating Modern UI PowerBuilder Framework using native objectsCreating Modern UI PowerBuilder Framework using native objects
Creating Modern UI PowerBuilder Framework using native objects
 
asp-net.pptx
asp-net.pptxasp-net.pptx
asp-net.pptx
 
Oracle Application Express
Oracle Application ExpressOracle Application Express
Oracle Application Express
 
Intro on Oracle Application express - APEX
Intro on Oracle Application express - APEXIntro on Oracle Application express - APEX
Intro on Oracle Application express - APEX
 
Microsoft dynamics ax 2012 development introduction part 2/3
Microsoft dynamics ax 2012 development introduction part 2/3Microsoft dynamics ax 2012 development introduction part 2/3
Microsoft dynamics ax 2012 development introduction part 2/3
 
Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)
Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)
Laravel (8) php_framework_handbook__start_from_zer_18604872_(z-lib.org)
 
Integrating powl with web dynpro abap.
Integrating powl with web dynpro abap.Integrating powl with web dynpro abap.
Integrating powl with web dynpro abap.
 
Oracle APEX for Beginners
Oracle APEX for BeginnersOracle APEX for Beginners
Oracle APEX for Beginners
 
Extensible Data Modeling
Extensible Data ModelingExtensible Data Modeling
Extensible Data Modeling
 
OAuth with Salesforce - Demystified
OAuth with Salesforce - DemystifiedOAuth with Salesforce - Demystified
OAuth with Salesforce - Demystified
 
Configure iis to access your website using an ip address
Configure iis to access your website using an ip addressConfigure iis to access your website using an ip address
Configure iis to access your website using an ip address
 
Salesforce Streaming event - PushTopic and Generic Events
Salesforce Streaming event - PushTopic and Generic EventsSalesforce Streaming event - PushTopic and Generic Events
Salesforce Streaming event - PushTopic and Generic Events
 
Design Pattern For C# Part 1
Design Pattern For C# Part 1Design Pattern For C# Part 1
Design Pattern For C# Part 1
 
Spring framework Controllers and Annotations
Spring framework   Controllers and AnnotationsSpring framework   Controllers and Annotations
Spring framework Controllers and Annotations
 
Extensibility
ExtensibilityExtensibility
Extensibility
 
Asp.net web api
Asp.net web apiAsp.net web api
Asp.net web api
 
Adobe AEM - From Eventing to Job Processing
Adobe AEM - From Eventing to Job ProcessingAdobe AEM - From Eventing to Job Processing
Adobe AEM - From Eventing to Job Processing
 
UDA-Componentes RUP. Autocomplete
UDA-Componentes RUP. AutocompleteUDA-Componentes RUP. Autocomplete
UDA-Componentes RUP. Autocomplete
 
SAP ODATA Overview & Guidelines
SAP ODATA Overview & GuidelinesSAP ODATA Overview & Guidelines
SAP ODATA Overview & Guidelines
 

Viewers also liked

Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.
Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.
Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.WO Community
 
Troubleshooting D2W Rules
Troubleshooting D2W RulesTroubleshooting D2W Rules
Troubleshooting D2W RulesWO Community
 
Contributing to the Community
Contributing to the CommunityContributing to the Community
Contributing to the CommunityWO Community
 
Advanced Apache Cayenne
Advanced Apache CayenneAdvanced Apache Cayenne
Advanced Apache CayenneWO Community
 
COScheduler In Depth
COScheduler In DepthCOScheduler In Depth
COScheduler In DepthWO Community
 

Viewers also liked (6)

Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.
Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.
Beyond Fluffy Bunny. How I leveraged WebObjects in my lean startup.
 
Troubleshooting D2W Rules
Troubleshooting D2W RulesTroubleshooting D2W Rules
Troubleshooting D2W Rules
 
Contributing to the Community
Contributing to the CommunityContributing to the Community
Contributing to the Community
 
Advanced Apache Cayenne
Advanced Apache CayenneAdvanced Apache Cayenne
Advanced Apache Cayenne
 
WOdka
WOdkaWOdka
WOdka
 
COScheduler In Depth
COScheduler In DepthCOScheduler In Depth
COScheduler In Depth
 

Similar to Ajax Under The Hood

Ajax tutorial
Ajax tutorialAjax tutorial
Ajax tutorialKat Roque
 
Introduction to ajax
Introduction to ajaxIntroduction to ajax
Introduction to ajaxNir Elbaz
 
Building Applications Using Ajax
Building Applications Using AjaxBuilding Applications Using Ajax
Building Applications Using Ajaxs_pradeep
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just RubyMarco Otte-Witte
 
How to make Ajax work for you
How to make Ajax work for youHow to make Ajax work for you
How to make Ajax work for youSimon Willison
 
API Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API DocumentationAPI Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API DocumentationRouven Weßling
 
27javascript
27javascript27javascript
27javascriptAdil Jafri
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationSociable
 
Soa development using javascript
Soa development using javascriptSoa development using javascript
Soa development using javascriptDsixE Inc
 
Javascript
JavascriptJavascript
JavascriptAdil Jafri
 
Ajax Lecture Notes
Ajax Lecture NotesAjax Lecture Notes
Ajax Lecture NotesSanthiya Grace
 
jQuery Objects
jQuery ObjectsjQuery Objects
jQuery ObjectsSteve Wells
 
jQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends ForeverjQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends Foreverstephskardal
 
Plone Interactivity
Plone InteractivityPlone Interactivity
Plone InteractivityEric Steele
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous JavascriptGarrett Welson
 
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...mfrancis
 
OSGi and Spring Data for simple (Web) Application Development
OSGi and Spring Data  for simple (Web) Application DevelopmentOSGi and Spring Data  for simple (Web) Application Development
OSGi and Spring Data for simple (Web) Application DevelopmentChristian Baranowski
 

Similar to Ajax Under The Hood (20)

Ajax tutorial
Ajax tutorialAjax tutorial
Ajax tutorial
 
Introduction to ajax
Introduction to ajaxIntroduction to ajax
Introduction to ajax
 
Ajax3
Ajax3Ajax3
Ajax3
 
Building Applications Using Ajax
Building Applications Using AjaxBuilding Applications Using Ajax
Building Applications Using Ajax
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
How to make Ajax work for you
How to make Ajax work for youHow to make Ajax work for you
How to make Ajax work for you
 
React js
React jsReact js
React js
 
API Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API DocumentationAPI Days Paris - Automatic Testing of (RESTful) API Documentation
API Days Paris - Automatic Testing of (RESTful) API Documentation
 
27javascript
27javascript27javascript
27javascript
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentation
 
Soa development using javascript
Soa development using javascriptSoa development using javascript
Soa development using javascript
 
Javascript
JavascriptJavascript
Javascript
 
Ajax Lecture Notes
Ajax Lecture NotesAjax Lecture Notes
Ajax Lecture Notes
 
jQuery Objects
jQuery ObjectsjQuery Objects
jQuery Objects
 
jQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends ForeverjQuery and Rails: Best Friends Forever
jQuery and Rails: Best Friends Forever
 
Plone Interactivity
Plone InteractivityPlone Interactivity
Plone Interactivity
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
 
OSGi and Spring Data for simple (Web) Application Development
OSGi and Spring Data  for simple (Web) Application DevelopmentOSGi and Spring Data  for simple (Web) Application Development
OSGi and Spring Data for simple (Web) Application Development
 
Ajax
AjaxAjax
Ajax
 

More from WO Community

KAAccessControl
KAAccessControlKAAccessControl
KAAccessControlWO Community
 
In memory OLAP engine
In memory OLAP engineIn memory OLAP engine
In memory OLAP engineWO Community
 
Using Nagios to monitor your WO systems
Using Nagios to monitor your WO systemsUsing Nagios to monitor your WO systems
Using Nagios to monitor your WO systemsWO Community
 
Build and deployment
Build and deploymentBuild and deployment
Build and deploymentWO Community
 
High availability
High availabilityHigh availability
High availabilityWO Community
 
Reenabling SOAP using ERJaxWS
Reenabling SOAP using ERJaxWSReenabling SOAP using ERJaxWS
Reenabling SOAP using ERJaxWSWO Community
 
Chaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real WorldChaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real WorldWO Community
 
D2W Stateful Controllers
D2W Stateful ControllersD2W Stateful Controllers
D2W Stateful ControllersWO Community
 
Deploying WO on Windows
Deploying WO on WindowsDeploying WO on Windows
Deploying WO on WindowsWO Community
 
Unit Testing with WOUnit
Unit Testing with WOUnitUnit Testing with WOUnit
Unit Testing with WOUnitWO Community
 
Life outside WO
Life outside WOLife outside WO
Life outside WOWO Community
 
Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO DevsWO Community
 
Migrating existing Projects to Wonder
Migrating existing Projects to WonderMigrating existing Projects to Wonder
Migrating existing Projects to WonderWO Community
 
iOS for ERREST - alternative version
iOS for ERREST - alternative versioniOS for ERREST - alternative version
iOS for ERREST - alternative versionWO Community
 
iOS for ERREST
iOS for ERRESTiOS for ERREST
iOS for ERRESTWO Community
 
"Framework Principal" pattern
"Framework Principal" pattern"Framework Principal" pattern
"Framework Principal" patternWO Community
 
Filtering data with D2W
Filtering data with D2W Filtering data with D2W
Filtering data with D2W WO Community
 
Localizing your apps for multibyte languages
Localizing your apps for multibyte languagesLocalizing your apps for multibyte languages
Localizing your apps for multibyte languagesWO Community
 

More from WO Community (20)

KAAccessControl
KAAccessControlKAAccessControl
KAAccessControl
 
In memory OLAP engine
In memory OLAP engineIn memory OLAP engine
In memory OLAP engine
 
Using Nagios to monitor your WO systems
Using Nagios to monitor your WO systemsUsing Nagios to monitor your WO systems
Using Nagios to monitor your WO systems
 
Build and deployment
Build and deploymentBuild and deployment
Build and deployment
 
High availability
High availabilityHigh availability
High availability
 
Reenabling SOAP using ERJaxWS
Reenabling SOAP using ERJaxWSReenabling SOAP using ERJaxWS
Reenabling SOAP using ERJaxWS
 
Chaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real WorldChaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real World
 
D2W Stateful Controllers
D2W Stateful ControllersD2W Stateful Controllers
D2W Stateful Controllers
 
Deploying WO on Windows
Deploying WO on WindowsDeploying WO on Windows
Deploying WO on Windows
 
Unit Testing with WOUnit
Unit Testing with WOUnitUnit Testing with WOUnit
Unit Testing with WOUnit
 
Life outside WO
Life outside WOLife outside WO
Life outside WO
 
Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO Devs
 
Migrating existing Projects to Wonder
Migrating existing Projects to WonderMigrating existing Projects to Wonder
Migrating existing Projects to Wonder
 
iOS for ERREST - alternative version
iOS for ERREST - alternative versioniOS for ERREST - alternative version
iOS for ERREST - alternative version
 
iOS for ERREST
iOS for ERRESTiOS for ERREST
iOS for ERREST
 
"Framework Principal" pattern
"Framework Principal" pattern"Framework Principal" pattern
"Framework Principal" pattern
 
Filtering data with D2W
Filtering data with D2W Filtering data with D2W
Filtering data with D2W
 
WOver
WOverWOver
WOver
 
Localizing your apps for multibyte languages
Localizing your apps for multibyte languagesLocalizing your apps for multibyte languages
Localizing your apps for multibyte languages
 
ERGroupware
ERGroupwareERGroupware
ERGroupware
 

Recently uploaded

Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseWSO2
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governanceWSO2
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaWSO2
 
Decarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceDecarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceIES VE
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
How to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfHow to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfdanishmna97
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2
 
Design and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data ScienceDesign and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data SciencePaolo Missier
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformWSO2
 
JavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuideJavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuidePixlogix Infotech
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard37
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAnitaRaj43
 

Recently uploaded (20)

Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern Enterprise
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governance
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Decarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceDecarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational Performance
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
How to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfHow to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cf
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
Design and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data ScienceDesign and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data Science
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
 
JavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuideJavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate Guide
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 

Ajax Under The Hood

  • 1. MONTREAL 1/3 JULY 2011 Ajax.framework: Under the Hood Chuck Hill Global Village Consulting, Inc. WOWODC 2011
  • 2. Session Overview • My Goals • Outline: • Ajax vs Classical WebObjects • How Things Work vs Just Works • Building Blocks • Case Study • No JSON
  • 3. A Word on our Sponsors • Jean-Francois Veillette • Anjo Krank • Mike Schrag • the rest of us • you
  • 4. A Word on JavaScript • Not a toy scripting language • NOT Java, “Lisp in C’s clothing” • functional programming • loose “duck” typing and prototypal inheritance • dynamic objects • Douglas Crockford and Yahoo
  • 6. Ajax R-R in a Nutshell
  • 7. New R-R Loop Phase • handleRequest • replaces action method • returns response for Ajax request • called by invokeAction • ... at the right time! • takeValues→invokeAction→handleRequest→appendToResponse?’ • returns AjaxResponse (important!)
  • 8. Ajax Action R-R Loop • “The Basic” • takeValues • invokeAction • handleRequest • whatever • can return JS, HTML, or nothing • client-side result varies
  • 9. Ajax Update R-R Loop • “The Meat Lover’s” • ...?_u=MyContainerID&1239887663 • invokeAction • handleRequest • AjaxResponse.generateResponse • invokeAction (yes! again!) • handleRequest (on AUC) • appendChildrenToResponse (AUC)
  • 10. Ajax Submit, Action, & Update • “All Dressed” • takeValuesFromRequest • invokeAction • handleRequest • AjaxResponse.generateResponse • invokeAction (yes! again!) • handleRequest (on AUC) • action method (result discarded) • appendChildrenToResponse (AUC)
  • 11. Ajax Replace R-R Loop • “Poutine Pizza” • ...?_r=true&1239887663 • takeValuesFromRequest • invokeAction • handleRequest • action method (component) returned as replacement) • intuitive, but may be dangerous
  • 12. Special Ajax Classes • AjaxRequestHandler: don’t store page • ERXAjaxApplication: no takeVlaues for ?_u=xxx&2309482093 • ERXAjaxSession: Ajax Page Caching • ERXAjaxContext: partial form submits • AjaxResponse: generateResponse→invokeAction for AUC
  • 15. Support Classes • AjaxComponent • AjaxDynamicElement • AjaxUtils • AjaxOptions, AjaxOption, AjaxConstantOption, AjaxValue
  • 16. AjaxComponent • WOComponent replacement • Stateful • Mostly familiar usage • handleRequest • addRequiredWebResources
  • 17. AjaxDynamicElement • WODynamicGroup replacement • Stateless • Harder to use than WOComponent • Binding and template access • handleRequest • addRequiredWebResources
  • 18. AjaxUtils • createResponse • javascriptResponse • Add JS and CSS resources (via ERXResponseRewriter) • shouldHandleRequest • binding convenience with JSON parsing • response generation • updateDomElement • redirecting • etc. seek and ye shall nd
  • 19. JavaScript/JSON Value Encoding new Ajax.Request('/some_url', { method: 'get', parameters: {company: 'example', limit: 12} });
  • 20. AjaxValue • converts to JavaScript/JSON format • type-aware value • type guessing ability • javascriptValue • [a, b, ...], {a:b; ...}, escaping in strings etc.
  • 21. AjaxOption.Type • simple enumeration • AjaxValue data types • update if you extend AjaxValue
  • 22. AjaxOption • named for Prototype parameter “options” • bridge from bindings to JavaScript • component or dynamic element • Parameters • JavaScript Name • Type • Binding Name • Default Value
  • 23. AjaxConstantOption • Used for computed values public AjaxConstantOption( String javaScriptName, Object constantValue, Type type)
  • 24. AjaxOptions • with an S • collection of key-value pairs • used as component* or class • *component usage likely buggy • works with StringBuffer and WOResponse • works best with AjaxOption.createAjaxOptionsDictionary
  • 25. AjaxOptions Usage public NSDictionary createAjaxOptions(WOComponent component) { NSMutableArray<AjaxOption> list = new NSMutableArray<AjaxOption>(); list.addObject(new AjaxOption("frequency", AjaxOption.NUMBER)); list.addObject(new AjaxOption("onLoading", AjaxOption.SCRIPT)); list.addObject(new AjaxOption("evalScripts", Boolean.TRUE, AjaxOption.BOOLEAN)); ... NSMutableDictionary<String, String> options = AjaxOption.createAjaxOptionsDictionary(list, component, associations()); return options; } response.appendContentString("AUC.registerPeriodic('" + id + "'," + canStop + "," + stopped + ","); AjaxOptions.appendToResponse(options, response, context); response.appendContentString(");");
  • 26. Part II • Being the Second Part
  • 27. Twenty Steps to WO-Ajax • Who loves ya baby? • From discovery to commit • slowly • in 20 steps
  • 28. Step 1: Review and Plan • Find something • See if it is worth using • Plan how you will use it
  • 29. Step 2: Check that License • Licenses like the GPL are best avoided • For Wonder: BSD, MIT or Apache 2 are preferred • For your own projects consider the terms
  • 30. Step 3: Download Source Files • Determine JavaScript les needed • Often component specic and supporting
  • 31. Step 4: Download Resources • Get example HTML from demo source • CSS les • Image resources • License le • Other resources?
  • 32. Step 5: Start Small • AjaxComponent or AjaxDynamicElement? • Ajax, ERCoolComponents, or private? • Create class and/or .wo • Add JS, CSS, images, etc to WebServerResources
  • 33. Step 6: addRequiredWebResources protected void addRequiredWebResources(WOResponse response, WOContext context) { addScriptResourceInHead(context, response, "Ajax", "controls.js"); addScriptResourceInHead(context, response, "Ajax", "prototype.js"); addScriptResourceInHead(context, response, "ERCoolComponents", "Rating/livepipe.js"); addScriptResourceInHead(context, response, "ERCoolComponents", "Rating/rating.js"); addStylesheetResourceInHead(context, response, "ERCoolComponents", "Rating/rating.css"); }
  • 34. Step 7: Static appendToResponse public void appendToResponse(WOResponse response, WOContext context) { super.appendToResponse(response, context); response.appendContentString("<div id="rating_one" class="rating_container">"); response.appendContentString("</div>"); response.appendContentString("<script type="text/javascript">"); response.appendContentString("var rating_one = new Control.Rating('rating_one');"); response.appendContentString("</script>"); }
  • 35. Step 8: handleRequest public WOActionResults handleRequest(WORequest request, WOContext context) { System.out.println("CCRating " + request.headers()); return null; }
  • 36. Step 9: Initial Testing • Smoke Test Time! • Is control rendered correctly? • Does CSS load? • Are images visible? • Does it “work” client side?
  • 37. Step 10: Check Client Side Errors • Use FireBug or Safari Web Inspector • Look for errors in JavaScript console • Look for resources that fail to load
  • 38. Step 11: Update Paths in CSS Resource paths in CSS are likely wrong: background-image:url(/stylesheets/rating.gif); These are resolved (by Wonder) relative to the CSS file’s location: background-image:url(rating.gif);
  • 39. Step 12a: First Dynamic Steps public void appendToResponse(WOResponse response, WOContext context) { super.appendToResponse(response, context); String id = (String) valueForBinding( "id", ERXWOContext.safeIdentifierName(context, false), context.component()); response.appendContentString("<div "); appendTagAttributeToResponse(response, "id", id); appendTagAttributeToResponse(response, "class", "rating_container"); response.appendContentString("></div>");
  • 40. Step 12b: First Dynamic Steps appendToResponse continued... response.appendContentString("<script type="text/javascript">"); response.appendContentString("var "); response.appendContentString(id); response.appendContentString(" = new Control.Rating('"); response.appendContentString(id); response.appendContentString("'); </script>"); }
  • 41. Step 13a: Rating Options <script type="text/javascript"> var e_1_0_0_1_3_7 = new Control.Rating('e_1_0_0_1_3_7', {value: 5, min: 2, max: 8} ); </script>
  • 42. Step 13b: Rating Options response.appendContentString("'); </script>"); response.appendContentString("', "); AjaxOptions.appendToResponse(createOptions(context), response, context); response.appendContentString("); </script>"); } protected NSMutableDictionary createOptions(WOContext context) { NSMutableArray ajaxOptionsArray = new NSMutableArray(); ajaxOptionsArray.addObject(new AjaxOption("min", AjaxOption.NUMBER)); ajaxOptionsArray.addObject(new AjaxOption("max", AjaxOption.NUMBER)); ajaxOptionsArray.addObject(new AjaxOption("value", AjaxOption.NUMBER)); return AjaxOption.createAjaxOptionsDictionary( ajaxOptionsArray, context.component(), associations()); }
  • 43. Step 14: Rest of Bindings ajaxOptionsArray.addObject(new AjaxOption("capture", AjaxOption.BOOLEAN)); ajaxOptionsArray.addObject(new AjaxOption("classNames", AjaxOption.DICTIONARY)); ajaxOptionsArray.addObject( new AjaxOption("input", "inputId", null, AjaxOption.STRING)); ajaxOptionsArray.addObject(new AjaxOption("multiple", AjaxOption.BOOLEAN)); ajaxOptionsArray.addObject(new AjaxOption("rated", AjaxOption.BOOLEAN)); ajaxOptionsArray.addObject(new AjaxOption("reverse", AjaxOption.BOOLEAN)); ajaxOptionsArray.addObject(new AjaxOption("updateOptions", AjaxOption.DICTIONARY)); ajaxOptionsArray.addObject( new AjaxOption("updateParameterName", "formValueName", null, AjaxOption.STRING));
  • 44. Step 15a: Server Interaction ajaxOptionsArray.addObject( new AjaxOption("updateParameterName", "formValueName", null, AjaxOption.STRING)); ajaxOptionsArray.addObject( new AjaxConstantOption("updateParameterName", "formValueName", formValueName(context), AjaxOption.STRING)); ajaxOptionsArray.addObject(new AjaxConstantOption("updateUrl", AjaxUtils.ajaxComponentActionUrl(context), AjaxOption.STRING)); protected String formValueName(WOContext context) { return (String)valueForBinding( "formValueName", id(context) + "_value", context.component());
  • 45. Step 15b: Server Interaction public WOActionResults handleRequest(WORequest request, WOContext context) { System.out.println("CCRating " + request.headers()); System.out.println("CCRating " + request.uri()); System.out.println("CCRating " + request.formValues()); Object ratingValue = request.formValueForKey(formValueName(context)); if (ratingValue instanceof String) { ratingValue = Integer.valueOf((String)ratingValue); } setValueForBinding(ratingValue, "value", context.component()); return null; }
  • 46. Step 16: WO Integration: action Binding public WOActionResults handleRequest(WORequest request, WOContext context) { Object ratingValue = request.formValueForKey(formValueName(context)); if (ratingValue instanceof String) { ratingValue = Integer.valueOf((String)ratingValue); } setValueForBinding(ratingValue, "value", context.component()); // Nothing gets returned to the client from the CCRating action so we // discard any result from firing the action binding if (hasBinding("action")) { valueForBinding("action", context.component()); } return null; }
  • 47. Step 17a: WO Integration: Form Input protected boolean actAsInput(WOContext context) { return booleanValueForBinding("actAsInput", true, context.component()); } protected NSMutableDictionary createOptions(WOContext context) { ... if ( ! actAsInput(context)) { ajaxOptionsArray.addObject(new AjaxConstantOption("updateUrl", AjaxUtils.ajaxComponentActionUrl(context), AjaxOption.STRING)); } else { ajaxOptionsArray.addObject(new AjaxConstantOption("input", id(context) + "_input", AjaxOption.STRING)); }
  • 48. Step 17b: WO Integration: Form Input public void appendToResponse(WOResponse response, WOContext context) { ... if (actAsInput(context)) { response.appendContentString("<input "); appendTagAttributeToResponse(response, "type", "hidden"); appendTagAttributeToResponse(response, "id", id + "_input"); appendTagAttributeToResponse(response, "name", formValueName(context)); appendTagAttributeToResponse(response, "value", valueForBinding("value", context.component())); response.appendContentString("/>"); ... }
  • 49. Step 17c: WO Integration: Form Input public void takeValuesFromRequest(WORequest request, WOContext context) { if (actAsInput(context)) { setValueFromFormValue(request, context); } super.takeValuesFromRequest(request, context); } protected void setValueFromFormValue(WORequest request, WOContext context) { Object ratingValue = request.formValueForKey(formValueName(context)); if (ratingValue instanceof String) { ratingValue = Integer.valueOf((String)ratingValue); } setValueForBinding(ratingValue, "value", context.component()); }
  • 50. Step 18: Clean and Document • Remove debugging code • General code clean-up and refactoring • JavaDocs for class • JavaDocs for methods, @param, @return
  • 51. Step 19: @binding JavaDocs * @binding value the value to show in the ratings widget and the value set when the user selects a different rating * @binding actAsInput optional, default is <code>true</code>, if false updates the value binding when clicked and optionally calls action method * @binding action optional, action method to fire when rating changed. Ignored if actAsInput is <code>true</code> or unbound * @binding min optional, the value sent to the server when the lowest rating is selected, indirectly controls the number of rating points displayed
  • 52. Step 20: Create .api File
  • 53. MONTREAL 1/3 JULY 2011 Q&A Ajax.framework: Under the Hood Chuck Hill Global Village Consulting