Development

sfUnobstrusiveDojoPlugin

You must first sign up to be able to contribute.

Unobtrusive Dojo Plug-In

The sfUnobstrusiveDojoPlugin offers helpers to easyily enrich your views with the magnificant and big numbered amount of widgets that come

with the Dojo Toolkit.

Warning: This plugin is in Alpha state, so expect changes to be made in the near future.

Introduction

Dojo Packages

Dojo is divided into different parts

  • dijit : This is the widget-package, recognized by the package-prefix dijit.
  • dojo : This is the core-package and includes everything except of widgets or additional,extensional subprojects (see nextpoint).
    You'll recognize it by the package-prefix dojo.
  • dojox : This is the extension-package. It extends dojo by subprojects which are maintained by different authors. If you tend to add additional behaviour to your dojo-repository, first take a look into dojox to see what code is already provided to avoid reinventing some dojo-wheels ;)

Dojo approaches

The Dojo Toolkit itselfs provides two approaches to enrich your HTML

  • declaratively,
    so you just can turn an normal
        <input type="text">
    
    into a Currency/Number/Date or other validatable Textbox by adding a simple HTML-Attribute
        <input type="text" dojoType="dijit.form.NumberTextBox" ...>
    
    A number textbox can/should have a min and a max value, so you have to specify the NumberTextbox? by further attributes.
        <input type="text" dojoType="dijit.form.NumberTextbox" constraints="{min:-20000,max:20000}" ...>
    
    That is not only restricted to dijit's.
    Normal dojo-components (prefixed with dojo.) can and should also be included into your normal HTML e.g. you can "misuse" a normal
        <div></div> 
    
    and make it to an JSON-Data-Store by adding
        <div dojoType="dojo.data.ItemFileReadStore" jsId="stateStore" url="/dojoroot/dijit/tests/form/comboBoxData.json"></div>
    
    As seen all widgets have at least the "dojoType"-Attribute in common and provide further special attributes (url=...,constraints=...) to describe the widget more precisely
  • programmatically,
    This is the normal way we know so far writing Javascript using methods, selectors, binding events and making XMLHttpRequests and so on...
    Dojo uses this approach to handle all of the dojo-work (briefly: the declarativelay defined widgets are parsed and then generate valid Javascript). You will use dojo programmatically for following reasons
    • to define an extension point for an already defined dijit-widget to customize it to your Appication
    • to react to a user interaction and change other widgets during runtime
    • you write a new or extend a given dojo widget (to be honest you'll have to use JS, HTML and CSS for that)
    • you write a new or extend a dojo component funtionality
    • a dojoX package yourself (see below) or

First Steps

There is one more point before we start: Only using the dijit-widgets won't bring you far, but it's the best starting point to unterstand dojo, so first try to get familiar with the widgets.

To briefly give a summary about them - dijit components are based on three things:

  • attributes (the HTML-Attributes seen above):
    these are used to initially define a widget or saying it programmatically, used for the constructor. Once they are defined, they can't be changed, except of the attributes that have a standard proxy method
  • standard methods (the standard behaviour):
    these are methods, defined by the widget's author to provide either proxy methods to attributes (to change them after they widget is created) or to be called by a programmatically defined extension point
  • extension points (your customized behaviour):
    these are methods with a default standard behaviour which can and should be overridden by you to customize the widget for your own app. The extension points are mostly called by the standard methods.

Installation

The sfUnobstrusiveDojoPlugin uses the sfPJSPlugin, which provides a way to call dynamically generated JavaScript files.

The benefit is the same as with UJS over PJS.You can write javascript through helpers directly into the main template and avoid switching back and forth to a behaviour template plus if you use the dojoType-attribute directly in your HTML-Code the appropiate dojo-classes will be loaded dynamically.

  • Install the plugin
    $ symfony plugin-install http://plugins.symfony-project.com/sfUnobstrusiveDojoPlugin
    

  • If it is not installed yet, install the sfPJSPlugin, which is necessary to run this plugin.
  • Download the dojo-toolkit and copy it into the plugins directory so that you have the following directory structure. Since the maximum size of symfony-plugin is 5MB, you have to this by yourself, because the dojo toolkit has a weight of 8MB
      sfUnobstrusiveDojoPlugin/
        web/
          js/
            dojo-0.9.0/
              dijit/
                ...
              dojo/
                ...
              dojox/
                ...
              util/
                ...
    
  • Enable the sfUnobstrusiveDojo module in the settings.yml:
    all:
      .settings:
        enabled_modules:        [default, sfUnobstrusiveDojo]
    
  • Activate the sfUnobstrusiveDojoFilter in the apps/myapp/filters.yml:
    This plugin can be used aside the sfUJSPlugin, but for programming usability and bug fixing it is recommended that it should be activated directly after the common filter and just before the already defined sfUJSFilter.
    Why ?
    Because the symfony filters are firstly executed from rendering to execution and then back. On their way back the view is populated with all the rendering of the final HTML Code, so all CSS and JS files included with use_stylesheet(...) or use_javascript(...) are included on the way back in the common filter.
    And since Dojo loads much of it's components and dijit-widgets at runtime, it's better (for debugging with the firebug) to have the single UJS-Javascript-File included before Dojo loads a lot of code dynamically. So you better define the sfUJSFilter after the sfUnobstrusiveDojoFilter so its processed before it (on the filterchain's way back to the rendering filter).
    rendering: ~
    web_debug: ~
    security:  ~
    
    # generally, you will want to insert your own filters here
    
    cache:     ~
    common:    ~
    Dojo:
      class: sfUnobstrusiveDojoFilter
    UJS:
      class: sfUJSFilter
    
    flash:     ~
    execution: ~
    
  • In your layout.php (resp. the decorating templates in which you want to use dojo), add following lines just before the closing head-tag resp. add a class-attribute to your beginning body-tag
    <head>
      ...
      <script type="text/javascript" src="/sfUnobstrusiveDojoPlugin/js/dojo-0.9.0/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
    </head>
    <body class="<?php echo sfConfig::get('app_dojo_theme'); ?>">
    
  • To use the themes you have to define the theme in the app.yml
    all:
      dojo:
        theme: tundra # change it either to soria or noir or to your own created theme name
    
    Dojo ships with three themes (tundra, soria and noir) but you can define own dojo themes

  • Clear the cache to enable the autoloading to find the new classes
      $ symfony cc
    

Filters and Helpers

The Filter

The Filter does two things:

  • like the sfUJSFilter it takes all the calls of the sfUnobstrusiveDojoHelper-functions, writes them into a final js-file and includes this file into the final HTML-Code
  • it parses the final HTML-Code for HTML-Tags with a "dojoType"-attribute and writes it's value (the needed dojo/dijit-component)

into the final js-file. So for the beginning if you're only testing the dijit-components you'll be fine by just adding the dojoType-attribute to your HTML-Tags. The filter will automatically generate dojo.require(...) with the appropiate class name.

The filter automatically includes two css files (the theme's css and the general dojo.css) and a extra dojo.require('dojo.parser') because dojo.parser is always needed.

The Helper

  • The sfUnobstrusiveHelper works like the sfUJSHelper with only six functions
    • Dojo($script) : Like the UJS(...)-function you can add javascript-code to use dojo-programmatically
    • Dojo_block() and Dojo_end_block(): defines the start and the end of a javascript-block. You can even use it this way
              <?php Dojo_block()?><script>
                ...
              </script><?php Dojo_end_block()?>
      
      Most texteditors only do syntax hightlighting for javascript when it's defined between script-tags. The dojo_block()-functions automatically strips them for you so use your texteditor's syntax highlighting.
    • Dojo_set_inclusion($static) : Sets the inclusion type (static: into the rendered HTML Code, dynamically: into a single js file) Default is false. For further information read the appropiate chapter of the sfUJSPlugin
    • get_dojo() : this function is called by the filter to get all the code defined by Dojo(...), Dojo_block(...)/Dojo_end_block(...) and include it either statically or dynamically (see Dojo_set_inclusion(..)) into the finally rendered HTML-Code ()
    • include_Dojo() : use this function if you want to specify where the code is inserted into the finally rendered HTML when you use it statically

Examples

These examples are from the dojo-book (take a peek). I modified them to show you how to use it with the sfUnobstrusivePlugin
An asterisk * separates dojo-attributes from normal HTML-Attributes

Example 1 : NumberSpinner


Easy beginning: We will add a NumberSpinner to our form

<input *dojoType="dijit.form.NumberSpinner"
       value="1000"
       *smallDelta="10"
       *constraints="{min:9,max:1550,places:0}"
       maxlength="20"
       id="integerspinner2">

In our example we define a NumberSpinner with a range from a min value of 9 to a max value of 1550 and 0 decimal places (so we have only integer values). The NumberSpinner will take steps of 10 numbers per click. For further information another peek.

Example 2 : The color palette


The Example with the extension point : The Color Palette is the best way to show the use of an extension point.

  <div *dojoType="dijit.ColorPalette" onChange="reportColor"></div>

<?php Dojo("
  function reportColor(selectedColor) {
    console.debug(selectedColor); // ==> here you could have also defined an other behaviour e.g. change the background-color a specific element
  }
");?>

this results in

// a js-file with the following content
dojo.require('dojo.parser'); // ==> always included when the filter finds a class to include (here the filter finds "dijit.Colorpalette")
dojo.require('dijit.Colorpalette'); // ==> included by the filter
function reportColor(selectedColor) { // included by the filter because of the use of the helper functions 
  console.debug(selectedColor);
}

Example 3 : A Dojo Combo-Box


More complicated example : We add a combobox to our form. And a DIV as a data store for JSON. Since comboboxes are dojo.data-enable it can use the div as a data store.

<div *dojoType="dojo.data.ItemFileReadStore" 
     *jsId="stateStore" 
     *url="/dojoroot/dijit/tests/form/comboBoxData.json"></div>
              
<input dojoType="dijit.form.ComboBox"
       *store="stateStore"
       value="California"
       *searchAttr="name"
       name="state2"
       onChange="setVal2" /> <!-- the call back, we'll ignore this because we focus on the data store -->

the JSON data, specified by the url-attribute could look like:

{ identifier:"abbreviation",
  items: [
    {name:"Alabama", label:"Alabama",abbreviation:"AL"},
    {name:"Alaska", label:"Alaska",abbreviation:"AK"},
    {name:"American Samoa", label:"American Samoa",abbreviation:"AS"},
    {name:"Arizona", label:"Arizona",abbreviation:"AZ"},

results in (exluding the comments)

// the final HTML Code...
// ... stays the same as defined but you have now a undisplayed div with the json-data in it and a name for it (stateStore)
// you can now use it as the data store for the combobox (`store="stateStore"`).
// the "searchAttr" defines the attribute name in the JSON-data that is searched when typing. 
// that makes your combobox to an autocomplete-enabled combobox 

Bugs

If you find any bugs (and I'm sure there are plenty of them) feel free to mail me at dojo-plugin [at] nikpour [dot] com

TODOs

  • Add Links to the dojo site for further reading
  • Find a way to get the filter to add the <script>-Tag
  • More examples

Changelog

2007-10-02 | 0.0.2 Alpha

2007-10-01 | 0.0.1 Alpha

  • Initial Release

Attachments