Skip to content

Latest commit

 

History

History
809 lines (550 loc) · 28.7 KB

1.8.rst

File metadata and controls

809 lines (550 loc) · 28.7 KB

Dojo 1.8 Release Notes

The following browsers have been tested and are supported in this release. If a browser version is not listed as supported, it still may work, especially on browsers with rapid release cycles (Chrome, Firefox). Future minor releases of dojo might include fixes to support future releases of these browsers, but we cannot guarantee it.

Desktop

  • Firefox 3.6-11
  • Safari 5-6
  • Chrome 13-18
  • IE 6-9
  • Opera 10.50-12 (Dojo core only)

Mobile (dojox/mobile)

  • iOS 4.x, 5.x (Mobile Safari) (including all Dijit widgets except Editor, Dialog)
  • Android 2.2-2.3, 3.1-3.2, 4.0
  • Blackberry 6-7
  • Mobile compatibility on desktop browsers: IE 8-9, Firefox 4-11, Safari 5-6, Chrome 13-18

TODO: Link to page with specific vendor device models tested on

dojo/_base/Deferred was deprecated in lieu of dojo/Deferred. It was updated to utilize the new promise architecture and maintains its legacy API, but developers should transition to dojo/Deferred. Also, dojo/_base/Deferred::when() has been deprecated in lieu of dojo/when.

dojo/_base/xhr was deprecated in lieu of dojo/request/xhr. It was updated to utilize the new request architecture, but developers should transition to dojo/request/xhr.

dojo/_base/sniff was deprecated in lieu of dojo/sniff. It was updated to utilize the new sniff module, but developers should transition to dojo/sniff.

dojo/dnd was enhanced to work on touch devices.

A new implementation of dojo/Deferred based on dojo/promise. It only supports the "modern" promise syntax (e.g. .then() instead of .addCallback() and .addErrback()). It is strongly recommended that you migrate from dojo/_base/Deferred and adopt the new API. See :ref:`dojo/Deferred <dojo/Deferred>`.

While dojo/DeferredList is not changed, it is deprecated in lieu of dojo/promise/all and dojo/promise/first.

The dijit/hccss module has moved to dojo core, with a stub left in dijit for backwards compatibility.

dojo/html::_ContentSetter is now async aware when it comes to parsing content being set. The promise returned from dojo/parser::parse() will be stored in parseDeferred. If using _ContentSetter directly, ensure that you use the parserDeferred to detect when the parsing is actually complete. For example:

.. js ::

  require(["dojo/html", "dojo/when"], function(html, when){
    var setter = new html._ContentSetter({
      node: someNode,
      parseContent: true
    });
    setter.set(someContent);
    when(setter.parseDeferred, function(){
      // Do something
    });
  });

dojo/io/iframe has was deprecated in lieu of dojo/request/iframe. It was updated to utilise the new request architecture, but developers should transition to dojo/request/iframe.

dojo/io/script has was deprecated in lieu of dojo/request/script. It was updated to utilise the new request architecture, but developers should transition to dojo/request/script.

There are several enhancements to dojo/parser:

The Parser now supports the use of Module IDs (MID) when specifying the data-dojo-type in declarative markup (#13778). Developers should use the MID in their code to ensure future compatibility with baseless modules. Just as before, the parser will not load a module that is not already loaded, therefore they need to be required prior to invoking the parser.

An example:

.. js ::

    require(["dojo/parser","dijit/form/Button","dijit/layout/ContentPane"],
      function(parser) {
        parser.parse();
      }
    );
.. html ::

    <div data-dojo-type="dijit/layout/ContentPane">
      <button data-dojo-type="dijit/form/Button">Click Me!</button>
    </div>

The parser now also supports a new data-dojo-mixins attribute that allows to dynamically mixin one or several classes into the main data-dojo-type class as follows:

.. js ::

    require(["dojo/parser", "dojox/treemap/TreeMap", "dojox/treemap/Keyboard", "dojox/treemap/DrillDownUp"],
      function(parser) {
        parser.parse();
      }
    );
.. html ::

    <div data-dojo-type="dojox/treemap/TreeMap" data-dojo-mixins="dojox/treemap/Keyboard, dojox/treemap/DrillDownUp"></div>

There's also a new method construct() that's useful for when you have a widget constructor and want to apply it to a node that may or may not have data-dojo-type specified:

.. js ::

      require(["dojo/parser", "dojo/query", "dijit/form/Slider",], function(parser, query, Slider){
          query("input[type=slider]").forEach(function(node){
               parser.construct(Slider, node);
          }
      }

The parser now fully supports the declarative script tags with a type="dojo/aspect" (#15117). This allows you to define scripts that run in line with the aspect concepts behind aspect programming used in the :ref:`dojo/aspect <dojo/aspect>` module.

Each of the following is possible:

.. html ::

  <div data-dojo-type="package/module" data-dojo-props="foo:'bar'">

    <!-- A script with "before" advice -->
    <script type="dojo/aspect" data-dojo-advice="before" data-dojo-method="method1" data-dojo-args="i">
      console.log("I ran before!");
      i++; // Modify an argument
      return [i]; // Return the modified argument to be used by the original method
    </script>

    <!-- A script with "around" advice -->
    <script type="dojo/aspect" data-dojo-advice="around" data-dojo-method="method2" data-dojo-args="origFn">
      return function(){ // you have to be a factory and return a function
        console.log("I ran before!");
        origFn.call(this); // With around advice, you have to call the original method
        console.log("I ran after!");
      });
    </script>

    <!-- A script with "after" advice -->
    <script type="dojo/aspect" data-dojo-advice="after" data-dojo-method="method3">
      console.log("I ran after!");
    </script>

  </div>

Note with the addition of this coupled with the support of script tags of type="dojo/on", it does mean that script tags of type="dojo/connect" are fully deprecated and will likely be dropped in 2.0. In fact, internally the parser uses dojo/aspect to accomplish a connect anyways.

The parser now supports the ability to require modules declaratively (#15118). This is accomplished using the <script type="dojo/require"> tag. Before the document is scanned and parsed, the parser will look for any <script> tags of type dojo/require and the parser will attempt to load any modules identified in the hash that is contained within the text of the tag and put it in the global scope. For example:

.. html ::

  <script type="dojo/require">
    on: "dojo/on",
    "app.registry": "dijit/registry",
    Button: "dijit/layout/button"
  </script>

See :ref:`Parser Declarative Require <dojo/parser#declarative-require>` for more information.

The parser now supports the ability to automatically require in modules when encountered declaratively (#14591). As the document is being scanned and parsed, but before the widgets are instantiated, the parser will automatically attempt to require in modules that it hasn't been able to resolve a constructor for and the data-dojo-type looks like a MID (e.g. package/module).

Developers should really be cautious when using this features, because you are not making your dependencies clear, you may have a harder time isolating where your issue is, because the parser is automatically loading modules that you may not be consciously aware of.

.. code-example ::

  Here is an example of the feature in action.  Notice how no modules are required.

  .. html ::

    <input type="text" name="field1" data-dojo-type="dijit/form/TextBox" value="Hello World" />
    <button type="button" data-dojo-type="dijit/form/Button">Button</button>

See :ref:`Parser Auto Require <dojo/parser#auto-require>` for more information.

Because of the nature of AMD and require(), when you use either the declarative require feature or the auto require feature, .parse() will operate in an asynchronous mode. In order to maintain backwards compatibility though, the results of .parser() continue to be an Array, but will also have a promise mixed in which is fulfilled with the results of the .parse(). For new development, the safest way to interact with .parse() is to treat the return as a promise. For example:

.. js ::

  require(["dojo/parser"], function(parser){
    parser.parse().then(function(instances){
      // instances contains the instantiated objects
    });
  });

The new dojo/promise package introduces a new architecture for asynchronous promises (callbacks), which are the foundation for :ref:`dojo/Deferred <dojo/Deferred>`.

Promise base class. All promises will be instances of this class. See :ref:`dojo/promise/Promise <dojo/promise/Promise>`.

Default error if a promise is canceled without a reason. See :ref:`dojo/promise/CancelError <dojo/promise/CancelError>`.

Takes multiple promises and returns a new promise that is fulfilled when all promises have been fulfilled. This essentially replaces dojo/DeferredList. See :ref:`dojo/promise/all <dojo/promise/all>`.

Takes multiple promises and returns a new promise that is fulfilled when the first of these promises is fulfilled. See :ref:`dojo/promise/first <dojo/promise/first>`.

A mixin that allows tracing of promise fulfilment. Calling .trace() or .traceError() on a promise enables tracing. Will emit resolved, rejected or progress events. See :ref:`dojo/promise/tracer <dojo/promise/tracer>`.

The dojo/request package introduces a new architecture for making asynchronous requests from code. The module abstracts the user, for the most part, from the actual provider that makes the request. This means the doesn't have to normally deal with the specifics of how the request is actually made. It builds upon the dojo/promise package.

Requiring the dojo/request as a module will return the default provider, based on platform. Browser based platforms use dojo/request/xhr and node based platforms use dojo/request/node.

See :ref:`dojo/request <dojo/request>` for more information.

Returns the default provider. See :ref:`dojo/request/default <dojo/request/default>` for more information.

The XHR provider. This is the default provider for browser based platforms. This deprecates dojo/_base/xhr. See :ref:`dojo/request/xhr <dojo/request/xhr>` for more information.

The node provider. This is the default provider for node based platforms. See :ref:`dojo/request/node <dojo/request/node>` for more information.

The iframe provider. This deprecates :ref:`dojo/io/iframe <dojo/io/iframe>`. See :ref:`dojo/request/iframe <dojo/request/iframe>` for more information.

The script provider. This deprecates :ref:`dojo/io/script <dojo/io/script>`. See :ref:`dojo/request/script <dojo/request/script>` for more information.

This module defines the handles for the responses to requests as well as provides a mechanism for registering additional handlers. The modules automatically registers javascript, json and xml. See :ref:`dojo/request/handlers` for more information.

Creates and manages the dojo/request/* topics. See :ref:`dojo/request/notify <dojo/request/notify>` for more information.

Used for watching and managing inflight requests. See :ref:`dojo/request/watch <dojo/request/watch>` for more information.

Used mapping URIs to particular providers. Useful when certain URIs require one type of provider, but others require a different one (like cross domain scenarios), but allow the user to develop a single path in the code. See :ref:`dojo/request/registry <dojo/request/registry>` for more information.

A set of utilities used by the dojo/request package.

The dojo/_base/sniff module was superseded by dojo/sniff. dojo/sniff functions the same way as the old module, except doesn't set globals like dojo.isIE. Instead, use has("ie") etc.

dojo/Stateful now supports custom accessors for Object properties (#15187). This is similar to the functionality in dijit/_WidgetBase. Setting a custom accessor in the format of _xxxSetter or _xxxGetter will automagically be called when set() or get() or invoked. For example:

.. js ::

  require(["dojo/Stateful", "dojo/_base/declare"], function(Stateful, declare){
    var aClass = declare(null, {
      foo: null,
      _fooGetter: function(){
        return this.foo;
      },
      _fooSetter: function(value){
        this.foo = value;
      }
    });

    var aInstance = new aClass();

    aInstance.set("foo", "bar");
    aInstance.get("foo");
  });

In addition, custom setters that will not be setting an attribute immediately (for example doing an XHR request to transform a value) can return a promise and the attribute watches, if any, will not be called until the promise is fulfilled.

There is a helper function directly setting the value of an attribute/property named _changeAttrValue that is intended for use when you have co-dependent values where calling set() is not appropriate, like when a value is set on a widget the checked state needs to change as well.

See :ref:`dojo/Stateful <dojo/Stateful>` for further information.

dojo/touch was enhanced to support touch.over, touch.out, touch.enter and touch.leave synthetic events similar to mouseover, mouseout, mouseenter, and mouseleave.

In addition, touch.move on mobile was changed to work like mousemove on desktop, so that when connecting to a DOMNode:

.. js ::

    on(node, touch.move, func)

It fires whenever and only when the finger is dragged over the specified node, regardless of where the drag started. Behavior when connecting to a document is unchanged.

Transparently applies callbacks to values and/or promises. See :ref:`dojo/when <dojo/when>`.

  • widget events, including attribute changes, are emitted as events on the DOM tree
.. js ::

    on(dom.byId("buttonContainer"), "click", function(evt){
        var widget = registry.getEnclosingWidget(evt.target);
        if(widget){
            console.log("click on widget " + widget.id);
        }
    });

See :ref:`Widget events published to the DOM <quickstart/events#widget-events-published-to-the-dom>` for details.

  • attribute setters specified with string values can now point to sub-widgets as well as DOMNodes, ex:
.. js ::

    dojo.declare("MyWidget",
        [dijit._WidgetBase, dijit._TemplatedMixin, dijit._WidgetsInTemplateMixin], {

        templateString:
            "<div>" +
                "<button data-dojo-type='dijit/form/Button'
                    data-dojo-attach-point='buttonWidget'>hi</button>" +
                "<input data-dojo-attach-point='focusNode'>" +
            "</div>"

        // Mapping this.label to this.buttonWidget.label
        label: "",
        _setLabelAttr: "buttonWidget",

        // Mapping this.value to this.focusNode DOMNode
        value: "",
        _setValueAttr: "focusNode",
    });
  • Can now accept a String for the value parameter (either as an argument to the constructor, or to set("value", ...).
.. js ::

    new dijit.Calendar({value: "2011-12-25"});
  • ContentPane now supports addChild() and removeChild(). However, the behavior of addChild(widget, index) is undefined if the ContentPane already contains random HTML. It's intended to be used when the pane contains just a list of widgets, like Toolbar or BorderContainer.
  • ContentPane.addChild(child) will not call resize() on the new child widgets, so it should be used carefully on ContentPanes inside of a layout widget hierarchy. Note that resize() only works on visible widgets, not hidden widgets such as unselected tabs of a TabContainer.
  • ContentPane is now async aware when setting its content via the ContentSetter.
  • DateTextBox's drop down Calendar no longer automatically opens upon clicking the input area, unless the hasDownArrow=false option is set (in which case that's the only way to open the drop down Calendar). (#14142)

dijit/Destroyable is new utility mixin to track handles of an instance, and then destroy them when the instance is destroyed. The application must call destroy() on the instance in order to release the handles.

This functionality was extracted from _WigetBase and most users will access it through _WidgetBase (or a subclass of _WidgetBase).

Example usage:

.. js ::

    var DestroyableSubClass = declare(Destroyable, {
        constructor: function(aStatefulObject){
            var self = this;
            this.domNode = domConstruct.create("button");
            this.own(
                // setup an event handler (automatically remove() when I'm destroyed)
                on(this.domNode, "click", function(){ ... }),

                // watch external object (automatically unwatch() when I'm destroyed)
                aStatefulObject.watch("x", function(name, oVal, nVal){ ... }),

                // create a supporting (internal) widget, to be destroyed when I'm destroyed
                new MySupportingWidget(...)
            );
        }
    });
  • Sizing improved for when Dialog is too big to fit in viewport. Also, sizing automatically adjusts if users resizes the browser window. (#14147)
  • Performance fixes for editors with lots of text (#14231)

The Menu widget has two new (optional) attributes:

  • selector:

    CSS selector that specifies that the Menu should be attached, via event delegation, to matching subnodes of targetNodeIds, rather than the targetNodeIds nodes themselves.

  • currentTarget:

    (readonly) which node the menu is being displayed for

Together, they allow a single Menu to attach to multiple nodes through delegation, and for the Menu's action to be adjusted depending on the node. For example:

.. js ::

  require(["dijit/registry", "dijit/Menu", "dijit/MenuItem", "dojo/query!css2"], function(registry, Menu, MenuItem){
      var menu = new Menu({
          targetNodeIds: ["myTable"],
          selector: "td.foo"
      });
      menu.addChild(new MenuItem({
          label: "click me"
          onClick: function(evt){
              var node = this.getParent().currentTarget;
              console.log("menu clicked for node ", node);
          }
      }));
  });

This will track right-click events on each cell of a table with class="foo".

Further, the targetNode's contents can be changed freely after the Menu is created. Nodes matching the selector can be created or removed, and no calls to bindDomNode() or unBindDomNode() are necessary.

Note that, like :ref:`dojo/on::selector() <dojo/on#selector-function>`, you need to require() an appropriate level of dojo/query to handle your selector.

The Tooltip widget has two new (optional) parameters:

  • selector: CSS selector that specifies that the Tooltip should be attached, via event delegation, to matching subnodes of the connectId node, rather than the connectId itself.
  • getContent(): lets the app customize the tooltip text that's displayed based on the node that triggered the tooltip.

These parameters allow a single Tooltip widget to display unique tooltips for (for example) each row in a table:

.. js ::

  new Tooltip({
    connectId: myTable,
    selector: "tr",
    getContent: function(matchedNode){ return ...; /* String */}
  });

Further, the table contents can be changed freely after the Tooltip is created. Rows can be created, removed, or modified, and no calls to the Tooltip widget are necessary.

Another example: specifying selector=".dijitTreeRow" will track mouseenter and mouseleave events on each row of a Tree, rather than merely monitoring mouseenter/mouseleave on the Tree itself.

Note that, like :ref:`dojo/on::selector() <dojo/on#selector-function>`, you need to require() an appropriate level of dojo/query to handle your selector.

All browsers except IE now implement shading in the claro theme via CSS gradients, rather than by using images. This reduces the number of files downloaded, speeding up page load.

Also, the remaining gradient images files (for IE) no longer contain any blue. Thus, customizing claro to a different does not require modifying those files. You are still required however to update icon files that contain the theme's primary color, such as:

  • checkboxes and radio buttons
  • the slider handles
  • calendar arrows
  • Dialog and TabContainer close icons
  • etc.

There have been many performance improvements to dijit:

  • CSS gradients used in claro (see above)
  • _CssStateMixin now creates listeners at the document level, rather than separate listeners for each widget. This speeds up page instantiation time, especially on a page with many small widgets like TextBoxes, Buttons, Trees (because of the many rows of the Tree), and Menus.
  • Similar event delegation changes were made for Menu and Tree, putting the listeners on the Menu or Tree rather than each individual MenuItem/TreeNode
  • Performance improvement for TabContainers with closable tabs, because only one close Menu is created per TabContainer, rather than one Menu per tab. Event handling was also moved to TabContainer level rather than at each individual tab.
  • A new dropLabels mode was introduced on axis. It is true by default and allows to drop superfluous labels on the axis. Note that in some cases this might slow down a bit the initial computation of the chart. You can avoid that by:

    • setting dropLabels to false (but then you don't get the automatic drop labels)
    • setting minorLabels to false if you know minorLabels won't show up anyway
  • Bars, Columns and Pie plots now support drop shadow property.

  • dojox.charting.widget classes now inherits from _WidgetBase instead of _Widget.

  • Base class for themes is now SimpleTheme instead of Theme. Themes that require gradients still need to use Theme which now inherits from SimpleTheme.

  • Provide a styleFunc on the various plots to allow to dynamically style the plot items.

  • Improve the management of missing data point in line-based plot by providing a interpolate option.

A new Calendar component is introduced in dojox.calendar package. It displays events from a data store along time using widespread representation and allows to interactively edit the position in time and duration of these events.

A new gauges package is introduced in dojox.dgauges package. It provides a fully extensible gauges framework allowing you to create your own gauges as well as predefined, ready to use gauge widgets. Both circular and rectangular gauges (horizontal and vertical) are supported.

A new Treemap component is introduced in dojox.treemap package. It displays data as a set of colored, potentially nested, rectangular cells. Treemaps can be used to explore large data sets by using convenient drill-down capabilities. They reveal data patterns and trends easily.

A webkit-mobile build profile was added to eliminate IE etc. code paths from a build intended only to run on webkit-mobile devices.

To create this special build:

cd util/buildscripts/
./build.sh releaseDir=... action=release optimize=closure profile=webkitMobile
  • The Gfx API now supports clipping at shape level via the new Shape.setClip(clipGeometry) method. The possible clipping geometry types are rectangle, ellipse, polyline and path (vml only supports rectangle clipping, while the gfx silverlight renderer does not support path clipping.
  • A new Shape.destroy() method has been added to properly dispose a shape when it is not used anymore. The Group.clear() method has been updated to take an optional boolean parameter that indicates whether the group children should be disposed while clearing the group.
  • The Group.getBoundingBox() method now returns the children bounding rectangle.
  • New modules specific to the svg and canvas renderers have been added, respectively dojox/gfx/svgext and dojox/gfx/canvasext. The purpose of these modules is to give the user access to the specific capabilities of the renderer.
    • canvasext defines new methods enabling access to the Canvas pixel manipulation API, via the new Surface.getContext(), Surface.getImageData() and the Surface.render() public method.
    • svgext defines a new Shape.addRenderingOption(option, value) that adds the specified SVG rendering option on this shape, as specified by the SVG specification (http://www.w3.org/TR/SVG/painting.html#RenderingProperties)
  • tracTreemap: a treemap demo visualizing trac ticket status
  • calendar: a calendar component demo
  • todoApp: a "todo" application leveraging dojox/mobile, dojox/app & dojox/mvc packages
  • mobileGallery; the mobile gallery now highlights the latest dojox/mobile features
  • gauges & mobileGauges: the gauges demos now use the new dojox/dgauges package
  • Constructor parameters: Execution of custom setters during widget construction has slightly changed. This may affect custom widgets that adjust widget parameters in postMixInProperties().

    As before, during initialization, _setXyzAttr(val) is called for each attribute xyz passed to the constructor where the attribute has a corresponding _setXyzAttr() function or string. The change is that the value passed is the value specified to the constructor, rather than this.xyz. In other words, given a widget like

    .. js ::
    
      declare("MyWidget", {
           this.xyz: "",
           postMixInProperties: function(){
               this.xyz = "dog";
           },
           _setXyzAttr(val){
              ...
           }
      }
    

    and then calling the constructor with a custom value:

    .. js ::
    
      new MyWidget({xyz: "cat"})
    

    Then _setXyzAttr("cat") will be called, rather than _setXyzAttr("dog") like before.

  • Connecting to Menu._openMyself(): If you have menus on Trees etc. where you have connected to the private method Menu._openMyself(), you should switch to the pattern shown above in the Menu section.

  • Due to the event delegation performance improvements, if you have custom templates for TreeNode, MenuItem, or TabButton, you should edit the templates to remove the data-dojo-attach-event="..." attributes.

See https://www.ibm.com/developerworks/mydeveloperworks/blogs/ykami/entry/migration_to_dojox_mobile_1_82