changeset 195:48d35d049b19

$ hg merge core-javascript # into default, ready for ReadTheDocs
author Jonathan Fine <jfine@pytex.org>
date Mon, 13 Feb 2012 10:05:46 +0000
parents f6e1dca9ff21 (current diff) 77e87f1b5811 (diff)
children 4456cb0c4d7c
files source/inheritance.rst
diffstat 46 files changed, 3293 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Oct 19 11:45:25 2011 +0100
+++ b/.hgignore	Mon Feb 13 10:05:46 2012 +0000
@@ -3,6 +3,8 @@
 \#*
 *.orig
 *.pyc
+*.zip
+*.exe
 
 # Generated by LaTeX Beamer.
 *.aux
@@ -15,7 +17,6 @@
 *.vrb
 
 syntax:re
-
 ^local/
 ^build/
-
+core-javascript/_build/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/Makefile	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,139 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+	-rm -rf core-javascript-work.zip
+	zip -r core-javascript-work.zip core-javascript-work
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	-cp -r core-javascript-work/ $(BUILDDIR)/html/
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/CoreJavaScript.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/CoreJavaScript.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/CoreJavaScript"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/CoreJavaScript"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	make -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(ALLSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/arguments.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,21 @@
+Arguments
+=========
+
+This can be omitted at a first reading.  The main point here is that
+in JavaScript
+
+#. There is no checking for number and type of arguments.
+
+#. The arguments actually supplied are stored in a special variable,
+   called *arguments*.
+
+#. The value of *arguments* is almost, but not exactly, an array.
+
+
+Test code
+---------
+
+.. literalinclude:: /core-javascript-work/tutorial.js
+   :language: javascript
+   :start-after: start return_arguments
+   :end-before: end return_arguments
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/bind-is-transient.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,69 @@
+Bind is transient
+=================
+
+
+Test code
+---------
+
+Here's the test code for attribute bind.
+
+.. literalinclude:: /core-javascript-work/tutorial.js
+   :language: javascript
+   :start-after: start transient-bind
+   :end-before: end transient-bind
+
+
+Discussion
+----------
+
+We create an object that has a *return_this* method.  The outcome of
+calling *return_this* depends on how it is called.
+
+There's a logic in the test code that produces contradictory, or at
+least surprising, outcomes.
+
+From
+
+.. code-block: javascript
+
+   obj.return_this === return_this;
+   method_deferred === obj.return_this;
+   method_deferred === return_this;
+
+we would expect
+
+.. code-block: javascript
+
+   obj.return_this() === return_this();
+   method_deferred() === obj.return_this();
+   method_deferred() === return_this();
+
+But this means that in *obj.return_this()* the *obj* is not relevant.
+But JavaScript (or its designers) wanted objects to have methods, so
+they introduced a special rule.
+
+
+Explanation
+-----------
+
+JavaScript does not distinguish classes and instances.  Python, and
+perhaps other dynamic languages, does.  This allows Python to supply a
+bound method, which retains a reference to the object, when a function
+belonging to the class is called on an instance.
+
+Here's a Python (version 3) command line dialogue that illustrates
+this.
+
+>>> def method(): pass          # The function.
+...
+>>> class A: method = method    # The class.
+>>> A.method                    # Function from class.
+<function method at 0x15be518>
+>>> A.method is method          # Same as the original function.
+True
+>>> a = A()                     # Instance.
+>>> a.method                    # Bound method, not original function.
+<bound method A.method of <__main__.A object at 0x16b9d10>>
+
+The odd behaviour shown in the JavaScript test code is a consequence
+of JavaScript not distinguishing between classes and instances.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/closures.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,86 @@
+Closures
+========
+
+You'll see closures a lot in JavaScript.  The reasons for this are:
+
+#. In JavaScript, :doc:`bind-is-transient`.
+
+#. It is callback functions attached to DOM elements that respond to
+   events.
+
+#. Most code attaches callbacks to individual DOM elements (rather
+   than delegating to a parent element).
+
+
+Test code
+---------
+
+Here's the test code for closures.
+
+.. literalinclude:: /core-javascript-work/tutorial.js
+   :language: javascript
+   :start-after: start closures
+   :end-before: end closures
+
+
+Discussion
+----------
+
+The factory function creates two functions, *get* and *set*, which
+refer to the variable *value* of the factory function.  The *get*
+function returns the value of this variable, while the *set* function
+changes it.
+
+To test the factory function we create two get-set pairs.  We then
+test that each *set* operation changes the value return by its partner
+*get* operation.
+
+Finally, we test that the two pairs don't interfere with each other.
+
+
+Explanation
+-----------
+
+Objects continue to exist so long as a reference remains to them.
+When the last reference to an object is removed (or when the object is
+part of *cyclic garbage*) the object can be destroyed.  When the
+return value of a function is stored (say as the value of a variable)
+then this return value continues to exist.  Similarly, anything
+referred to by the return value continues to exist.
+
+Closures come about when the return value of a function is itself a
+function defined within the outer function (or contains references to
+such functions).
+
+Suppose the outer function returns an *inner function* (or in other
+words a function that is defined within the outer function).  Suppose
+also that the inner function uses a variable (or parameter) of the
+outer function.  In this situation the inner function holds a
+reference to the value of this variable.  The code in the inner
+function can read (or get) this value.  It can also write to this
+variable.
+
+One final point.  Each call of the outer function creates a new
+instantiation of the function variable.
+
+
+Exercises
+---------
+
+A programmer, perhaps in a hurry, misses out a *var* in the example
+above.  So now it reads:
+
+.. code-block:: javascript
+
+   var get_set_factory = function(){
+
+      value;   // Here's the missing *var*.
+
+
+#. Which tests to you expect to pass, and which to fail?
+
+#. Make this change and run the tests.  Which actually fail?
+
+#. Explain what is happening.
+
+#. What does this tell us about coding and testing?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/conf.py	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,262 @@
+# -*- coding: utf-8 -*-
+#
+# Core JavaScript documentation build configuration file, created by
+# sphinx-quickstart on Wed Oct 19 11:43:46 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Core JavaScript'
+copyright = u'2011, Jonathan Fine'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.0'
+# The full version, including alpha/beta/rc tags.
+release = '0.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'CoreJavaScriptdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'CoreJavaScript.tex', u'Core JavaScript Documentation',
+   u'Jonathan Fine', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+# Added at the end of the \documentclass[options]{...}.
+# 'english' added to keep Babel quiet.
+# http://groups.google.com/group/sphinx-dev/browse_thread/thread/ee301b14175ad5bb/c06c6600192a17da
+latex_elements = {
+    'classoptions': ',openany,english',
+}
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'corejavascript', u'Core JavaScript Documentation',
+     [u'Jonathan Fine'], 1)
+]
+
+
+# -- Options for Epub output ---------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'Core JavaScript'
+epub_author = u'Jonathan Fine'
+epub_publisher = u'Jonathan Fine'
+epub_copyright = u'2011, Jonathan Fine'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+#epub_exclude_files = []
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/answers/closure-exercises.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,205 @@
+var something;
+
+TEST('anon', function()
+{
+    var answer;
+
+    // start
+    answer = function(){
+        return 1;
+    };
+    // stop
+
+    assert( answer() ===  1 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(){
+
+        var answer;
+
+        // start
+        answer = function(){
+            return 1;
+        };
+        // stop
+
+        return answer;
+    };
+
+    var my_inner_function = outer_function();
+
+    assert( typeof my_inner_function === 'function' );
+    assert( my_inner_function() === 1 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(){
+
+        var answer;
+
+        // start
+        answer = function(){
+            return 1;
+        };
+        // stop
+
+        return answer;
+    };
+
+    assert( outer_function()() === 1 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(n){
+
+        var answer;
+
+        // start
+        answer = function(){
+            return n;
+        };
+        // stop
+
+        return answer;
+    };
+
+    assert( outer_function(1)() === 1 );
+    assert( outer_function(2)() === 2 );
+    assert( outer_function(3)() === 3 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(n){
+
+        // start
+        return function(){
+          return n;
+        };
+        // stop
+    };
+
+    assert( outer_function(1)() === 1 );
+    assert( outer_function(2)() === 2 );
+    assert( outer_function(3)() === 3 );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var get_value = function(){
+        return value;
+    };
+
+    something = 1;
+    assert( get_value() === something );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var set_value = function(n){
+        value = n;
+    };
+
+    set_value(2);
+    something = 2;
+    assert( value === something );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var get_value = function(){
+        return value;
+    };
+
+    var set_value = function(n){
+        value = n;
+    };
+
+    something = 1;
+    assert( get_value() === something );
+
+    set_value(2);
+    something = 2;
+    assert( get_value() === something );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var ddd = function(aaa, bbb){
+        return {
+            // start
+            aaa: aaa,
+            bbb: bbb
+            // stop
+            };
+    };
+
+    var obj = ddd(1, 2);
+
+    assert( obj.aaa === 1 );
+    assert( obj.bbb === 2 );
+
+});
+
+
+TEST('anon', function()
+{
+
+    var get_set_factory = function(){
+
+        // start
+        var value;
+
+        var get = function(){
+            return value;
+        };
+
+        var set = function(new_value){
+            value = new_value;
+        };
+        // stop
+
+        return {
+            get : get,
+            set : set
+        };
+    };
+
+    var tmp;
+    tmp = get_set_factory();
+    var get_a = tmp.get;
+    var set_a = tmp.set;
+
+    tmp = get_set_factory();
+    var get_b = tmp.get;
+    var set_b = tmp.set;
+
+
+    set_a('aaa');
+    assert( get_a() == 'aaa' );
+
+    set_b('bbb');
+    assert( get_b() == 'bbb' );
+
+    assert( get_a() == 'aaa' );
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/closure-exercises.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,168 @@
+var something;
+
+TEST('anon', function()
+{
+    var answer;
+
+    // Please write your answer here.
+
+    assert( answer() ===  1 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(){
+
+        var answer;
+
+        // Please write your answer here.
+
+        return answer;
+    };
+
+    var my_inner_function = outer_function();
+
+    assert( typeof my_inner_function === 'function' );
+    assert( my_inner_function() === 1 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(){
+
+        var answer;
+
+        // Please write your answer here.
+
+        return answer;
+    };
+
+    assert( outer_function()() === 1 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(n){
+
+        var answer;
+
+        // Please write your answer here.
+
+        return answer;
+    };
+
+    assert( outer_function(1)() === 1 );
+    assert( outer_function(2)() === 2 );
+    assert( outer_function(3)() === 3 );
+});
+
+
+TEST('anon', function()
+{
+    var outer_function = function(n){
+
+        // Please write your answer here.
+    };
+
+    assert( outer_function(1)() === 1 );
+    assert( outer_function(2)() === 2 );
+    assert( outer_function(3)() === 3 );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var get_value = function(){
+        return value;
+    };
+
+    assert( get_value() === something );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var set_value = function(n){
+        value = n;
+    };
+
+    set_value(2);
+    assert( value === something );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var get_value = function(){
+        return value;
+    };
+
+    var set_value = function(n){
+        value = n;
+    };
+
+    assert( get_value() === something );
+
+    set_value(2);
+    assert( get_value() === something );
+});
+
+
+TEST('anon', function()
+{
+    var value = 1;
+
+    var ddd = function(aaa, bbb){
+        return {
+            // Please write your answer here.
+            };
+    };
+
+    var obj = ddd(1, 2);
+
+    assert( obj.aaa === 1 );
+    assert( obj.bbb === 2 );
+
+});
+
+
+TEST('anon', function()
+{
+
+    var get_set_factory = function(){
+
+        // Please write your answer here.
+
+        return {
+            get : get,
+            set : set
+        };
+    };
+
+    var tmp;
+    tmp = get_set_factory();
+    var get_a = tmp.get;
+    var set_a = tmp.set;
+
+    tmp = get_set_factory();
+    var get_b = tmp.get;
+    var set_b = tmp.set;
+
+
+    set_a('aaa');
+    assert( get_a() == 'aaa' );
+
+    set_b('bbb');
+    assert( get_b() == 'bbb' );
+
+    assert( get_a() == 'aaa' );
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/counters.css	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,17 @@
+body {
+    background: #DDD;
+    font-family: sans-serif;
+}
+
+#example {
+    padding: 20px;
+}
+
+#example span {
+    padding: 10px;
+    margin: 10px;
+    border: 10px solid blue;
+    background: #DDF;
+    foreground: blue;
+    font-weight: bold;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/counters.html	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,18 @@
+<html>
+<head>
+<script src="library.js"></script>
+<script src="counters.js"></script>
+<link rel="stylesheet" type="text/css" href="counters.css" />
+<title>JS for Python: example: counters</title>
+</head>
+<body>
+<h1>Counters</h1>
+
+<p>Click on a counter to increment its value.</p>
+
+<div id="example">
+<p>This will disappear if JavaScript is working properly.</p>
+</div>
+
+<p>Return to documentation of <a href="../counters-example.html">Counters example</a>.</p>
+</body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/counters.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,79 @@
+(function()
+{
+    // Define a Counter class.
+    var counter = {};           // Prototype object for Counter.
+
+    counter.__init__ = function(name){
+
+        this.name = name;
+        this.count = 0;
+    };
+
+    counter.onclick = function(event){
+
+        this.count ++;
+    };
+
+    counter.html = function(){
+
+        return this.name + ' ' + this.count;
+    };
+
+    Counter = SimpleClass(counter);
+
+
+    // Make explicit use of global variables.
+    var global = (function(){return this;})();
+
+
+    // Interaction.
+    var onclick_factory = function(models){
+
+        var onclick = function(event){
+
+	    event = event || global.event; // For IE event handling.
+	    var target = event.target || event.srcElement;
+            var id = target.id;
+            if (id) {
+                var id_num = +id.slice(1);
+                var model = models[id_num];
+                model.onclick();
+                var html = model.html();
+                if (html){
+                    global.document.getElementById(id).innerHTML = html;
+                }
+            }
+        };
+        return onclick;
+    };
+
+
+    // Set up the web page.
+    global.onload = function(){
+
+        var models = [
+            Counter('apple'),
+            Counter('banana'),
+            Counter('cherry'),
+            Counter('date')
+        ];
+
+        var element = document.getElementById('example');
+
+        element.innerHTML = (
+            '<span id="a0">apple 0</span>'
+            + '<span id="a1">banana 0</span>'
+            + '<span id="a2">cherry 0</span>'
+            + '<span id="a3">date 0</span>'
+        );
+
+        element.onclick = onclick_factory(models);
+        element = undefined;    // Avoid IE memory leak.
+    };
+
+})();
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/demo_testtools.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,14 @@
+TEST('all-pass', function()
+{
+    assert( 2 + 2 === 4 );
+    assert( 'the ' + 'cat' === 'the cat');
+});
+
+
+TEST('2-4-fail', function()
+{
+    assert( true );
+    assert( false );
+    assert( 1 );
+    assert( 0 );
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/exercise-1.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,14 @@
+var AAA = (function (BBB)
+{
+    BBB.fff = function(ccc)
+    {
+        return {
+            ggg: function(ddd)
+            {
+                return BBB.hhh(ddd, ccc.iii());
+            }
+        };
+    };
+    return BBB;
+
+}(AAA || {}));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/exercise-2.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,11 @@
+var copy_attributes = function(tgt, src){
+
+    tgt.aaa = src.get_aaa();
+    tgt.bbb = src.get_bbb();
+    tgt.ccc = src.get_ccc();
+    tgt.ddd = src.get_ddd();
+    tgt.eee = src.get_eee();
+    tgt.fff = src.get_fff();
+    tgt.ggg = src.get_ggg();
+    tgt.hhh = src.get_hhh();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/library.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,25 @@
+// start create
+var create = function(parent){
+
+    var tmp = function(){};
+    tmp.prototype = parent;
+    var child = new tmp();
+
+    return child;
+};
+// end create
+
+
+// start SimpleClass
+var SimpleClass = function(prototype){
+
+    var cls = function(){
+
+        var instance = create(prototype);
+        instance.__init__.apply(instance, arguments);
+        return instance;
+    };
+
+    return cls;
+};
+// end SimpleClass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-1-a.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,15 @@
+var AAA = function ()
+{
+    var BBB = AAA || {};
+    BBB.fff = function(ccc)
+    {
+        return {
+            ggg: function(ddd)
+            {
+                return BBB.hhh(ddd, ccc.iii());
+            }
+        };
+    };
+    return BBB;
+
+}();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-1-b.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,5 @@
+var AAA = function ()
+{
+    var BBB = AAA || {};
+    return BBB;
+}();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-1-c.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,1 @@
+var AAA = AAA || {};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-1-d.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,11 @@
+var AAA = AAA || {};
+
+AAA.fff = function(ccc)
+{
+    return {
+        ggg: function(ddd)
+        {
+            return AAA.hhh(ddd, ccc.iii());
+        }
+    };
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-2-a.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,10 @@
+var copy_attributes = function(tgt, src){
+
+    var keys = ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg', 'hhh'];
+    var i;
+    var key;
+
+    for(i=0; i< keys.length; i++){
+        tgt[key] = src['get_' + key]();
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-2-b.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,11 @@
+var copy_attributes_factory = function(keys){
+
+    return function(src, tgt){
+        var i;
+        var key;
+
+        for(i=0; i< keys.length; i++){
+            tgt[key] = src['get_' + key]();
+        };
+    };
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-2-c.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,15 @@
+var Fields = function(keys){
+    this.keys = keys;
+};
+
+Fields.prototype = {
+    copy_attributes : function(src, tgt){
+
+        var keys = this.keys;
+        var i;
+
+        for(i=0; i< keys.length; i++){
+            tgt[key] = src['get_' + key]();
+        };
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/solution-2-d.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,23 @@
+// Rhino $ js -f library.js -f solution-2-d.js -
+
+var fields = {};
+
+fields.__init__ = function(keys){
+    this.keys = keys;
+};
+
+fields.copy_attributes = function(src, tgt){
+
+    var keys = this.keys;
+    var key;
+    var i;
+
+    for(i=0; i< keys.length; i++){
+        key = keys[i];
+        tgt[key] = src['get_' + key]();
+    };
+};
+
+var Fields = SimpleClass(fields);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/test_library.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,40 @@
+var telltail = 'global';
+
+var TEST = function(title, code){
+    print( 'Testing: ' + title );
+    code();
+};
+
+var assert = function(arg){
+    if(!arg){
+        ddt();
+    }
+};
+
+
+// start SimpleClass
+TEST('SimpleClass', function()
+{
+    var fruit = {};
+
+    fruit.__init__ = function(name, colour){
+
+        this.name = name;
+        this.colour = colour;
+    };
+
+    fruit.greet = function(){
+
+        return "Hello, I'm a " + this.color + " " + this.name + ".";
+    };
+
+    var Fruit = SimpleClass(fruit);
+
+    var bn = Fruit('banana', 'yellow');
+    var rc = Fruit('cherry', 'red');
+    var gs = Fruit('Granny Smith', 'green');
+
+    assert( bn.greet() === "Hello, I'm a undefined banana." );
+
+});
+// end SimpleClass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/testtools.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,39 @@
+var telltail = 'global';
+var _assertion_count = 0;
+
+// Define a global function 'log'.
+var log;
+if (this.hasOwnProperty('jsArguments')){
+
+    log = function(s){
+        print(s + '\n');
+    };
+} else {
+    log = print;
+}
+
+//
+var TEST = function(title, code){
+
+    var x;
+
+    log( 'Testing: ' + title );
+    _assertion_count = 0;
+
+    try {
+        code();
+    } catch (x) {
+        log('! Exception at ' + x.fileName +':' + x.lineNumber);
+        log('! [' + x.name + '] '  + x.message );
+    }
+
+};
+
+var assert = function(arg){
+    _assertion_count += 1;
+    if (!arg){
+        var msg = '! assert ' + _assertion_count + ' has failed';
+        log(msg);
+    }
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/core-javascript-work/tutorial.js	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,203 @@
+// [Rhino] $ js -f testtools.js -f tutorial.js
+// [JSDB] $ jsdb -load testtools.js -load tutorial.js
+
+// start warm-up
+TEST('warm-up', function()
+{
+    assert( '0' == 0 );
+    assert ( 0 == '' );
+    assert( '0' != '' );
+
+    var a = NaN;
+    assert( a != a );
+
+});
+// end warm-up
+
+
+// start closures
+TEST('closures', function()
+{
+    // A factory for creating get-set pairs.
+    var get_set_factory = function(){
+
+        var value;
+        var get = function(){
+            return value;
+        };
+        var set = function(new_value){
+            value = new_value;
+        };
+
+        return {
+            get: get,
+            set: set
+        };
+    };
+
+    // Create and unpack two get-set pairs.
+    var tmp;
+    tmp= get_set_factory();
+    var get_a = tmp.get;
+    var set_a = tmp.set;
+
+    tmp= get_set_factory();
+    var get_b = tmp.get;
+    var set_b = tmp.set;
+
+    // Test that both pairs work.
+    set_a(12);
+    assert( get_a() === 12 );
+
+    set_b(13);
+    assert( get_b() === 13 );
+
+    // Test that each pair has its own value.
+    assert( get_a() === 12 );
+
+});
+// end closures
+
+
+// start return_this
+TEST('return_this', function()
+{
+    var return_this = function(){
+        return this;
+    };
+
+    var default_this = return_this();
+    assert( default_this.telltail === 'global' );
+
+    var obj = {};
+    obj.return_this = return_this;
+    assert( obj.return_this === return_this );
+
+    assert( obj.return_this() === obj );
+    assert( obj['return_this']() === obj );
+
+    assert( return_this.call(obj) === obj );
+    assert( return_this.apply(obj) === obj );
+
+    assert( return_this.call(undefined).telltail === 'global' );
+    assert( return_this.apply(undefined).telltail === 'global' );
+
+});
+// end return_this
+
+
+// start transient-bind
+TEST('transient-bind', function()
+{
+    // Set up the test object.
+    var return_this = function(){
+        return this;
+    };
+    var obj = {
+        return_this : return_this
+    };
+    assert( obj.return_this === return_this );
+
+    // Deferring method call changes the outcome.
+    var method_deferred = obj.return_this;
+    assert( method_deferred ===  obj.return_this );
+    assert( method_deferred() !==  obj.return_this() );  // AAA
+
+    // The two outcomes, precisely stated.
+    assert( obj.return_this() === obj );
+    assert( method_deferred().telltail === 'global' );
+
+    // Another view on the matter.
+    assert( method_deferred === return_this );
+    assert( method_deferred() === return_this() );  // BBB
+
+});
+// end transient-bind
+
+
+// start millers-device
+TEST('millers-device', function()
+{
+    var array = [];
+    var obj = {};
+    var fn = function(){};
+
+    assert( typeof array === 'object' );
+    assert( '' + obj === '[object Object]' );
+
+    assert( obj.toString() === '[object Object]' );
+
+    var object_toString = obj.toString;
+
+    assert( object_toString.call(array) === '[object Array]' );
+    assert( object_toString.call(fn) === '[object Function]' );
+
+});
+// end millers-device
+
+
+// start return_arguments
+TEST('return_arguments', function()
+{
+    var return_arguments = function(){
+        return arguments;
+    };
+
+    var my_arguments = return_arguments(0, 1);
+
+    assert( my_arguments.length === 2 );
+
+    assert( my_arguments[0]  === 0 );
+    assert( my_arguments[1]  === 1 );
+
+    assert( '' + my_arguments === '[object Object]' );
+    assert( '' + [0, 1] === '0,1' );
+
+    var array_slice = [].slice;
+    var my_arguments_fixed = array_slice.call( my_arguments );
+
+    assert( '' + my_arguments_fixed === '0,1');
+
+    var obj = {};
+    assert( obj.toString.call( my_arguments_fixed ) === '[object Array]' );
+
+});
+// end return_arguments
+
+
+// start new-operator
+TEST('new-operator', function()
+{
+    // A 'traditional class'.  It records 'this' as a side effect.
+    var this_in_Fn;
+    var Fn = function(){
+        this_in_Fn = this;
+    };
+
+    // Call the 'class' without the 'new'.
+    this_in_Fn = null;          // Clear any previous value.
+    var non_instance = Fn();
+    assert( non_instance === undefined );
+    assert( this_in_Fn.telltail === 'global');
+
+    // Call the 'class' with the 'new'.
+    this_in_Fn = null;          // Clear any previous value.
+    var instance = new Fn();
+    assert( instance === this_in_Fn );
+    assert( instance.telltail === undefined );
+
+    // Demonstrate that instance is a descendant of Fn.prototype.
+    Fn.prototype.telltail = 'instance-of-Fn';
+    assert( instance.telltail === 'instance-of-Fn' );
+
+    // We can give Fn a new prototype.
+    instance.new_telltail = 'child-of-instance';
+    Fn.prototype = instance;
+
+    // And now an instance of Fn has two telltails.
+    var second_instance = new Fn();
+    assert( second_instance.telltail === 'instance-of-Fn' );
+    assert( second_instance.new_telltail === 'child-of-instance' );
+
+});
+// end new-operator
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/counters-example.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,38 @@
+Counters example
+================
+
+Goal
+----
+
+The goal is to create a web page which contains several independent
+counters.  Each time a counter is clicked, it is incremented.  Here's
+you can `try out a working example
+<./core-javascript-work/counters.html>`_ of what's wanted.
+
+Below is the complete code of this example.  To simplify the matter,
+it is completely self-contained.  It uses no library code, other than
+the definition of *SimpleClass*.
+
+In general library code is a good idea.  This example is designed to
+teach you the basics of JavaScript, and not the use of a library.  We
+hope that what you learn here will help you choose a library, and
+build libraries of your own.
+
+
+counters.html
+-------------
+
+.. literalinclude:: /core-javascript-work/counters.html
+   :language: html
+
+counters.css
+------------
+
+.. literalinclude:: /core-javascript-work/counters.css
+   :language: css
+
+counters.js
+-----------
+
+.. literalinclude:: /core-javascript-work/counters.js
+   :language: javascript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/equality.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,146 @@
+Equality
+========
+
+Equality in JavaScript can be a little odd.
+
+
+Double equals
+-------------
+
+JavScript has two operations for equality (and inequality).  One of
+them is '==' (and '!=' for inequality).  It's the oddest.
+
+
+Not transitive
+^^^^^^^^^^^^^^
+
+If *a* is equal to *b*, and if *b* is equal to *c* , then we expect
+*a* to be equal to *c*.  This is called the transitive property.
+
+
+.. code-block:: javascript
+
+
+   js> '0' == 0      // 'a' is equal to 'b'
+   true
+   js> 0 == ''      //  'b' is equal to 'c'
+   true
+   js> '0' == ''    // 'a' is not equal to 'c'
+   false
+
+
+
+Not reflexive
+^^^^^^^^^^^^^
+
+We expect *a* to be equal to *a*.  This is called the reflexive
+property.
+
+.. code-block:: javascript
+
+   js> NaN == NaN
+   false
+
+Fortunately, this seems to be the only example.
+
+
+Is symmetric
+^^^^^^^^^^^^
+
+If *a* is equal to *b* then we expect *b* to be equal to *a*.  This is
+called the symmetric property.  In JavaScript equality is symmetric.
+
+
+
+Triple equality
+---------------
+
+JavaScript also has '===' (and '!==' for inequality).
+
+
+Is transitive
+^^^^^^^^^^^^^
+
+Unlike double equals, triple equals is always transitive.
+
+.. code-block:: javascript
+
+   js> '0' === 0      // unequal
+   false
+   js> 0 === ''       // unequal
+   false
+   js> '0' === ''     // unequal
+   false
+
+
+Not reflexive
+^^^^^^^^^^^^^
+
+.. code-block:: javascript
+
+   js> NaN === NaN
+   false
+
+
+By the way, there's a thread on Facebook with subject `Time and Date
+on my wall shows NaNNaNNaN at NaN:NaN
+<http://www.facebook.com/topic.php?uid=4915599711&topic=54061>`_.  I
+wonder how that happened.
+
+Is symmetric
+^^^^^^^^^^^^
+
+Triple equality is still symmetric.
+
+
+Don't use double equality
+-------------------------
+
+Double equality does implicit conversions and besides has some odd
+rules.  My advice is **don't use double equality**.
+
+Triple equality does not do conversions.  If you want to do
+conversions in your comparision my advice is to make them explicit.
+
+
+Compare as string
+-----------------
+
+The easiest conversion is to string.  Here are two immutables, a
+number and a string.
+
+.. code-block:: javascript
+
+   js> a = 0
+   0
+   js> b = '0'
+   0
+
+
+These quantities are double equal but not triple equal.
+
+.. code-block:: javascript
+
+   js> a == b
+   true
+   js> a === b
+   false
+
+Here's how to do an explicit conversion to string before comparison,
+which gives an equality.
+
+.. code-block:: javascript
+
+   js> '' + a === '' + b    // Converts variables to strings.
+   true
+
+.. note::
+
+   It's always easier to read a triple equal comparison, because
+   you're not distracted by the complex double equal rules.
+
+
+Compare as number
+-----------------
+
+[To follow later.]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/exercise-1.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,35 @@
+Exercise one
+============
+
+Here's some JavaScript code I found somewhere.  I've changed the names
+of everything to hide the origin of the code.  But it's not something
+I've made up.
+
+The exercise is
+
+#.  Understand and describe what it does.
+
+#.  Provide clearer code that does the same thing.
+
+#.  Suggest a better way of going about things.
+
+.. literalinclude:: /core-javascript-work/exercise-1.js
+   :language: javascript
+
+
+Hints
+-----
+
+#.  The code creates and calls an anonymous function, a bit like this.
+
+    .. code-block:: javascript
+
+       js> a = function(x){return x + 1}(2)
+       3
+
+#.  What happens if AAA is an object?
+
+#.  What happens if AAA is undefined?
+
+#.  For now, ignore the assignment to BBB.fff.  What value does AAA
+    get?  (The answer depends the initial value of AAA.)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/exercise-2.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,59 @@
+Exercise two
+============
+
+Here's some more JavaScript code I found.  I've changed the names of
+everything to hide the origin of the code.  But it's not something
+I've made up.
+
+.. literalinclude:: /core-javascript-work/exercise-2.js
+   :language: javascript
+
+The exercise is
+
+#.  Rewrite the function copy_attributes so that it makes a loop over
+
+    .. code-block:: javascript
+
+        var keys = ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg', 'hhh'];
+
+#.  Write a copy_attributes_factory function so that we can write
+
+    .. code-block:: javascript
+
+       var copy_attributes = copy_attributes_factory(keys);
+
+#.  Write a Fields class such that something like this will work:
+
+    .. code-block:: javascript
+
+      var aaa = Fields(keys);
+      aaa.copy_attributes(src, tgt);
+
+
+Hints
+-----
+
+#.  In JavaScript attribute access and item access are the same.
+    First we use item access to set:
+
+    .. code-block:: javascript
+
+       js> a = {}
+       [object Object]
+       js> key = 'attrname'
+       attrname
+       js> a[key] = 42
+       42
+
+    and then we use attribute access to get:
+
+    .. code-block:: javascript
+
+       js> a.attrname
+       42
+
+#.  This applies even for function (aka method) calls.
+
+#.  Have the factory function store the keys in a closure.
+
+#.  There are many ways of writing Fields.  Choose one that suits you.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/getting-started.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,76 @@
+Getting started
+===============
+
+What you need
+-------------
+
+You'll need on your machine
+
+#.  A JavaScript interpreter which provides a command line
+
+#.  An editor on your machine.
+
+You'll also to download and unzip the course :download:`work folder
+</core-javascript-work.zip>`.
+
+
+Windows and Linux
+-----------------
+
+For Windows the easiest thing to do is to `download the JSDB
+interpreter <http://www.jsdb.org/download.html>`_, and use notepad (or
+some other editor).
+
+For Linux you and install Rhino and use your favourite editor.
+
+.. code-block:: sh
+
+   $ sudo apt-get install rhino
+
+
+Are you ready?
+--------------
+
+You'll want to be able to run the JavaScript interpreter from the
+command line when in the work folder.  This will be automatic (via the
+PATH) with Linux and Rhino.  For Windows the easiest thing to do is to
+place the jsdb.exe file in the work folder.
+
+When you're ready type *js* at a command prompt.  This starts the
+interpreter and gives you a *js>* prompt. You'll get something like
+this.
+
+.. code-block:: javascript
+
+   core-javascript-work$ js
+   Rhino 1.7 release 2 2010 01 20
+   js>
+
+Now type the command as below at the JavaScript prompt (with Return at the end of
+each line) and you'll get responses as below.
+
+
+.. code-block:: javascript
+
+   js> a = '0'
+   0
+   js> b = 0
+   0
+   js> c = ''
+
+   js> a == b
+   true
+   js> b == c
+   true
+   js> a == c
+   false
+
+
+You might be surprised by the last response from the interpreter, but
+every JavaScript interpreter does this.
+
+
+Yes, you're ready
+-----------------
+
+To exit the interpreter use Ctrl-C or Ctrl-D.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/global.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,122 @@
+The global object
+=================
+
+JavaScript has a global object.  It is, so to speak, the object of
+last resort.  If there's no other suitable object then JavaScript will
+use the global object (rather than reporting an error).
+
+.. note::
+
+   Douglas Crockford writes **JavaScript's global object ... is far and
+   away the worst part of JavaScript's many bad parts.**
+
+
+Getting global
+---------------
+
+Here's how to get the global object.
+
+.. code-block:: javascript
+
+   js> return_this = function(){return this;}
+
+   function () {
+       return this;
+   }
+
+   js> global = return_this()
+   [object global]
+
+The programmer who wants to can always obtain access to the global
+object.
+
+
+Global variables
+----------------
+
+Global variables are nothing more than attributes of the global
+object.
+
+.. code-block:: javascript
+
+   js> s = 'Hello world.'
+   Hello world.
+   js> global.s
+   Hello world.
+   js> global.i = 42
+   42
+   js> i
+   42
+
+
+Global pollution
+----------------
+
+It's very easy to inadvertently pollute (change) the global object.
+All it takes is an assignment to an undeclared variable in a function.
+
+.. code-block:: javascript
+
+   js> pollute = function(n){ i = n; };
+   function (n) {
+       i = n;
+   }
+   js> i
+   42
+   js> pollute(13)
+   js> i
+   13
+
+More global pollution
+---------------------
+
+There's a more subtle way to pollute the global object, which involves :doc:`JavaScript's this object <what-is-this>`.
+
+To begin with, note that we can push values onto an array.
+
+.. code-block:: javascript
+
+   js> array = []
+
+   js> array.push(1, 2, 3)
+   3
+   js> array
+   1,2,3
+
+Let's try using *array.push* as a stand-alone function.
+
+.. code-block:: javascript
+
+   js> p = array.push
+   function push() { [native code for Array.push, arity=1] }
+
+   js> p(4, 5, 6)
+   3
+
+The push function returns the length of the object it has just pushed
+to.  So the value *3* above is a signal that all is not well.  And
+indeed it is not.  The original array is unchanged, and the global
+object has an entry at 0.
+
+.. code-block:: javascript
+
+   js> array
+   1,2,3
+   js>
+   js> global[0]
+   4
+
+It's also got a length!
+
+.. code-block:: javascript
+
+   js> global.length
+   3
+
+
+Explanation
+-----------
+
+This behaviour is a consequence of :doc:`what-is-this` and
+:doc:`bind-is-transient`, together with JavaScript's no-exceptions
+design.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/immutables.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,131 @@
+Immutables
+==========
+
+First, a quick word about variables.  A value is an indentifier that
+holds a value.  In JavaScript every value has a type, but variables
+are not typed.  In other words, any variable can hold any value.  Most
+dynamic language (such as Perl, Python and Ruby) are like this.
+
+Always declare variables with a var statement, because sometimes a
+missing var can cause a hard-to-find bug.  Experiments at the command
+line are the only exception to this rule.
+
+We can change an array or a 'dictionary'.  Immutable values are values
+that can't be changed.  We can't change, for example, the third
+character in a string.
+
+
+Strings
+-------
+
+Strings literals are delimited by single or double quote marks, with
+special characters escaped.  There's no difference between the two
+forms (except in single quote you don't have to escape double quote,
+and vice versa.)  Generally, I prefer the single quote form as it's
+less busy on the eye and slightly easier to type.
+
+.. code-block:: javascript
+
+   js> s = 'Hello world.'
+   Hello world.
+
+We can add two strings together to produce a third string.
+
+.. code-block:: javascript
+
+   js> r = "I'm me. "
+   I'm me.
+   js> r + s
+   I'm me. Hello world.
+
+
+typeof
+------
+
+There's a built-in operator called 'typeof' that returns a string
+that, sort-of, gives the type of a value.
+
+.. code-block:: javascript
+
+  js> typeof(s)
+  string
+
+Because typeof is an operator (just as '+' is an operator) the
+parentheses are not needed, and many JavaScript programmers omit them.
+
+.. code-block:: javascript
+
+  js> typeof s
+  string
+
+Here we see that typeof produces (returns) a string.
+
+.. code-block:: javascript
+
+  js> typeof typeof s
+  string
+
+
+Numbers
+-------
+
+JavaScript numbers are platform and processor independent.  It uses
+IEE 754 to represent both integers and floats.
+
+.. code-block:: javascript
+
+   js> i = 42
+   42
+   js> typeof i
+   number
+
+
+Booleans
+--------
+
+JavaScript has keywords 'true' and 'false' whose values are always
+true and false respectively.
+
+.. code-block:: javascript
+
+   js> t = true
+   true
+   js> typeof b
+   boolean
+
+Logical comparisions also produce Booleans.
+
+.. code-block:: javascript
+
+   js> f = (1 > 2)
+   false
+   js> typeof f
+   boolean
+
+
+undefined and null
+------------------
+
+JavaScript has *two* values that represent None.  Later, we'll see
+why, and which to use when.  For now we'll simply note that they are
+different, because their types are different.
+
+.. code-block:: javascript
+
+   js> typeof undefined
+   undefined
+   js> typeof null
+   object
+
+
+Gotchas
+-------
+
+.. code-block:: javascript
+
+   js> s = 'Hello world.'
+   Hello world.
+   js> s.lang = 'en'
+   en
+   js> s.lang === undefined
+   true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/index.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,56 @@
+Welcome to Core JavaScript training
+===================================
+
+This document has a :ref:`search`.
+
+
+About this course
+-----------------
+
+.. toctree::
+   :maxdepth: 2
+
+   getting-started
+   counters-example
+   testtools
+
+
+Objects
+-------
+
+.. toctree::
+   :maxdepth: 2
+
+
+   immutables
+   equality
+   objects
+   object-tree
+   simple-classes
+
+
+Functions
+---------
+
+.. toctree::
+   :maxdepth: 2
+
+   global
+   closures
+   what-is-this
+   bind-is-transient
+   what-is-new
+   arguments
+   millers-device
+
+
+Examples and exercises
+----------------------
+
+.. toctree::
+   :maxdepth: 2
+
+   exercise-1
+   solution-1
+   exercise-2
+   solution-2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/make.bat	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,163 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\CoreJavaScript.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\CoreJavaScript.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %ALLSPHINXOPTS% %BUILDDIR%/locale
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/millers-device.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,22 @@
+Mark Miller's device
+====================
+
+This can be omitted at a first reading. Mark Miller is one of the
+leading JavaScript experts at Google.  He's been credited an ingenious
+application of call that gives a simple and reliable test for whether
+or not an object is an array.
+
+This may not sound very much, but it is something that had been
+puzzling the other experts for some years.  For example, Crockford in
+his *Good Parts* (published 2008, page 61) gives a much more complex
+and less reliable solution to this problem.
+
+The moral of this story is that even the experts in JavaScript can
+have difficulty finding the best way to solve a simple problem.
+
+Test code
+---------
+.. literalinclude:: /core-javascript-work/tutorial.js
+   :language: javascript
+   :start-after: start millers-device
+   :end-before: end millers-device
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/object-tree.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,168 @@
+The object tree
+===============
+
+Objects can have attributes.  The statements
+
+.. code-block:: javascript
+
+   value = obj.attr             # Get the attr of 'a'.
+   obj.attr = value              # Set the attr of 'a'.
+
+respectively **set** and **get** the *attr* attribute of the object
+*obj*.  Inheritance is where an object gets some its attributes from
+one or other more objects.  JavaScript uses an object tree for
+inheritance.
+
+
+.. _inheritance-tree:
+
+Tree
+----
+
+All JavaScript objects are part of an inheritance tree.  Each object
+in the tree has a parent object, which is also called the prototype
+object (of the child).  There is a single exception to this rule,
+which is the **root** of the tree.  The root of the tree does not have
+a parent object.
+
+.. note::
+
+   **You can't get far in JavaScript without understanding the
+   object tree.**
+
+
+Get
+^^^
+
+When JavaScript needs to get an attribute value of an object, it first
+looks up the attr of the attribute in the object's dictionary.  If the
+attr is a key in the dictionary, the associated value is returned.
+
+If the attr is not a key, then the process is repeated using the
+object's parent, grandparent, and so on until the key is found.  If
+the key is not found in this way then *undefined* is returned.
+
+
+Set
+^^^
+
+When JavaScript needs to set an attribute value of an object it
+ignores the inheritance tree.  It simply sets that value in the
+object's dictionary.
+
+
+Root
+----
+
+When the interpreter starts up, the **root** of the tree is placed at
+*Object.prototype*.  (We'll find out later why that location is used.)
+
+Every object inherits from the **root**, although perhaps not
+directly.  Here's a simple example:
+
+.. code-block:: javascript
+
+   js> root = Object.prototype
+   js> a = {}
+   js> a.attr === undefined
+   true
+   js> root.attr = 'gotcha'
+   js> a.attr
+   gotcha
+
+If we give *root* a *attr* attribute then every other object,
+including those already created and those not yet created, also has a
+*attr* attribute with the same value.  (In practice it's better not to
+change Object.prototpye.)
+
+This applies arrays:
+
+.. code-block:: javascript
+
+   js> array = [0, 1, 2]
+   0,1,2
+   js> array.attr
+   gotcha
+
+And even to functions:
+
+.. code-block:: javascript
+
+   js> f = function(){}
+   function () {
+   }
+
+   js> f.attr
+   gotcha
+
+.. note::
+
+  A page might have many scripts, all of which would like to modify
+  the Object.prototype root object.  This can cause bugs and
+  incompatibilities.  So try not to do this.
+
+
+However, this up-the-tree lookup does not apply if *attr* is found
+earlier in the tree.  We continue the previous example to show this,
+and the behaviour of set.
+
+.. code-block:: javascript
+
+   js> a.attr = 'fixed'
+   js> a.attr
+   fixed
+   js> root.attr
+   gotcha
+
+
+Create
+------
+
+Any tree can be constructed from its root, together with a command
+**create(parent)** that returns a new **child** of the given parent
+node.
+
+In all but the most recent version of JavaScript the *create* function
+is not built in.  However, it's easy to write one, once you know
+enough JavaScript.  Here's how its done in the work folder's
+library.js file.
+
+.. literalinclude:: /core-javascript-work/library.js
+   :language: javascript
+   :start-after: start create
+   :end-before: end create
+
+
+Using create
+------------
+
+Here's an example of its use:
+
+.. code-block:: javascript
+
+   js> a = {}
+   js> b = create(a)
+   js> a.attr = 'apple'
+   apple
+   js> b.attr
+   apple
+
+
+And a continuation of the example:
+
+.. code-block:: javascript
+
+   js> c = create(b)
+   js> c.attr
+   apple
+   js> b.attr = 'banana'
+   banana
+   js> c.attr
+   banana
+
+
+.. note::
+
+   JavaScript uses an inheritance tree.  By using *create*, we can
+   create any inheritance tree.  All JavaScript objects are in this
+   tree.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/objects.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,177 @@
+Objects
+=======
+
+JavaScript has objects and is object-oriented, but in an unusual way
+(more on that later).
+
+
+Simple objects
+--------------
+
+Simple objects are like dictionaries or hashes in other languages.
+They support key-value storage and access to attributes.  Here's how
+to create a simple object.
+
+.. code-block:: javascript
+
+   js> obj = {}
+   [object Object]
+
+   js> typeof obj
+   object
+
+We can store attribute values in a simple object (or any object in the
+doc:`object-tree`).
+
+.. code-block:: javascript
+
+   js> obj.s = 'hi'
+   hi
+   js> obj.i = 10
+   10
+
+We can get these values back again.
+
+.. code-block:: javascript
+
+   js> obj.s === 'hi'
+   true
+   js> obj.i == 10
+   true
+
+
+Missing attributes
+------------------
+
+It's not an error to ask for something that's not there.  We get
+undefined.
+
+.. code-block:: javascript
+
+   js> obj.dne === undefined
+   true
+
+We still get undefined if we set the value to undefined.
+
+.. code-block:: javascript
+
+   js> obj.undef = undefined
+   undefined
+   js> obj.dne === undefined
+   true
+
+You can use null to signal that there is a value, but that it is None.
+
+.. code-block:: javascript
+
+   js> obj.none = null
+   null
+   js> obj.none === null
+   true
+
+
+hasOwnProperty
+--------------
+
+You can use hasOwnProperty to help figure out why an object has an
+undefined attribute.  It's also useful when inspecting the
+doc::`object-tree`.  Often, however, it's better to write your code so
+you don't need to do this (for example by using null).
+
+.. code-block:: javascript
+
+   js> obj.hasOwnProperty('dne')
+   false
+   js> obj.hasOwnProperty('undef')
+   true
+   js> obj.hasOwnProperty('none')
+   true
+
+
+Object literals
+---------------
+
+You can create a simple object by placing key-value pairs in the curly
+braces.
+
+.. code-block:: javascript
+
+   js> someone = {
+     >     'name': 'Joe Doe',
+     >     'age': 43
+     > }
+   [object Object]
+
+   js> someone.age
+   43
+
+Take care *not* to put a trailing semicolon in the object literal.  It
+will work in Firefox but not in Internet Explorer.
+
+
+Arrays
+------
+
+An array is a list of items.  You can put anything is as a value for
+the list.  Use square brackets to create an array.
+
+.. code-block:: javascript
+
+   js> array = []
+
+Arrays expand to accomodate the data you store in them.  You can even
+leave gaps.
+
+.. code-block:: javascript
+
+   js> array[0] = 'zero'
+   zero
+   js> array[3] = 'three'
+   three
+
+An array turned into a string consists of the string on its entries
+joined by commas.
+
+.. code-block:: javascript
+
+   js> array
+   zero,,,three
+   js> array[1] === undefined
+   true
+
+
+Array literals
+--------------
+
+As with simple objects, simply place the values between the square
+brackets, separated by commas.
+
+.. code-block:: javascript
+
+   js> seasons = ['spring', 'summer', 'autumn', 'winter']
+   spring,summer,autumn,winter
+
+
+As with simple objects, beware of trailing commas and missing entries.
+This will work in some browsers and not others.
+
+
+JSON
+----
+
+`JSON <http://www.json.org/>`_,stands for JavaScript Simple Object
+Notation.  It is very much one of the best parts of JavaScript.  It is
+`the fat-free alternative to XML <http://www.json.org/xml.html>`_, and
+is widely used in AJAX (instead of XML).  JSON objects are object and
+array literals constructed using only simple objects, arrays, strings,
+true, false and null.
+
+If your code accepts JSON objects then it will be a lot easier to use
+it with AJAX or otherwise integrate it with other systems.
+
+Many programming languages have JSON libraries.  You don't have to use
+JavaScript to use JSON.
+
+To provide standards, there are rules on how to write a JSON objects.
+Many applications and programming languages will generate valid JSON
+for you.  I find YAML a convenient way of authoring JSON data.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/py/remove_answers.py	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,94 @@
+'''Remove answers from exercises file.'''
+
+import os
+import sys
+
+NORMAL, SKIPPING, ERROR = range(3)
+LINE, SOMETHING, START, STOP = range(4)
+
+lookup = {}
+
+# All other states are an error.
+lookup[NORMAL, LINE] = NORMAL
+lookup[NORMAL, SOMETHING] = NORMAL
+lookup[NORMAL, START] = SKIPPING
+lookup[SKIPPING, LINE] = SKIPPING
+# lookup[NORMAL, STOP] = ERROR
+# lookup[SKIPPING, SOMETHING] = ERROR
+lookup[SKIPPING, STOP] = NORMAL
+
+
+def doit(src, tgt):
+
+    pending = []
+    with open(src, 'rb') as lines:
+
+        new_state = NORMAL
+
+        for lineno, line in enumerate(lines):
+
+            state = new_state
+
+
+            stripped_line = line.strip()
+
+            if stripped_line.startswith('something'):
+                event = SOMETHING
+
+            elif stripped_line == '// start':
+                event = START
+
+            elif stripped_line == '// stop':
+                event = STOP
+
+            else:
+                event = LINE
+
+            new_state = lookup[state, event]
+
+            if event == SOMETHING:
+                pass
+
+            elif event == STOP:
+                pass
+
+            elif event == START:
+                indent = len(line) - len(line.lstrip())
+                spaces = line[0:indent]
+                pending.append(spaces + '// Please write your answer here.')
+
+            elif state == SKIPPING:
+                pass
+
+            elif event == LINE:
+                pending.append(line.rstrip())
+
+
+        with open(tgt, 'wb') as f:
+
+            for line in pending:
+                f.write(line + '\r\n')
+
+
+
+if __name__ == '__main__':
+
+
+    root = 'core-javascript-work'
+    exercises_dir = root
+    answers_dir = os.path.join(root, 'answers')
+
+
+    names = [
+        name
+        for name in os.listdir(answers_dir)
+        if name.endswith('.js')
+        ]
+
+
+    for name in names:
+
+        src = os.path.join(answers_dir, name)
+        tgt = os.path.join(exercises_dir, name)
+
+        doit(src, tgt)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/simple-classes.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,47 @@
+Simple classes
+==============
+
+JavaScript has objects, which through the object tree support
+inheritance.  Almost all object-oriented languages have classes and
+instances, but JavaScript has neither.  This will be explained later,
+along with a discussion of the consequences.
+
+For now our focus is on getting going with object-oriented
+programming.  The easiest way to do this is via create.
+
+
+Definition
+----------
+
+Here's a factory function that creates classes.  It returns a function
+called *cls*, which in turn when called returns instances.  At it's
+heart is *create*, and also *apply* and *arguments*, which we've not
+seen before).
+
+.. literalinclude:: /core-javascript-work/library.js
+   :language: javascript
+   :start-after: start SimpleClass
+   :end-before: end SimpleClass
+
+
+Why *cls*?
+----------
+
+We call the returned function *cls* because in JavaScript *class*,
+like *function* is a reserved word in JavaScript.  However, in
+JavaScript the identifier *class* has no meaning, and cannot be used
+in any valid JavaScript program.  It seems that they intended to
+provide a built-in class capability, but never got round to it.
+
+
+Fruit example
+-------------
+
+Here's an example of the use of *SimpleClass*.  There's a bug in it,
+and I've changed the test so it passes.  Can you find the bug and fix
+the example?
+
+.. literalinclude:: /core-javascript-work/test_library.js
+   :language: javascript
+   :start-after: start SimpleClass
+   :end-before: end SimpleClass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/solution-1.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,118 @@
+Solution one
+============
+
+Here's the code we're studying.
+
+.. literalinclude:: /core-javascript-work/exercise-1.js
+   :language: javascript
+
+
+Verbal summary
+--------------
+
+We are making sure that there's an object AAA and giving it an
+attribute AAA.fff, which is a function.  We won't say more about the
+function in this summary.
+
+
+Hoisting once-only arguments
+----------------------------
+
+First, we'll hoist the argument to the anonymous function into its
+body.  We can always do this, without changing the meaning, provided the
+function is called only once.
+
+.. literalinclude:: /core-javascript-work/solution-1-a.js
+   :language: javascript
+
+There, that's better.  We no longer have to read to the end of the
+function to find out what BBB is (and in particular its relationship
+with AAA).
+
+
+What is AAA?
+------------
+
+Next, we'll hide (or ignore) the assigment to BBB.fff.  This
+assignment sets an attribute on the object pointed to by the variable
+BBB.  In other words, it mutates the object pointed to by BBB, but the
+variable BBB still points to the same object as it did before.
+
+.. literalinclude:: /core-javascript-work/solution-1-b.js
+   :language: javascript
+
+
+If AAA starts out as an object then the expression
+
+.. code-block:: javascript
+
+   AAA || {}
+
+evaluates to AAA, while if AAA is undefined then it evaluates to the
+newly created object literal (the left-and-right curly braces).  In
+either case, this value is assigned to the local variable BBB, which
+is then returned by the anonymous function and bound to AAA.
+
+Put another way, if AAA starts off as undefined then it is bound to a
+new object, while if it starts off as an object then it finishes as
+the same object.
+
+Therefore, our truncated version of the original exercise is equivalent to
+
+.. literalinclude:: /core-javascript-work/solution-1-c.js
+   :language: javascript
+
+This idiom is very common in JavaScript, and is (as here) a
+consequence of using objects as namespaces (which is better than using
+the global object) and defensiveness about the order in which files
+are loaded.
+
+Here's a command line session that shows this equivalence.  To begin
+with AAA is undefined and the assignment binds AAA to a new object.
+For the second assignment AAA is defined and the assignment binds AAA
+to the object is already bound to.
+
+.. code-block:: javascript
+
+   js> var AAA = AAA || {}
+   js> AAA
+   [object Object]
+   js> pointer = AAA
+   [object Object]
+   js> var AAA = AAA || {}
+   js> pointer === AAA
+   true
+
+
+The assignment to BBB.fff
+-------------------------
+
+Reading the code, it looks as if BBB is local to the anonymous
+function.  As a variable it is, but its value is not.  The value of
+BBB is bound to the global object AAA at the end of the function call.
+
+The following is almost equivalent to our original JavaScript code.
+Note that BBB.hhh has been changed to AAA.hhh.
+
+.. literalinclude:: /core-javascript-work/solution-1-d.js
+   :language: javascript
+
+
+Caveat
+------
+
+Why did I say *almost equivalent*?  Because we might subsequently do
+something like
+
+
+.. code-block:: javascript
+
+   var CCC = AAA;
+   AAA = undefined;
+
+For the original code the closure variable BBB still exists and points
+to the same object as CCC, even though AAA is undefined.  Thus, the
+reference to BBB.hhh in the original code will continue to work.
+
+For the revised code, when the value of AAA is set to undefined the
+reference to AAA.hhh will fail.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/solution-2.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,112 @@
+Solution two
+============
+
+Here's the code we are studying.  The first task is make a loop that
+does the assignments.
+
+.. literalinclude:: /core-javascript-work/exercise-2.js
+   :language: javascript
+
+
+Making a loop
+-------------
+
+As previously hinted, we use item access rather than attribute access.
+The problem with attribute access is that the name of the key is
+hard-coded and we want it to vary during the loop.
+
+Here's the solution.  There's a bit of overhead in setting up the
+loop, but the body of the loop is straightforward.
+
+.. literalinclude:: /core-javascript-work/solution-2-a.js
+   :language: javascript
+
+
+Factory function
+----------------
+
+The second task is to write a factory function that takes the list of
+keys as a parameter.
+
+This is a common refactoring pattern, and so is worth learning well.
+First we give the code, and then the explanation.
+
+.. literalinclude:: /core-javascript-work/solution-2-b.js
+   :language: javascript
+
+
+Here's what we've done.  We created a wrapper function, with *keys* as
+its only parameter.  This will be our factory function.  We've placed
+the original function into the body of the wrapper, and return it (as
+the value of the wrapper function).  Finally, we clean up by removing
+the *keys* constant from the inner function.
+
+There, it's done!  When the factory function executes it returns an
+instance of the inner function for which *keys* is the argument we
+supplied to the factory.
+
+
+A prototype class
+-----------------
+
+The third task is to write a Fields class that has a copy_attributes
+method.
+
+Here's a function prototype based solution.  It relies on the user of
+the class supplying the *new* operator to create the new instance (and
+chaos results if the user forgets).
+
+.. literalinclude:: /core-javascript-work/solution-2-c.js
+   :language: javascript
+
+A minor point is the trailing sequence of right curly braces.  Two are
+followed by a semicolon, but the middle one is not.  Why?  What
+happens if we put a semicolon there?
+
+
+A SimpleClass solution
+----------------------
+
+Here's another solution to the third task, which does not require the
+user to supply a *new* operator when creating instances.  Instead it
+uses a factory function, which we call *Class* , that creates an
+instance constructor function from a prototype object.
+
+.. literalinclude:: /core-javascript-work/solution-2-d.js
+   :language: javascript
+
+
+Exercise: write test
+--------------------
+
+Here's an exercise.  Write a JavaScript file that tests this solution.
+
+
+Exercise: bound method class
+----------------------------
+
+
+Recall that this-based instance methods are somewhat fragile.  In
+other words, code like this will fail (and make unwanted changes to
+the global object):
+
+.. code-block:: javascript
+
+   var instance = MyClass(arg1, arg2);
+
+   var fn = instance.method;
+   element.onclick(fn);
+
+Let's say that a class *has bound methods* if we can safely pass
+around instance methods.  In other words, we want *instance.method* to
+have no dependence on the value of *this*.
+
+We can achieve this by using a different class factory function.
+
+.. code-block:: javascript
+
+   var myclass = {}    // The prototype object.
+   // Add methods to myclass.
+   var MyClass = BoundMethodClass(myclass);
+
+The exercise is to create (and test) a BoundMethodClass factory.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/testtools.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,76 @@
+Test tools
+==========
+
+To make it easier to test code, and to ensure that example code is
+correct, there is a small testtools.js file in the work folder.
+
+
+How to write tests
+------------------
+
+To prepare a test create a file like this.  It's also in the work
+folder.  (For real examples the file will give *assert* a more
+interesting argument, whose truth or falsity is perhaps not obvious.)
+
+.. literalinclude:: /core-javascript-work/demo_testtools.js
+   :language: javascript
+
+
+How to run tests
+----------------
+
+Here's how to run the tests at the command line, finishing with a
+command prompt that allows you inspect the state and also run the test
+again.
+
+
+Rhino
+^^^^^
+
+For Rhino use *load* to run the test again.
+
+.. code-block:: sh
+
+   core-javascript-work$ js -f testtools.js -f demo_testtools.js -f -
+   Testing: all-pass
+   Testing: 2-4-fail
+   ! assert 2 has failed
+   ! assert 4 has failed
+   Rhino 1.7 release 2 2010 01 20
+   js> load('demo_testtools.js')  // You type this.
+   Testing: all-pass
+   Testing: 2-4-fail
+   ! assert 2 has failed
+   ! assert 4 has failed
+   js>
+
+
+JSDB
+^^^^
+
+For JSDB use *run* to run the test again.
+
+.. code-block:: sh
+
+   C:core-javascript-work> jsdb -load testtools.js -load demo_testtools.js
+   Testing: all-pass
+   Testing: 2-4-fail
+   ! assert 2 has failed
+   ! assert 4 has failed
+   js> load('demo_testtools.js')  // You type this.
+   Testing: all-pass
+   Testing: 2-4-fail
+   ! assert 2 has failed
+   ! assert 4 has failed
+   js>
+
+
+testools.js
+-----------
+
+(Optional on a first reading.)  Here's the file testools.js.  It's
+short and simple (and has a not-nice dependency on global variables).
+It also has a branch based on whether it's being run on JSDB or Rhino.
+
+.. literalinclude:: /core-javascript-work/testtools.js
+   :language: javascript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/what-is-new.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,62 @@
+What is new?
+============
+
+This can be omitted at a first reading, and omitted altogether if you
+never have to deal with code that uses the *new* operator.  If you do,
+then you **must** read about the missing *new* problem.
+
+JavaScript has an object tree.  This is a fundamental language
+feature.  The *new* operator is a way of adding objects to the tree.
+The *create* function, which is built-in to the latest version of
+JavaScript, can be defined in terms of *new*, and vice versa.
+
+
+Test code
+---------
+
+.. literalinclude:: /core-javascript-work/tutorial.js
+   :language: javascript
+   :start-after: start new-operator
+   :end-before: end new-operator
+
+
+Discussion
+----------
+
+By changing the prototype object of *Fn* we start building a tree of
+objects.
+
+There is a built-in relation between an object and its parent.  There
+is no relation between the object and its constructor, here called
+*Fn*, except that at the time of construction the parent of the object
+is Fn.prototype.
+
+The exact rules for the behaviour of *new* are complicated and not
+given here.
+
+
+No missing *new* warning
+------------------------
+
+We saw that when *Fn* is called without the *new* then during its
+execution the value of *this* is the global object.  If the
+constructor *Fn* mutates *this* (and almost every constructor does),
+then it is the global object that is mutated.
+
+This is very bad:
+
+#. You may clobber someone elses data.
+
+#. Someone else may clobber your data.
+
+#. If you create two instances, you will clobber your own data.
+
+#. Testing for this error involves extra work.
+
+#. Bugs that arise from this error can appear random and can be hard
+   to find.
+
+.. note::
+
+   Crockford writes **A much better alternative is to not use new at
+   all."**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core-javascript/what-is-this.rst	Mon Feb 13 10:05:46 2012 +0000
@@ -0,0 +1,87 @@
+What is this?
+=============
+
+JavaScript has a keyword *this*, whose value depends on the execution
+context.  It is always an object (and never an immutable, such as a
+number).
+
+
+Test code
+---------
+
+.. literalinclude:: /core-javascript-work/tutorial.js
+   :language: javascript
+   :start-after: start return_this
+   :end-before: end return_this
+
+
+Discussion
+----------
+
+The function *return_this* is a convenient way of getting of getting
+hold of the object that is the value of *this*. The code that follows
+shows:
+
+#. The default value of *this* is the global object.
+
+#. When *return_this* is called as either a method (i.e. an attribute
+   that is a function) or item of *obj* then *this* is *obj* itself.
+
+#. That the *call* and *apply* methods of a function allow us to set
+   the value of *this* within a particular execution of the function.
+
+#. If we pass *undefined* to function *call* or *apply* then we get
+   the global object as *this*.
+
+
+Explanation
+-----------
+
+Throughout the execution of JavaScript code, the identifier *this* has
+a value, which is an object (and not an immutable value).  The value
+of *this* depends on how the JavaScript interpreter got to be
+executing the code.
+
+#. At the command line *this* is the global object.
+
+#. In a function *this* is the object from which the interpreter got
+   the function.
+
+#. Because global variables are attributes of the global object, the
+   rule for calling global variables as functions is a special case of
+   the previous rule.
+
+#.
+
+
+Here's a helpful way to look at the situation.  It is as if the
+interpreter maintains a *this stack*, which starts containing a single
+item, the global object.  Each time an item access of an object is
+immediately followed by a function call, the object is added to the
+*this stack*, and removed at the end of the function call.  For all
+other function calls the global object is added to the *this stack*.
+
+During execution of a function the value of *this* is the element at
+the top of the *this stack*.
+
+Finally, the function *call* and *apply* methods allow for a
+particular object to be placed at the top of the *this stack* before
+the function is called.
+
+
+Exercises
+---------
+
+#. At the command-line try making an assignment to *this*.  What
+   happens?
+
+#. Try loading a JavaScript program that makes an assignment to
+   *this*.  What happens?
+
+#. For what values of *value* is the following true?
+
+   .. code-block:: javascript
+
+      return_this.apply(value) === value;
+
+#. Write a simple test that detects these values.
--- a/source/inheritance.rst	Wed Oct 19 11:45:25 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-Inheritance
-===========
-
-
-Objects have attributes.  In both JavaScript and Python the statements
-
-.. code-block:: python
-   
-   value = a.name               # Get the name of 'a'.
-   a.name = value               # Set the name of 'a'.
-
-respectively **set** and **get** the *name* attribute of the object
-*a*.  Inheritance is where an object gets some its attributes from one
-or other more objects.
-
-JavaScript and Python handle inheritance differently.  Here we
-describe what JavaScript does, and later [where] we compare with
-Python.
-
-
-.. _inheritance-tree:
-
-Tree
-----
-
-In JavaScript all objects are part of an inheritance tree.  Each
-object in the tree has a parent object, which is also called the
-prototype object (of the child).  There is a single exception to this
-rule, which is the **root** of the tree.  The root of the tree does
-not have a parent object.
-
-**You can't get far in JavaScript without understanding the
-inheritance tree.**
-
-Get
-^^^
-
-When JavaScript needs to get an attribute value of an object, it first
-looks up the name of the attribute in the object's dictionary.  If the
-name is a key in the dictionary, the associated value is returned.
-
-If the name is not a key, then the process is repeated using the
-object's parent, grandparent, and so on until the key is found.  If
-the key is not found in this way then (see :ref:`object-missing-keys`)
-*undefined* is returned.
-
-Set 
-^^^ 
-
-When JavaScript needs to set an attribute value of an object it
-ignores the inheritance tree.  It simply sets that value in the
-object's dictionary.  With Python its just the same.  (However,
-JavaScript's :doc:`pseudo-objects` are don't behave in this way.)
-
-Root
-----
-
-When the interpreter starts up, the **root** of the tree is placed at
-*Object.prototype*.
-
-Every object inherits from the **root**, although perhaps not
-directly.  Here's an example:
-
-.. code-block:: javascript
-
-   js> root = Object.prototype
-   js> a = {}
-   js> a.name === undefined
-   true
-   js> root.name = 'gotcha'
-   js> a.name
-   gotcha
-
-Once we give *root* a *name* attribute every other object, including
-those already created and those not yet created, also has a *name*
-attribute with the same value.
-
-However, this does not apply if *name* is found earlier in the tree.
-We continue the previous example to show this, and the behaviour of
-set.
-
-.. code-block:: javascript
-
-   js> a.name = 'fixed'
-   js> a.name
-   fixed
-   js> root.name
-   gotcha
-
-Using create
-------------
-
-Any tree can be constructed from its root, together with a command
-**create(parent)** that returns a new **child** of the given parent
-node.
-
-In JavaScript the *create* function is not built in (although perhaps
-it should be).  However, it's easy to write one [link], once you know
-enough JavaScript.
-
-Here's an example of its use:
-
-.. code-block:: javascript
-
-   js> a = {}
-   js> b = create(a)
-   js> a.name = 'apple'
-   apple
-   js> b.name
-   apple
-
-
-And a continuation of the example:
-
-.. code-block:: javascript
-
-   js> c = create(b)
-   js> c.name
-   apple
-   js> b.name = 'banana'
-   banana
-   js> c.name
-   banana
-
-
-.. note::
-
-   JavaScript uses an inheritance tree.  By using *create*, we can
-   create any inheritance tree.  All JavaScript objects are in this
-   tree.