Login Register

Dojotoolkit.org

Disintegrate Effect

Dojotoolkit.org - Sat, 07/05/2008 - 05:38

With the successful completion of the explode effect, I decided to build on the code used to split the node into pieces. I split the code in half and thus created a new generic function, dojox.fx._split that returns an animation object that splits the node into args.rows and args.columns and applies args.pieceAnimation() to each piece. This function takes the piece, its x and y location in the grid of pieces, and the dojo.coords of the original node as arguments and returns either an animation object or an array of animation objects to be combined.

So, I can now start churning out all types of effects that deal with pieces of a node separately. I've already created a disintegrate effect, in which each piece drops 1.5 times the height of the node and fades out. You can play with it and other effects in progress here.

Although I could continue in this direction, I've decided to go back and create effects that make the node appear from nothing rather than disappear. This may be slightly more involved, since I'd like to avoid the "stale values" issue as well as making the user explicitly define the dimensions of the node at the end of the animation.

Categories: Dojotoolkit.org

DnD Form Editor Progress

Dojotoolkit.org - Fri, 07/04/2008 - 19:35

I missed my update last week, so this post actually covers the past two weeks.

Rewrite with dijit._Widget

One of the first things Peter mentioned after my initial commits was that my code was not very Dojo-like, and (though he didn't say it) not very good. I had all the setup code in a single initialization function, which the client had to explicitly call. Instead of having a separate class for each component (Source, Canvas, Editor), each piece was declared as a dojo.dnd.Source and then specific actions were attached here, there, and anywhere. The code was not at all modular, with the implementation exposed in many places. Peter gently suggested making each component a subclass of dijit._Widget, which would give me a lot of built-in functionality (dijit.byId, constructors, etc.) for free.

Refactoring the code to subclass dijit._Widget has been very helpful. The components are completely decoupled, my code is much more modular, and the client code is quite simple. Creating a class for each component also makes customizing their behavior a cinch, since it's easy to monkeypatch any of the class methods.

PropEditor

I've finally created the PropEditor, which allows you to edit the properties of a field element. Right now it only supports changing the name, but eventually it will be able to edit the choices for a select, change the default value for a field, and more.

pub/sub

I'm trying to keep the components completely decoupled after the refactoring, so each piece is usable in isolation from the others. This means that, for example, the Canvas can't call a method of the PropEditor when a field is selected, since there may not even be a PropEditor instance on the page. Instead of direct method calls, I'm using dojo.publish + dojo.subscribe to pass messages and data around to anyone who wants to listen. This is my first time doing event-driven programming like this, and I think it's a neat way to maintain modularity between classes. The PropEditor could actually be used on any page that publishes the correct messages, not just in concordance with my Canvas class.

Loading existing elements

Since I'm building a form editor, and not just a form creator, the Canvas needs a way to load existing form elements from a page. Taking a page from dojo.dnd.Source, the Canvas will now add any existing soc.ed.Elements to its internal structure when the Canvas is created, similar to how dojoDndItems are gathered.

All the major pieces of the editor have been created, so now I'll be focused on making each one richer and better.

Categories: Dojotoolkit.org

GFX 2.0 Analysis document

Dojotoolkit.org - Fri, 07/04/2008 - 04:36

Hi dojoers,

I am thinking to put my analysis document for GFX 2.0 (this document has been updating from the first time discussion with my mentor Mr.Eugene Lazutkin). You can read the document to know more about abstract design of GFX 2.0... At the moment, I am writing document to explain thoroughly about GFX 2.0 implementation, it will be described about:
- Assumption implementation (for example, no color texturing, no light feature, etc)
- Implementation detail (including design diagram, improvement made to increase performance)
- Problem (algorithm, feature that hard to implement)

Link for the analysis document can be read in this link

Categories: Dojotoolkit.org

d-rails progress, or, my journey through javascript scope hell.

Dojotoolkit.org - Wed, 07/02/2008 - 21:13

This week I've made a lot of progress on rails' JavaScriptGenerator. JavaScriptGenerator basically offloads a lot of the work to the underlying prototype js library, and it's meant to be an expressive means of speaking javascript with ruby code. To maintain this flexibility, I've been implementing a lot of prototype functionality in our drails javascript package.

There are 2 new classes, drails.Element and drails.ElementCollection, and one new interface, drails.Enumerable.

drails.Element is a stripped down version of prototype's Element, but rather than extending a DOMNode with additional functionality, it wraps it in a class and provides the basic API that rails explicitly exposes in JavaScriptGenerator. I say explicitly, because a neat feature of JavaScriptGenerator is that if you call a method that isn't explicitly defined in it, it tries to pass it down the chain to the underlying javascript.

The implementation of drails.Element is the opposite of the prototype Element. prototype declares a bunch of methods that look like this:
Element.insert(element, insertions);

and then "methodizes" them each time a DOM Node is extended, with code that looks something like this:
// element == Dom Node
    for (property in Element.Methods) {
      value = Element.Methods[property];
      if (Object.isFunction(value) && !(property in element))
        element[property] = value.methodize();
    }

Function.prototype.methodize = function() {
    if (this._methodized) return this._methodized;
    var __method = this;
    return this._methodized = function() {
      return __method.apply(null, [this].concat($A(arguments)));
    };

Instead of this, I define the methods as instance methods of the drails.Element class, but then provide the same "static" style interface as prototype by instantiating a new instance of drails.Element for the "static" style interface:

drails.Element.Functions = (function(){
  function functionize(method){
    return function(){
      var args = drails.toArray(arguments);
      return method.apply(new drails.Element(args[0]),args.slice(1));
    };
  }
  functions = {};
  for(prop in drails.Element.Methods){
    var value = drails.Element.Methods[prop];
    if(dojo.isFunction(value) && prop[0] != "_"){
      functions[prop] = functionize(value);
    }
  }
  return functions;
})();

It took me awhile to get this flow correct and working, as there are some tricky scope issues when passing around anonymous functions. At least now I finally understand what this means.

drails.ElementCollection is similar in scope, in that it wraps a NodeList (i.e. one returned from dojo.query) in a class, and mixes in the Enumerable interface, so you end up with an Enumerable collection of drails.Elements.

Not much more to say here until I finish getting unit tests in place, but you can have a look at all the new javascript code here: http://pastie.org/226646

Please let me know if you see anything amiss with it.

Categories: Dojotoolkit.org

Explode Effect

Dojotoolkit.org - Wed, 07/02/2008 - 19:09

I created a nice animation effect that splits the element into an arbitrary number of rows and columns, then sends them flying away from the element's center. The user can specify whether or not the pieces fade out as they move, and whether or not the distance and duration of each piece's animation should be randomized.

The effect is accomplished by cloning the node once for each piece and combining each piece's animation together. The original node's opacity is set to zero onPlay.

Unfortunately, there are a few small kinks I still need to work out in the way the effect is structured. For example, many of the basic _Animation arguments are ignored, and the effect does not play nicely with dojo.fx.chain.

Now that I have a successful technique for splitting a node into pieces and animating them, I can create a whole slew of unique effects never before seen in a JavaScript toolkit. I'll be demonstrating these effects here as I perfect them.

Categories: Dojotoolkit.org

Welcome Opera GFX 2.0

Dojotoolkit.org - Wed, 07/02/2008 - 04:08

Hi dojoers,

Finally, after bugging around with algorithm to change Quaternion to Euler rotation system... The Opera implementation for GFX 2.0 is out... It is around 90% though (I need mathematician who understand about good camera management).

Since the Firefox and Opera implementation are already out... So I already achieved the unification API feature of GFX 2.0... After mid evaluation, I want to jump into high level of GFX 2.0 to make interactive 3D module... such as loading 3d model... and easy 3d environment loader file... I also want to make a real world example...
Some example:
-Model Viewer
GFX 2.0 supports user to load or create 3D model in 3D environments. For example, a furniture website would like to show 3D model furniture to user. User is able to interact with the 3D model furniture like manipulating the view (rotate, zoom or pan view) and changing 3D model state (opening door of wardrobe).
-Statistic Chart
GFX 2.0 allows user to view charts both in 2D and 3D environments. In 3D environment, user can manipulate view to be rotated and zoomed.
-Mathematic Graph
GFX 2.0 also can be used to display mathematic equation graph in 2D and 3D. User can analyze the equation shape or specific point location.

Some checkpoint:
- Anyone know (book or web page) which tell about good camera management (interaction with the algorithm)?
- Anyone have a thought about nice 3D real world example?
- Any idea about nice 3d model file format? Such as Google Earth model file...

If you guys want to see the test page (sorry no camera rotation for Opera... I cant implement this...), you can see it in this page

Thanks very much! I really appreciate, if you provide suggestions, ideas or critics...

Categories: Dojotoolkit.org

New Realtime Demo! Very exciting!

Dojotoolkit.org - Thu, 06/26/2008 - 01:47

Hi dojoers,

There we go! A new demo page, it has realtime script execution, so you can play around with the library. Notice that, I put some predefined script already as example script... You can change it or do your own in custom script... The purpose of this demo page is to determine whether my API is good or not... Not forget to mention, I will post the class diagram for you to get an abstract idea about the API... Try your best not to see the source code... try to guess from the argument parameter name... I am sorry I cant provide full HTML documentation right now since I will do it later on this project lifetime...



Please go to this to see the demo page and this to see the class diagram...



I would really appreciate if you give some comments, suggestions, or critics... Thanks!

Categories: Dojotoolkit.org

animation.reverse()

Dojotoolkit.org - Wed, 06/25/2008 - 21:17

I've been playing around with the idea of a user-friendly way to make a toggle-able animation, meaning the user creates a single animation object, and when that object is played, the animation either plays forward or backward, depending on the animated node's current position or animation status. If the animation is played while it's already running, it would stop and then play in reverse from the current position.

I tried a few different methods, but they all were unsuccessful or unreasonable one way or another. After this experimentation I realized that the best solution would be to add a reverse function to _Animation that would basically stop the animation if running and then play in reverse.

Categories: Dojotoolkit.org

d-rails progress, all quiet on the western front

Dojotoolkit.org - Wed, 06/25/2008 - 03:33

Not much to report this week as far as actual commits go. Been working on grokking rails' JavaScriptGenerator, JavaScriptHelper, and PrototypeHelper. I'm hoping to have a dojoified replacement for the aforementioned done by next week. I'm working on rewriting the unit tests from rails to their dojo equivalents right now, then moving on to the implementation. Stay tuned for updates.

Categories: Dojotoolkit.org

Delay in markup previews project

Dojotoolkit.org - Sun, 06/22/2008 - 19:25

There was a delay in my project, I didn't do much last week - there were
final exams in the university and I had to prepare well. Now, when I finally
finished this term, I can concentrate on the project and be productive.

There were updates on the code since my last blog post.
I added a simple implementation of grouped tokens handling. It can be used
for the cases when you need to treat a set of equal tokens, which go one after
another, as a one big separate token.

For example, it can be used for list processing. Here is a simple list in
Markdown format:

* this is
* a bulleted
* list

Each line is treated as a list item (so it can be translated to <li>
html tag), but all three lines grouped together can be treated as a whole list
and can be translated to <ul> tag.

You can test how it works here: grouped tokens test.

David gave me good advices on how should I rewrite some parts of code and
how it should work. And while inspecting the code I wrote David added a simple
definition of Mediawiki syntax. You can try it here: languages test.

Next week I plan to finish a parser and start developing of token-processing
functions so I can have a simple working prototype of Markdown parser to
the end of next week.

Categories: Dojotoolkit.org

Bridge of Floss

Dojotoolkit.org - Sun, 06/22/2008 - 15:41

Wow, it's been two weeks since my last blog. I'll be sure to update this regularly from now on.

I've been experimenting with a method to solve the "stale values" bug in sizeTo but when I realized that the goal of my project is to provide a "toolset," not a bug fix, I decided to forget about trying to solve the bug in dojox.fx and focus on cranking out new animations that handle interruptions and dynamic initial values. Instead of using the defective sizeTo, I'm using animateProperty.

In addition to a set of animation presets, I was considering improving the Toggler class so animations move at a consistent rate when interrupted with a toggle.

Categories: Dojotoolkit.org

d-rails progress, implementing dojo.fx helpers

Dojotoolkit.org - Wed, 06/18/2008 - 20:53

So this past week I've been working on a new data flow for our d-rails helpers in rails. I've implemented most of the dojo.fx functionality with this new flow, since it's a relatively small subset of functionality that would give me a pretty good idea if this was going to work well or not.

So let's start.

I ran across this page while researching dojo.fx, http://mzacher.de/sandbox/dojo.html , and while it's based on an older version of dojo, it gave me a good goal to work toward. Since the effects that he used on that page are unavailable in the current release of dojo, I did a bit of a stripped down version which I'll show you now.

First we'll look at a snippet of the view file:

<div id="fadeout" class="box" onclick='<%= fade_out "fadeout"%>'>
        Fade out
</div>
               
<div id="highlight" class="box" onclick='<%= highlight "highlight", { :color => "#ffe761" }%>'>
        Highlight
</div>
               
<div id="slideby" class="box" onclick='<%= slide_by "slideby", { :top => 50, :left => 22 }%>'>
        Slide by (click again and again)
</div>

Pretty simple stuff here: 3 divs, each with a server-side generated onclick property. Each helper an element ID as it's first argument, and an options hash as its second.

Now lets look at how these helpers actually generate the code. Here's what the highlight helper looks like:

def highlight(element_id, options = {})
  dojo_require("dojox.fx")
  options[:node] = element_id
  dojo_fx_play("dojox.fx.highlight", options)
end

Also pretty simple so far, we're just adding element_id to the hash under the name node, and calling dojo_require (to ensure that we load the library when the page is rendered) and dojo_fx_play (which actually generates the code required).

Now it gets a little more complicated. Lets look at what dojo_require and dojo_fx_play are actually doing:

def dojo_require(module_name)
  @_dojo_requires ||= Set.new
  module_name.each { |m| @_dojo_requires.add(m) }
end

def dojo_fx_play(function_name, *args)
  dojo_function_call(function_name, *args) + ".play();"
end

def dojo_function_call(function_name, *args)
  out = function_name + "("
  args.each do |arg| 
    out << arg.to_json
    out << (args.last == arg ? ")" : ",")
  end
  out
end

So dojo_fx_play just calls dojo_function_call with the method name and args list. dojo_function_call just directly converts the args list to json and outputs a javascript statement. The advantage to this is that dojo developers don't need to learn a new vernacular of options to use the methods they've always had.

dojo_require on the other hand, just keeps a list of which modules have been require'd so far in an instance variable to be used later.

I'm guessing that right about now you're wondering why I'm bothering to do any of this at all. dojo HAS a dojo.require function, and all I'm really doing is converting dojo functions to ruby syntax. The magic here comes in final helper, which isn't actually referenced in the view I showed you earlier.

def dojo_script_tag
  out = ""
  unless @_dojo_requires.nil? 
    @_dojo_requires.each do |req|
    out << "dojo.require('#{req}');"
    end
  end
  javascript_tag(out)
end

dojo_script_tag is (usually) called in the template instead of the views themselves. It makes sure you have all the dojo.require's that you need, and wraps them up in a script tag. The reason this is somewhat magical is because of the way rails handles templates.

If you have a template file, let's call it template.rhtml, it will look something like this:
<head>
    <title>d-rails rocks!</title>
    <%= javascript_include_tag :defaults %>     
  </head>
  <body>
    <%= render :partial => 'shared/header'%>
    <%= yield %>
    <%= render :partial => 'shared/footer'%>
    <%= dojo_script_tag %>
  </body>

The nice thing about templates is that they "compile" the files they include, before executing themselves. This means we can have lots of lots of helpers called from the header, footer, and main body, and not have to worry about keeping track of our dojo.require statements.

The code still felt a little incomplete though, so I wanted to try adding something else to make it a little more "dojo." Creating objects and running play() on them in the onclick handlers didn't seem like the best way to do this, so I came up with something a little bit different:

def dojo_fx_play(function_name, *args)
  new_dojo_object(dojo_function_call(function_name, *args)) + ".play();"
end

def new_dojo_object(constructor)
  @_dojo_objects ||= []
  name = @_dojo_objects.last.nil? ? "drails_object_000" : @_dojo_objects.last[:name].next
  @_dojo_objects << {:name => name, :constructor => constructor} 
  name    
end

def dojo_script_tag
  out = ""
  unless @_dojo_requires.nil? 
    @_dojo_requires.each do |req|
    out << "dojo.require('#{req}');"
    end
  end
  unless @_dojo_objects.nil? 
    @_dojo_objects.each do |obj|
    out << "var #{obj[:name]} = #{obj[:constructor]};"
    end
  end
  javascript_tag(out)
end

Now we can re-use the objects we've created. dojo_fx_play calls new_dojo_object, passing in what dojo_function_call returns, which adds it to the registry. new_dojo_object returns the name of the object after it's placed in the registry, which gets passed up the chain as "objectName.play()" for the onclick handlers. Finally, dojo_script_tag completes the circle by writing the object definitions in the same script tag as all the dojo.requires.

Of course there are several downfalls particular to this implementation.

  • Can't name your own javascript objects (yet)
  • I'm probably rewriting at least *some* functionality that rails already has. (dojo_function_call strikes me as very probable)

At the same time though, I think this is a good direction for things to be going. As always, I'd love to hear your thoughts, critiques, suggestions, etc.

Categories: Dojotoolkit.org

What's going on in dnd-form-editor land?

Dojotoolkit.org - Wed, 06/18/2008 - 02:25
Demo

I'm pretty happy with how the drag and drop is turning out. I have a demo that you can play with, dragging dijit names to create real form objects. The basic functionality is in place, and I can iterate on this for the rest of the summer to turn it into something usable. If you're interested, you can check out the code with:

svn co http://svn.dojotoolkit.org/soc/2008/dndforms_jbalogh soc

Put the soc directory at the same level as dojo and dijit.

Duplicate source items

The sitepen blog was really helpful in working out my final dnd troubles. I was suffering from the problem outlined in the "Avoiding Duplicate Items" section: copyOnly is great for preventing item removal from a dojo.dnd.Source, but if you drop an item from that source onto itself, you get multiple copies of that item.

The fix for me was to create an around method that blocks a drop from the same source, along with setting the dnd manager's canDrop flag to false after every drop event.

Don't reinvent dojo

When I started creating dijits on the fly, I had a big array of objects, with the class, node type, and any extra parameters. For example, the object to create a TextBox with an input node:

{cls: dijit.form.TextBox, tag: "input", attrs: {type: "text"}}

First I would create the right type of dom node, add the correct attributes, and then pass in the node to create a new dijit. It was a lot of work, and completely unnecessary.

It turns out that each dijit does the right thing just given a div. The dijit._Templated classes disregard what you pass in, creating a new node according to the template. Other widgets apply their transformations to the div.

I'm learning to step back from the code, think about what I'm doing, and figure out which part of Dojo I'm trying to reimplement.

Where do we go from here?

I've had a bunch of encouraging comments so far (thanks!), and I was wondering how people are planning to use this project. What kind of app do you have, who will be creating the forms, how will the generated forms be used, etc.? I'll keep your comments in mind while I'm working on the rest of the project.

Categories: Dojotoolkit.org

Dojo Modules for AIM

Dojotoolkit.org - Mon, 06/16/2008 - 17:58

Do you want Dojo code for an AIM-based text IM client that runs in a web page? Something that can play buddy sounds?

My employer, AOL, just open-sourced some Dojo modules that include a wrapper for the Web AIM API and UI widgets for user presence, the buddy list and sending and receiving instant messages (IMs).

The modules are open source versions of the modules used by AOL Webmail, so they have history in a real product. The modules are designed for Dojo 1.1 and above.

The source for the BSD-licensed modules is hosted on Google Code, at the aimdojo project. The first release, 1.0.0 is available for download. You can also use the code directly from the AOL Content Delivery Network (CDN), saving you some bandwidth. Here are two examples that use the AOL CDN:

  • Simple.html: Just shows the simplest usage of the modules, using aim.ImPanel with the default options.
  • ResizableFloatWithHoverCard.html: Shows how to use aim.ImPanel inside other dijit widgets that allow the buddy list to be dragged and resized. Also shows configuration options for the HoverCard (the info card that shows up as you hover over buddy names).

If you have comments or questions, please visit the aimdojo Google Group.

Categories: Dojotoolkit.org

This week...

Dojotoolkit.org - Mon, 06/16/2008 - 02:16

Hi dojoers,

Last week is kind of researching week for me... since a lot of things came to me... From interview with Google Sydney (I am applying to work with Google) till "wet week" (people from NSW, AU should know this... Last week was raining all the time)... What have I been researching is what is the best data structure to support the 3d environment graphic? Especially for scene management (such as BSP, Octal, and soon) I also researching for best math calculation to boost the performance... Anyone know about camera management? At the moment, my camera is quite a bit suck... I would like to know more about n-DOF (Degree of Freedom)... If anyone has information about those, I would really appreciate if you can share a little bit to me... Ah! Lately, all sudden my head full of ideas... I just posted a project idea into forum and contributor mailing list... It is about including sound support into DOJO (If you interested go link)...

Categories: Dojotoolkit.org

Continuation with charts..

Dojotoolkit.org - Mon, 06/09/2008 - 16:52

It hasn't been the most productive week for me. I've been exploring methods and ways to implement bullet chart. Also I'm doing some final touches on the candle plot.

Also I had lot of my time wasted bcoz I wanted to know how to put better blog posts :). It's really weird but actually I'm little unconfortable with blogs :(. Anyway I was able to get over with it to an extent in last few days.
If you are like me you would like this article http://betterexplained.com/articles/build-a-site-you-and-your-readers-wi....
Actually whole site was quite good. Anyway I'm back on track to develop bullet chart.. Hope to have something solid soon..

Categories: Dojotoolkit.org

Testing page

Dojotoolkit.org - Mon, 06/09/2008 - 08:11

Hi,

This week for my project is about user-usability. Thinking about how to make user uses the library easily... It is hard to think API for creating render object because there are many things that need to be covered (color, transformation, what shape n soon).

The creating object API is kind a bit hacky n hand waving (only createBox with a lot of assumption), it needs to be expanded for more flexibility. I also want to show small demonstration for what I have been doing so far, demonstrating with showing API is the best way to do, unfortunately, no API documentation at the moment... So what I can show to you at the moment is test page with sort of covering 60% API that I want to bring to user... Please go to the test page to see the demonstration. Note that, it is necessary to have Firefox 3.0 Beta 1 installed with proper Canvas3D extension (see the link in the page). Please give comment or suggestion... Thanks n have fun!

Categories: Dojotoolkit.org

Markup previews project: basic parser implemented

Dojotoolkit.org - Sun, 06/08/2008 - 18:28

This week I was working on a parser implementation and made some progress.

The parser I implemented consists of language definition part (where all tokens are defined), function definitions which process a particular token and a scanner that processes text, detects tokens and applies these functions.

To define a new token you need to add a new entry to tokens array in a language definition part, eg:

tokens: [
    // token can be defined using "start" and "end" regexps
    { start: '\\[', end: '\\]',
      mode: 'test',
      token: dojox.markup.TestToken
    },
    // or, for simpler cases, it can be defined using "regex"
    { regex: '[-A-Za-z0-9_\\.\\, ]*',
      mode: 'text',
      token: dojox.markup.TextToken
    },
    ...
]

For now scanner can process nested tokens and can process more complex cases, like token definitions with equal "start" and "end" or two tokens with equal "start" and different "end", etc

For now it can't:

  • process wrong nested tokens (eg {some [text}] )
  • it doesn't check the "allowed_children" property (which is used to define which tokens can be inside a particular token)
  • if anything goes wrong or it cant detect any token the error is generated

You can play with it here: soc week#02 dojox.markup tests.

Your comments are welcome.

Categories: Dojotoolkit.org

d-rails progress... testing 1, 2, 3.

Dojotoolkit.org - Wed, 06/04/2008 - 22:38

Ahh, it feels good to come back from a much-needed week long vacation following final exams. I know you all have been wondering what I've been up to, aside from enjoying my time in the sun and drinking margaritas. So for d-rails, the word of the week this week is testing.

Since we want to ensure d-rails is an easy drop in replacement, the behavior of the d-rails helper functions must be exactly the same as the existing helper functions which rely on prototype as their underlying library. The current rails distribution uses unit tests to test the helper functions, but these are only syntactic string comparisons which don't really test behavior in the same way that we need to test in d-rails. Here's an example of a test in prototype_helper_test.rb

def test_form_remote_tag_with_method
    assert_dom_equal %(A BUNCH OF RANDOM HTML/JS THAT DRUPAL IS DELETING FOR ME BUT YOU DON'T NEED TO SEE IT TO GET THE POINT),
    form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, :html => { :method => :put })
  end

As you can see, all this really does is compare the html/js spit out by the function call to a selected string. This type of testing is no doubt useful, as you want to ensure incremental changes you make don't cause your base test cases to fail. However, these tests are largely useless to us for testing that the behavior of the dojo helper overrides is equivalent to the default prototype implementation. What we really need is something that can compare the behavior of these in the browser.

I know a lot of you are yelling at the screen now, "Selenium! Selenium! Selenium!", which I agree is a good way to test real javascript behavior in real browsers. The problem I'm running into is not in selecting a test framework (I've pretty much settled on Selenium so far), but in actually getting the tests written.

I'll have to give some background on rails for you to appreciate the problems I'm encountering, so stick with me:

d-rails' current aim is to replace the built in prototype javascript helper methods in the ActionView::Helpers::PrototypeHelper module. A module in ruby is basically a mix-in for a class. To include a module in a class in ruby, you simply say include Qualified::ModuleName. In our current example, the prototype helper methods are instance methods applied to a controller in rails.

Controllers in rails process all incoming requests and spit out some output based on the request. Some data is shared between controllers and views, including the helper methods. So if we want to test this code in a real environment, we need to run these methods within the views or the controllers, and compare them. The problem comes when you want to have a d-rails prototype helper override method and a prototype helper method running in the same controller. (the reason we want something like this is so we can compare the two, side-by-side with selenium.)

I could go into a lot of details here, but the gist of it is that we can only have one module or the other loaded into the controller. More specifically, we can't switch modules in the midst of execution of a controller action (if we could, we could run link_to_remote with the default module, dynamically load the d-rails override module, the run link_to_remote again to get the dojo version of the function. Because of this, I've been trying to figure out a way selenium can observe the behavior of something on one page, load a new page and observe its behavior, then compare the two.

I know there is a lot of experience in the dev community with javascript testing tools, so maybe you guys can give me some advice.

There's also been something else that's bugging me about what we're doing now. I talked to a friend of mine, Brian Smith, who is part of the co-working space Downtown Cartel (which happens to be right down the street from me), and he was telling me about how javascript helpers in rails are evil.  The article makes a lot of good points, and I'm not entirely sure that helpers really fit the dojo paradigm. (maybe some of you can let me know after reading that article)

I also ran across this post written about a month ago about writing your rails views in javascript, and it seemed to vibe well with the way I've seen dojo being used in practice.  I'd really, really like to hear your thoughts on this.  I don't know the best ways to use dojo in practice, but I'd like for rails developers to be doing it the same way as everyone else.  The rails community is very receptive to Domain Specific Languages (DSLs), and writing a DSL to create views in ruby which leverages dojo and uses it in the way it's really meant to be used seems like a good idea.  Any and all feedback is more than welcome.

Categories: Dojotoolkit.org

5-minute Custom Build

Dojotoolkit.org - Wed, 06/04/2008 - 20:44

Working on the drag and drop form editor, I'm pulling in lots of modules: almost
everything in dijit.form, dojo.dnd (of course), and dijit.lang.functional &
dijit.lang.aspect because they're fun. Each module I require then pulls in
more files that it needs, so I was up to 131 web requests to load a single
page. The latency is acceptable on localhost, but it's absolutely terrible over
the network.

Pete Higgins has a couple of great screencasts over at dojocampus, but
it's kind of hard to refer back to a video, so here's my 5-minute build tutorial.
I'm assuming that your app code is in a directory next to dojo:

lib
|-- dijit
|-- dojo
|-- dojox
|-- mystuff
`-- util

First, find all the dojo modules that you're pulling in. cd to the root of
your app and run:

ack '^\s*(dojo.require[^;]*;)' -h --output='$1' | sort | uniq

This picks up all the dojo.require calls within your code and prints each one
out only once. The regex starts with \s* because I didn't want it finding
require's that I had commented out. I'm using ack, a replacement for grep that
uses perl regexes and is recursive by default. Using find and grep instead is
left as an exercise to the reader.

This prints the require's to the screen, but we want to put them all in a file for the
build system:

cat <<EOF > includes.js
dojo.provide("includes.js");
`ack '^\s*(dojo.require[^;]*;)' -h --output='$1' | sort | uniq`
EOF

I'm calling the file 'includes.js', and starting it with
dojo.provide("includes.js"); It looks like this:

dojo.provide("include.js");
dojo.require("dijit.form.Button");
dojo.require("dijit.form.CheckBox");
...

Source the includes file from your html page:

<script type="text/javascript" src="includes.js"></script>

This won't change anything right now, but it gets us prepared for later on.

Next we need to create a profile so the build system knows what to look for.
We'll call it my.profile.js:

dependencies = {
    layers: [
        {
            name: "../mystuff/includes.js",
            dependencies: [
                "mystuff.includes"
            ]
        }
    ],
    prefixes: [
        [ "dijit", "../dijit" ],
        [ "dojox", "../dojox" ],
        [ "mystuff", "../mystuff"   ]
    ]
}

We create one layer, with the name ../mystuff/includes.js. The path is relative to
the dojo directory, so the build system will put the compressed file in the same
place the includes file currently resides.

The only dependency for this layer is includes.js, which we created earlier.
It's full of more dojo.require dependencies that the build system will trace
for us.

The prefixes array tells the build system what directories we want to include
in our build version. These directories will be copied over to the build site.
You need to list any modules that you use, even if they're not directly
referenced in a layer. See the dojobook for more info.

Now we're ready to start building. cd to util/buildscripts, where you'll
find a bunch of different build scripts. We want to use build.sh. The
incantation is

./build.sh profileFile=/path/to/my.profile.js action=release \
           cssOptimize=comments optimize=shrinkSafe

Give profileFile the correct path to the profile created above, and leave the
rest of the parameters as is. They tell the build system to crank the
optimizations up to 11, removing comments, newlines, spaces, and turning on
shrinkSafe.

After a bit of churning, you'll have a shiny compressed version ready to stream
over the wires. My transfer size was cut by 56% (down to 9 requests), reducing
browser latency and making my app much more responsive.

Categories: Dojotoolkit.org
Syndicate content