blob: 4dbb705f809c4d21f76b607e4fb5db7f40a4dcec [file] [log] [blame]
#summary Proposal about Javascript refactoring
#labels Importance-Deprecated,Phase-Implementation,Contents-Draft
*Warning*: this is a proposal, and references code not yet pushed in the main repository. Current scripts and tools can be found on the [http://bitbucket.org/dhans/statistic-module-for-melange/ statistics GSoC branch], the following are links to provisional refactored code in [http://bitbucket.org/dhans/statistic-module-for-melange/src/tip/app/soc/content/js/melange.js melange.js] and [http://bitbucket.org/dhans/statistic-module-for-melange/src/tip/app/soc/content/js/melange.graph.js melange.graph.js]
<wiki:toc max_depth="2" />
=Introduction=
With more Javascript code being written and deployed, global namespace pollution is going to be a risk. So, we have two options: handle Java-like packages and dependencies between modules with projects like [http://code.google.com/p/jingo/ Jingo] or keep Python to handle all this stuff, just giving it the potential to handle dependencies.
=Tools=
==jsLint==
To run jsLint and check melange.js and melange.graph.js files, you need java installed in your local computer, just run
{{{
./jslint.sh
}}}
in {{{ scripts/ }}} directory.
The check is based on a slightly modified source of [http://www.jslint.com/rhino/index.html jsLint rhino version].
Following the defaults:
{{{
bitwise:false,
eqeqeq:true,
immed:true,
laxbreak:false,
newcap:false,
nomen:false,
onevar:false,
plusplus:false,
regexp:false,
browser:true,
undef:true,
white:true,
indent:2,
predef:['window','jQuery','google']
}}}
In practice:
* check for use of == and != (always use === and !==)
* check if immediate function calling are surrounded by parens
* disallow uncorrect breaking of lines
* assumes a browser
* prevent undefined variables
* check whitespaces before an anonymous function calling
* check if there are 2 whitespaces per indentation
* ignores {{{ window }}}, {{{ jQuery }}} and {{{ google }}} being global variables
* do not tolerate use of {{{ eval }}} statement
* do not tolerate unfiltered {{{ for...in }}} statements
If you want to check your code, copying and pasting in the [http://www.jslint.com/ online version of jsLint] (you will receive more useful infos as output), set the following [http://www.jslint.com/#options jsLint options]:
* Strict white space
* Assume a browser
* Disallow undefined variables
* Disallow {{{ == }}} and {{{ != }}}
* Require parens around immediate invocation
* Strict white space indentation: set it to *2*
==jsUnit==
Provisional tests for [http://bitbucket.org/dhans/statistic-module-for-melange/src/tip/app/soc/content/js/melange.js melange.js] and [http://bitbucket.org/dhans/statistic-module-for-melange/src/tip/app/soc/content/js/melange.graph.js melange.graph.js] can be found in {{{ tests/javascript/melange.tests.html }}}, [http://bitbucket.org/dhans/statistic-module-for-melange/src/tip/tests/javascript/melange.tests.html source code for tests in the repository can be found here].
To run jsUnit, you need to point your browser to this file:
{{{ ./thirdparty/jsunit/testRunner.html }}}
In the input line that will be shown, insert the path (URL style) of
{{{ ./tests/javascript/melangeTestSuite.html }}}
starting from your root directory.
Then you just need to click "Run", and it will run the test against the code. Fill free to set "Test level" to "debug (highest)" to see more details.
==jsCoverage==
To work, jsCoverage needs to modify the source code of the scripts to "instrument" it. As the code will be modified and copied to another directory, also tests that points to the former code needs to be redirected to point to the instrumented code. This could be avoided by moving the original code to another directory first, but, at the moment, it just keeps things as they are.
So, to instrument the code and modify the [http://bitbucket.org/dhans/statistic-module-for-melange/src/tip/tests/javascript/melange.tests.html melange.tests.html file] just run
{{{
./jscoverage_on.sh
}}}
from {{{ ./scripts }}} directory.
It will create a {{{ ./app/soc/content/js_coverage }}} directory and will modify, as said, {{{ ./tests/javascript/melange.tests.html }}} file. It ignores, at the moment, {{{ slot-allocator-090320.js }}}, because it seems not to be compatible for some reasons.
Then you just need to run jsUnit as described above, and click on the "JSCoverage" button. In that way, you can see the code lines covered by the tests.
After this, you need to rollback the previous changes, by running
{{{
./jscoverage_off.sh
}}}
script from {{{ ./scripts }}} directory.
It will delete the {{{ ./app/soc/content/js_coverage }}} directory and rollback the changes in {{{ ./tests/javascript/melange.tests.html }}} file.
==JSDocToolkit==
JSDocToolkit is present under
{{{ ./thirdparty/jsdoctoolkit }}}
directory. To run it against the Javascript code, just run
{{{
./jsdoctoolkit.sh
}}}
from the {{{ ./scripts }}} directory.
It will generate a directory
{{{ ./app/soc/content/js/documentation }}}
and two subdirectories under it, called {{{ private }}} and {{{ public }}}, which contain documentation for developers and documentation for public API of the Javascript files. Documentation in {{{ public }}} directory will also ignore undocumented files, which can lead to incorrect output.
More info on _how_ to document Melange Javascript code when the refactoring will be on place.
==Shrinksafe==
Outputs of many javascript compressors have been tested, using this [http://compressorrater.thruhere.net/ online Javascript compressor rater]. Although [http://dean.edwards.name/packer/ Packer] seems to be more efficient, it seems that it can lead to unpredictable output in older browsers, so we might want to use [http://www.dojotoolkit.org/docs/shrinksafe Shrinksafe] to minify our code, as it seems more conservative.
To run shrinksafe, which is in {{{ ./thirdparty/shrinksafe }}} directory, just run
{{{
./shrinksafe.sh
}}}
from {{{ ./scripts }}} directory.
It will generate a
{{{ ./app/soc/content/js_min }}}
subdirectory, in which you can find all minified files, postfixed with a "min.js".
This is just a test to see if it would be of any use to us.
=Guidelines=
In any way, we need:
1. To separate Javascript code in *modules*, and use Javascript language features to _namespace correctly_ those modules.
2. To keep as much Javascript code as possible *outside* Django templates.
3. To put HTML strings *outside* Javascript code, eventually developing a little function to load those templates and then, for templating, something that emulates {{{ sprintf() }}} or begin to use [http://plugins.jquery.com/project/jquerytemplate jQuery Template plugin].
4. Use {{{ jQuery.noConflict() }}} (after loading any library/plugin) and giving jQuery a different namespace like {{{ $j }}} to avoid conflicts if we ever want to integrate other libraries ({{{ $ }}} namespace is very well overused)
The proposal is to create a {{{ melange }}} namespace and begin adding sub-namespace to it for every feature we need. We might want to add {{{ models }}}, {{{ logic }}} and {{{ templates }}} subdirectories to the {{{ content/js }}} as well, to keep an homogeneous structure with the python code.