>>> dojo.require("dojox.lang.functional")
>>> dojo.require("dojox.lang.functional.fold")
>>> df = dojox.lang.functional
>>> df.reduce([1,2,3], "+")
TypeError: a.hasNext is not a function
Oops, that was not what I expected, thanks to Alex’s help Firefox3 beta3 could be identified as the one who causes the problem. And I filed a bug there, so lets hope the next Firefox beta/version does it right.
Yesterday another one of my contributions found it’s way into dojo: dojox.widget.Rating. You can try out the always latest version online in the dojo archive. It’s quite a simple form widget, that allows you to click a star for rating an item. The number of stars and the styling can be adjusted via images and CSS.
If you want an even more flexible way to customize the stars you should look at what Tobi has to offer with his SVG generated stars, they come in many more flavors!
I know that already for a long time. And since using dojo I know it even better. And already for a couple of years I am always again coming across functional programming, but never got any deeper into it then using the basic things. But now there is a really juicy piece of fruit I will chew, thanks to Eugene Lazutkin who wrote this wonderful article on Functional JavaScript fun in Dojo. And he also describes what which JS version implements, and more important which browser provides what. Must read!
Thanks …
Ok, watch out for dojo accelerating and passing on the left … Shane O’Sullivan posted, already in december last year about the dojo demo engine. A great step forward and a way to document stuff much better, since you get examples and one tab further you see how it is coded.
It is still in development, but the future looks bright!
So, use all the resources you get …
Mayflower had invited me to join their Barcamp last weekend - and it was awesome. Thank you a lot!!!
We had been a crowd of about 40 people all hacking all day long until deep at night, it was a great atmosphere and some very interesting projects had been made. I am sure some things will come up on the Mayflower blog soon, just keep watching!
I was mainly working on integrating the dojo.grid into the next version of Phprojekt and doing some ground work for a very flexible structure. And I have learned a lot more about dojo again. It’s just great!
Besides that I was advocating a lot for Python and Django especially :-), I just can’t hold back. But it’s hard to convert anyone there, since Mayflower is the biggest and best PHP service provider in Germany and the people there are really good in what they are doing! Though one came up to me and said “thank you for putting the Python book on the table” (which I did a while ago in the Mayflower office, just for fun).
Thanks again and hopefully see you soon again.
[UPDATE] The link to the sourcecode now points to the dojango implementation, the dpaste one is gone.
Just in case someone is using json_encode()I wrote a while ago, I have updated the function due to updates in the latest Django dev version. Find the source here.
I have solved two problems here. One is that now lazy strings are used all over in Django, which this updates handles and detecting a list and a dictionary stumbled on subclasses of them.
I guess by now everyone knows that the dojo version 1.0 had been released yesterday. I will closely follow the dojo development, since I think this is the most promising JavaScript framework out there.
Let’s hack on …
It was especially interesting to hear one thing that I also found out in my current project, it was “do DOM manipulation off-DOM”. Which means if you are doing some “heavy” DOM manipulation you should ie. copy the DOM element into an absolute positioned element (so that it doesn’t effect all the other elements that are floating around it) and manipulate it there. What I did in this case, was just simply setting visibility to hidden, so I can manipulate and evaluate all the parameters (such as layer size, position, etc. mostly using dojo.corrds()) and when done calculating I simply apply it to the original element. In our case we were resizing fonts to best fit in a box. And it made a noteable difference in performance to make the font size manipulation off-DOM.
Found via Alex’s blog entry on the dojo page, thanks.
First things first, if your project allows you to migrate to 0.9 (you got the time to do it) - do it! It’s worth all the sweat and it might cost you some.
I have converted a mid-size project from dojo 0.4 to 0.9 and it took longer than I thought, but also because I had to collect all the info from multiple places, so I will try to share what I discovered or collected and hoepfully make it easier to migrate. Good luck!
If you come across more changes that match somewhere in the list just add them to the comments, I will try to incorporate them.
Namespaces
Some functions have changed their namespaces. Most common functions have moved to dojo.* namespace to simply be quickly reachable. Simply do a console.dir(dojo) on the FireBug console, which lists all the functions that are located in the dojo.* namespace.
I found those changes:
Some functions disappeared dojo.lang.isUndefined() disappeared, I didnt find the reasoning anywhere yet. If you have no deeply nested objects you try to check, a function isUndefined() will work well I created one for my project. If you don’t like that I guess you have to replace all calls with typeof varName == "undefined".
dojo.lang.isNumber() disappeared too. My solution: function isNumeric(v) {return dojo.number.format(v)!==null};.
dojo.html.getPadding() was removed and seems to have become dojo.style(el, "paddingLeft"), dojo.style(el, "paddingRight"), etc. and that looks reasonable, it only gets the data you really need not all the paddings though you would have needed only one.
dojo.html.getScroll() is gone, the hack I use is dojo._docScroll() which does return the data as I need them, but it looks very private :-(.
dojo.dom.removeNode(el) was removed since the same can easily be achieved el.parentNode.removeChild(el), though removeNode() was pretty convinient, but not really necessary. Another intelligent move.
dojo.string.escape() is gone too. I just copied the old 0.4 function (dojo.string.escapeXml() see here for the source) into my local project namespace, I didnt find a replacement in dojo0.9 yet :-(. Probably also a simple thing like the removeNode thing, but I don’t know yet.
Important function changes dojo.html.toCoordinateObject() was renamed to dojo.coords() which is a good move, since it was way too long. It now returns an object with the keys: w,h,t,l (width, height, top, left). Much more efficient.
this._inherited() is not a function anymore, but I guess I was one of the few who used it directly though I shouldn’t. Now call this.inherited("funcName", arguments).
I think that only due to a bug or missing implementation I used to use _inherited() now it seems to be fixed and as it is supposed to be. But:inherited() can only be called for the same function as the callee … strange, so we have to use className.functionName.apply(this, arguments) and that is one thing that really sucks, since you hard code the className in the class … I hope that will change.
dojo.fx.html.wipeOut(el, 1000, null, onEnd) changes to this dojo.fx.wipeOut({node:el, duration:1000, easing:null, onEnd:onEnd}).
For all the properties see the dojo._Animation object’s properties are all you can pass to the wipe-method.
Widget stuff djConfig.searchIds forget about them!
Alex Russel told me in IRC
[12:35] cain: what is the replacement for “djConfig.searchIds” ?
[12:35] slightlyoff: cain: there isn’t one
[12:35] cain: how do i add ids to be rendered as widgets?
[12:35] slightlyoff: cain: there’s only a larger toggle (parseOnLoad)
[12:35] slightlyoff: cain: or you can run the parser yourself on a smaller subtree
[12:35] slightlyoff: cain: but in 0.9, the parser is much much much faster
So all you need to do is put djConfig.parseOnLoad=true at the beginning of your page and all widgets will be found. But be careful you have to manually dojo.require all the widget classes, iirc it was done automatically in 0.4. The porting guide says:
you must require the Dojo parser along with any widgets referenced, and enable a page scan using the “parseOnLoad” setting
that sucks, for the parser could easily find out which class/file to load, now i have to handish require things.
In place of dojo.widget.createWidget(), simply use the Javascript “new” constructor. I.e. var dialog = new dijit.Dialog(params).
Replace all by . The use of namespaces for creating widgets is straightforward now, in 0.4 it was strange. Great.
When building your own widgets you surely used the following dojo.uri.moduleUri that has become dojo.moduleUrl.
dijit.form.Form.getValues() is currently ignoring all fields inside the form if they are not widgets :-(, in 0.4 it didn’t.
dojo.widget.ComboBox is now dijit.form.ComboBox remotely loaded data are now realized via the dojo.data API. Before you simply specified a dataUrl attribute now that requires a dojo.data-store. And if you have a huge set of data on the server that you actually want to use the ComboBox to filter on, you will need this patch!
Replace dojo.widget.Form not with dijit.form.Form, but don’t make it a widget and use dojo.formToObject() instead, its much more efficient and explicit.
dojo.widget.Editor2 has become dijit.Editor, the toolbar config is much easier now, it used to be in an external file, now it’s as simple as that:
data in here
There is a problem loading it into a hidden layer, see this ticket there is work on the way see this comment.
Other stuff
In 0.4 it was not such a trivial task to make dojo render widgets that were in a chunk of HTML, that was loaded via AJAX. Now parsing a HTML chunk and render widgets in there simply is a call to dojo.parser.parse(node).
For most uses dojo.io.bind() has become dojo.xhrPost()/dojo.xhrGet() and the return data have been extended quite a bit.
If you have a form, that is a dijit.form.Form widget and you have some extra attributes, that the widget doesnt support by default in there, as i.e. “action” they will be kicked out, I used the following patch http://trac.dojotoolkit.org/ticket/4392 to have them added again. But there seems to be changes going on in this area, there is some attributeMap added, but I am not sure if this is the way and if that stays.
In the bootstrap.js i found the following comment:
Refer to ‘dojo.global’ rather than referring to window to ensure your code runs correctly in contexts other than web browsers (eg: Rhino on a server).
That means (and is also practiced in dojo) dont access “window” directly anymore but via “dojo.global” to me that sounds like it might make a lot of sense to simplify testing outside the browser, but I need to see that in action somehow.
Dojo is going the very efficient and elegant way of using one function as setter and getter in many places, the setter looks like this: dojo.cookie("name", value, {param:1, ... });
or the getter, which is the same function(!) is simple as that var value = dojo.cookie("name");
This makes the API so much simpler, the code cleaner and simply simpler. Very handy.
That’s just a plain list of what I have found and remembered to write down. hth
Sometimes when you want to do something right and you are lacking the tools you write them (but very often I don’t ), but in the case of doctests for dojo I saw the need. This time I took the time to write a doctest-class for dojo. It is currently only a ticket in the dojo trac, but some feedback looks pretty promising.
I saw the Ian Bicking had already once written a doctest module, but after skimming over it and thinking about the task, I decided to write it from scratch and a pure dojo fit, since it surely is not much work (as it also turned out, which is a rare case).
I knew the doctests module from the Python, where it obviously also comes from. In the beginning I found doctests ugly, those huge chunks of console-pastes inside my docstring. But after getting to know the value of the doctests by learning django’s newforms completely by a huge doctest I felt what they can do and that they can really help a lot.
Doctests just make you understand the code in the place it is written. If you (as I do) often look into the sources it can be really helpful to see a programming example right there inside the docstring of the class/method/function.
To make it short, I implemented this for JavaScript and it works nicely. I am actually developing a dojo.data-store but in order to do that I needed doctests, that’s where the need came from.
One of dojo’s base functions might look like this now:
dojo.trim = function(/*String*/ str){
// summary: trims whitespaces from both sides of the string
// description:
// This version of trim() was selected for inclusion into the base
// due to its compact size and relatively good performance (see Steven Levithan's blog:
// http://blog.stevenlevithan.com/archives/faster-trim-javascript).
// The fastest but longest version of this function is going to be placed in dojo.string.
// examples:
// >>> dojo.trim(" trim me ")
// "trim me"
// >>> dojo.trim("\t\ttrim me ")
// "trim me"
// >>> dojo.trim(" \t\t trim me \t ")
// "trim me"
// >>> dojo.trim("trim me")
// "trim me"
// >>> dojo.trim(" trim me")
// "trim me"
// >>> dojo.trim("trim me ")
// "trim me"
// >>> dojo.trim("")
// ""
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); // String
}
Run doctests
The trac ticket in dojo including the files and some info you can find here. You can download the patch right here.
First apply the patch, so that the dojox.testing.DocTest module is available.
This patch containing the doctest class is though to be a part of dojo, so it currently requires that you have a dojo module or a module that you registered with dojo (dojo.registerModulePath()).
To run i.e. the above shown doctest you just need to know in which file (module) it is (dojo._base.lang in this case) and type the following into your FireBug console:
>>> dojo.require("");
>>> var doctest = new dojox.testing.DocTest();
>>> doctest.run("dojo._base.lang");
It will then print out a line for each test in the FireBug console with the result and some info. In the before case it looks like this:
...
Test 44: OK: dojo.trim(" trim me ")
Test 45: OK: dojo.trim("\t\ttrim me ")
Test 46: OK: dojo.trim(" \t\t trim me \t ")
Test 47: OK: dojo.trim("trim me")
Test 48: OK: dojo.trim(" trim me")
Test 49: OK: dojo.trim("trim me ")
Test 50: OK: dojo.trim("")
Embed doctest
You can also embed the doctests into other test modules, i.e. if you are just want to add the doctests to your unittests and get them all as one result. You can simply check the property errors of your doctest instance:
>>> doctest.errors
[]
As you can see if there are no errors it’s length is 0.
You can see an example of how to do that here in the file data/tests/stores/QueryReadStore.js the first function testDocTests() runs the doctests of the module “dojox.data.QueryReadStore” and verifies that there are no errors.
I hope this will be useful to some people. Let me know if you have any kind of feedback, bugs or whatever. In the class itself you can see that I have also already thought of some things that need to be done/added to this class. Have fun doctesting …
There is not much to say, it is a saving! The screenshot below is a diff of a JavaScript file, that used to use dojo 0.4 and now uses the latest (0.9).
Just click it to see in full size.
The code on the left used dojo 0.4 on the right it’s dojo 0.9. You can see undoubtably that dojo 0.9 makes you write less code. Let’s pick out some things.
dojo.html.toCoordinateObject() has become dojo.coords() great, this always took a lot of time to write, but even better it needs to reference one object less and it has a much shorter name! The scroll is included, if you set the second parameter (includeScroll) to true you get the scroll already included, you can see in the old code I still did it by hand (though I think it existed there too).
And the padding is included too, you can see that I don’t do any padding calculation anymore additionally.
JSLint throws some very interesting errors. If your code is working and a bit mature you might not find many things that look very wrong at first sight. But after working a bit with JSLint and questioning some of the results it throws I can understand it more and more. Here are some explanations for what JSLint says and why.
All possible JSLint message can be found here.
‘{a}’ is undefined.
One that everyone will agree needs to be taken care of are the use of undefined variables. Sometimes it’s just a matter of case, i.e. I found some variable mailPart and mailpart where the later was found undefined and this might really bite you in the butt. So imho those are the first errors one needs to look out for and fix, they are serious.
Use ‘{a}’ to compare with ‘{b}’.
Use ‘===’ to compare with ‘null’.
Use ‘===’ to compare with ‘0′.
Use ‘===’ to compare with ”.
Use ‘===’ to compare with ‘true’.
Use ‘===’ to compare with ‘false’.
At first sight you might say “Why?”. But after playing a bit with Firebug and trying some things I found out why this makes sense. The values that you get the warnings for are not save to compare with ==. Just take out Firebug and try out some stuff:
>>> "" == 0
true
>>> "" === 0
false
>>> null == undefined
true
>>> null === undefined
false
>>> true == 1
true
>>> true === 1
false
You can see that there are some values that equal though they are not the same.
There is too much room for errors! Just imagine expecting a parameter in a function and you want to check it for being null, but the input actually (caused by some previous error) is undefined, if you compared using == then you if-statement would evaluate to true, which is not what you wanted here. And this might start the chain of errors that cost time to debug.
So make sure you really get what you expect and use === for comparing the values: 0, null, undefined, "", true and false!
Missing radix parameter.
This message is given when you are using parseInt() without the second parameter radix. This might cause a problem when the variable passed to parseInt() starts with a 0, which makes JavaScript interpret the value as an octal number. Or if the string even starts with “0x” parseInt() might come up with the idea to see a hexadecimal number.
>>> parseInt("8")
8
>>> parseInt("08")
0
>>> parseInt("010") // A juicy mistake, octal numbers.
8
>>> parseInt("0x10") // Probably rare, but possible, hexadecimals.
16
>>> parseInt("08", 10) // Prevent problems, use the radix.
8
>>> parseInt("010", 10)
10
And if the paramter passed to parseInt() is a variable that comes from some other place you can not be sure that the string does not start with a “0″. So using the radix might save a lot of headache.
Expected { and instead saw ‘{b}’.
This is not really a big thing, but it helps keeping clean code and prevents from future errors. Mostly this warning just occurs when you are writing a one-line-if-statement without the curly braces, i.e.
if (i===true)
callThis();
There is no potential error in running this code, but the optimizers, packers and the next developers touching the code will have a much easier time when you surround the function call with curly braces.
if (i===true) {
callThis();
}
You just don’t want the next developer who is correcting the statement and adding something to the execution block to undeliberatly forget the curly braces and wonder why his code doesn’t work as expected.
if (i===true)
callThis();
andCallThis();
That piece of code looks good from far, but look close (not always you have the time to do so) and you see that the indentions makes you think there are two function calls inside the if-block, but in reality there aren’t since the curly braces had been forgotten. Avoid those problems by putting them, right from the start.
This seems like a no-brainer of for dummies, but I have seen error arising from that!
Actually I wanted to list a couple more warnings and explain them, but the time … you know. I hope to get around to do some more soon. Meanwhile have fun getting your source code cleaner …
Yesterday I had to get JSLint up an running to check some code and improve the code quality. Since setting it up, getting it running and configuring JSLint is not really a piece of cake I thought I might share the steps so for those interested it goes faster than for me :-).
Overview
JSLint is available as an online version, where you can paste your source code on a page and have it analyzed. This analyzing takes place locally, so there is no source code being sent to the server!
JSLint is also available in full source code.
But working locally it only really makes sense to have JSLint installed on your maschine. And therefore you need Rhino to run locally and that is what brings the fun :-).
Setup Rhino
Check out Rhino first from the mozilla cvs (detailed description). The short version is simply: cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co mozilla/js/rhino
For building Rhino be sure to have Ant installed and go into the directory and run ant cd mozilla/js/rhino
ant compile
That gave me a lot of deprecated warnings, but I guess that is only because I have the JRE1.5 running and Rhino usually uses 1.4 afaik. Now your build hopefully finished with “BUILD SUCCESSFUL”.
Now Rhino should be ready to go.
Run JSLint
To make JSLint work locally you need to download jslint.js that we will execute using Rhino.
Ant generates the class files (the compiled java files) into the directory build/classes, so you now need to go there in order to run the Rhino.
It’s easiest when you simply save jslint.js in the same directory too.
Running jslint now is as easy as
cd build/classes
java org.mozilla.javascript.tools.shell.Main jslint.js mypath/and/file.js
This assumes that you have jslint.js in the current directory (mozilla/js/rhino).
If you now get lines like the following:
Lint at line 55 character 2: Missing semicolon.
}
then you got JSLint running.
Now it needs tweaking to get most our of it.
Configure JSLint
All the reasoning for using JSLint and some hints how to write good code can be found on the JSLint page. All the options you can use to tweak JSLint are also found on that page, pretty far down in the section “Options”.
You apply those options by simply writing them (at the top) of yourfile.js, I for example used the following options:
/*jslint nomen:false, evil:false, browser:true, laxbreak:true, passfail:false, adsafe:true, undef:true */
/*extern dojo */
There are a couple more options. Those used here are for:
nomen:false - does not check the variable names, otherwise it would mourn about variable names like “this._privateProp”, it’s the underscore that JSLint doesn’t like, for whatever reason
evil:false - warns about all evals which are evil
browser:true - the standard browser globals should be predefined
laxbreak:true - does NOT check line breaks, JSLint seems to be pretty picky otherwise and it’s rules don’t always fit what we expect
passfail:false - this doesn’t let the scan stop on the first error
adsafe:true - I really don’t know may be it checks that your JS will also work with advertisiing embedded in your site …
Tweak jslint.js
There is just one annoying thing, it’s that JSLint stops after 50 messages, which is not what I want. I just run JSLint put the results in a file and parse through the file to find the really important things first (that might need some tool :-)).
Therefore you need to modify the jslint.js. In line 17 you will find
if(warnings===50){quit("Too many errors.",l,ch);}
change this to
if(warnings===100000){quit("Too many errors.",l,ch);} .
At least that is what I did, now it dumps me all the errors (well at least a 100,000 which I hopefully never reach).
Finally
As you can see it is all pretty simple, the tricky part imho was to find the information one needs to get all out of the tool. And that just consumes a lot of time, so I hope this helps all those interested. Have fun, and let me know if I missed a point …
Yesterday was such a cool day, it was impossible to screw it after Minh had told me that I can simply use
debugger;
inside my JavaScript code and the browser stops at this point and opens the debugger, the Firefox (including Firebug of course) and the IE of course too.
That is such an awesome discovery :-). Especially when using a project that uses a couple hundred JS files and where finding the right file and setting a breakpoint can really be pain in some place.
Happy hacking …
Your royal highness doesn’t like you finding royal places in the royal UK *cough*. How dumb is that. Therefore use a way around, as described very extensively on Tom Anthony’s blog in the article Geocoding UK Postcodes with Google Map API. Thanks Tom!
Thanks to this blog post I got it running, though I was not less than five hours hunting. Gee, I wish there was a tool which would let me find the shortcuts to the solution of any problem :-).
After we had followed all the install guides and double and triple checked everything those were the tweaks we needed to do to get it really running:
Edit OpenFire properties - Log into OpenFire as an administrator and add two server properties:
xmpp.httpbind.client.requests.polling = 0
xmpp.httpbind.client.requests.wait = 10
These are required because of a bug where JWChat won’t respect the polling values given to it by the server.
Dojo’s class construction kit is a nice thing, once you know how to use it. What I especially like about it, is that it even allows for multiple inheritance!
Just a short example, I have a base class for a page (as you used here). If the page also contains forms then I also use the “myproject.form” class, that I can simply add to my page’s class via multiple inheritance, that is so neat! Like so:
There are situations when you are hunting a bug and you got the feeling that it actually is no real bug, it’s just a typo or something as simple, but you just can’t find it. So I better write that down so next time I am searching for this error message I will get the result right away. Those are the kind of errors that are just nasty but time consuming. Actually it’s a PTS bug, Programmer too stupid bug.
I have written a little class for my current page, nothing fancy and not really any substantial code in there. But somehow I still get this nasty error, that Firebug (btw a must have tool) shows as you can see in the image.
dojo.declare("myproject.page.ideas", myproject.page,
function(pageData) {
// initialize the class here right on it's instanciation
}, {
onPageLoaded:function() {
// Is being called by the parent class, when dojo.addOnLoad() hits.
}
});
var page = myproject.page.ideas({});
At some point you are getting blind looking at you code, and so it was here. The problem is very simple. I forgot the “new” before the class instantiation (let’s not discuss if it is a class, object, type, …).