summaryrefslogtreecommitdiff
path: root/includes/js/dojo/tests
diff options
context:
space:
mode:
authormensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f>2008-11-13 09:49:11 +0000
committermensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f>2008-11-13 09:49:11 +0000
commite44a7e37b6c7b5961adaffc62b9042b8d442938e (patch)
tree95b67c356e93163467db2451f2b8cce84ed5d582 /includes/js/dojo/tests
parenta62b9742ee5e28bcec6872d88f50f25b820914f6 (diff)
downloadsemanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.gz
semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.bz2
New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'includes/js/dojo/tests')
-rw-r--r--includes/js/dojo/tests/AdapterRegistry.js75
-rw-r--r--includes/js/dojo/tests/DeferredList.js206
-rw-r--r--includes/js/dojo/tests/NodeList-fx.html150
-rw-r--r--includes/js/dojo/tests/TODO11
-rw-r--r--includes/js/dojo/tests/_base.js136
-rw-r--r--includes/js/dojo/tests/_base/Color.js32
-rw-r--r--includes/js/dojo/tests/_base/Deferred.js76
-rw-r--r--includes/js/dojo/tests/_base/NodeList.html370
-rw-r--r--includes/js/dojo/tests/_base/_loader/addLoadEvents.html37
-rw-r--r--includes/js/dojo/tests/_base/_loader/afterOnLoad.html56
-rw-r--r--includes/js/dojo/tests/_base/_loader/bootstrap.js86
-rw-r--r--includes/js/dojo/tests/_base/_loader/getText.txt1
-rw-r--r--includes/js/dojo/tests/_base/_loader/hostenv_browser.js15
-rw-r--r--includes/js/dojo/tests/_base/_loader/hostenv_rhino.js17
-rw-r--r--includes/js/dojo/tests/_base/_loader/hostenv_spidermonkey.js15
-rw-r--r--includes/js/dojo/tests/_base/_loader/loader.js52
-rw-r--r--includes/js/dojo/tests/_base/_loader/scope/scope04.html80
-rw-r--r--includes/js/dojo/tests/_base/_loader/scope/scopeContained.html71
-rw-r--r--includes/js/dojo/tests/_base/_loader/scope/scopeContainedXd.html84
-rw-r--r--includes/js/dojo/tests/_base/_loader/scope/scopeDjConfig.html64
-rw-r--r--includes/js/dojo/tests/_base/_loader/scope/scopeSingle.html62
-rw-r--r--includes/js/dojo/tests/_base/_loader/scope/scopeSingleDaac.html63
-rw-r--r--includes/js/dojo/tests/_base/array.js301
-rw-r--r--includes/js/dojo/tests/_base/connect.js225
-rw-r--r--includes/js/dojo/tests/_base/declare.js197
-rw-r--r--includes/js/dojo/tests/_base/fx.html342
-rw-r--r--includes/js/dojo/tests/_base/fx.js8
-rw-r--r--includes/js/dojo/tests/_base/fx_delay.html22
-rw-r--r--includes/js/dojo/tests/_base/html.html556
-rw-r--r--includes/js/dojo/tests/_base/html.js12
-rw-r--r--includes/js/dojo/tests/_base/html_box.html207
-rw-r--r--includes/js/dojo/tests/_base/html_box_quirks.html205
-rw-r--r--includes/js/dojo/tests/_base/html_quirks.html322
-rw-r--r--includes/js/dojo/tests/_base/html_rtl.html110
-rw-r--r--includes/js/dojo/tests/_base/json.js37
-rw-r--r--includes/js/dojo/tests/_base/lang.js180
-rw-r--r--includes/js/dojo/tests/_base/query.html154
-rw-r--r--includes/js/dojo/tests/_base/query.js9
-rw-r--r--includes/js/dojo/tests/_base/timeout.php7
-rw-r--r--includes/js/dojo/tests/_base/xhr.html404
-rw-r--r--includes/js/dojo/tests/_base/xhr.js8
-rw-r--r--includes/js/dojo/tests/_base/xhrDummyMethod.php7
-rw-r--r--includes/js/dojo/tests/back-hash.js33
-rw-r--r--includes/js/dojo/tests/back.html107
-rw-r--r--includes/js/dojo/tests/back.js8
-rw-r--r--includes/js/dojo/tests/behavior.html106
-rw-r--r--includes/js/dojo/tests/behavior.js8
-rw-r--r--includes/js/dojo/tests/cldr.js19
-rw-r--r--includes/js/dojo/tests/colors.js48
-rw-r--r--includes/js/dojo/tests/cookie.html84
-rw-r--r--includes/js/dojo/tests/cookie.js8
-rw-r--r--includes/js/dojo/tests/currency.js48
-rw-r--r--includes/js/dojo/tests/data.js12
-rw-r--r--includes/js/dojo/tests/data/ItemFileReadStore.js10
-rw-r--r--includes/js/dojo/tests/data/ItemFileWriteStore.js1402
-rw-r--r--includes/js/dojo/tests/data/countries.json11
-rw-r--r--includes/js/dojo/tests/data/countries_commentFiltered.json12
-rw-r--r--includes/js/dojo/tests/data/countries_idcollision.json10
-rw-r--r--includes/js/dojo/tests/data/countries_references.json44
-rw-r--r--includes/js/dojo/tests/data/countries_withBoolean.json11
-rw-r--r--includes/js/dojo/tests/data/countries_withDates.json21
-rw-r--r--includes/js/dojo/tests/data/countries_withNull.json10
-rw-r--r--includes/js/dojo/tests/data/countries_withoutid.json10
-rw-r--r--includes/js/dojo/tests/data/data_multitype.json18
-rw-r--r--includes/js/dojo/tests/data/geography_hierarchy_large.json44
-rw-r--r--includes/js/dojo/tests/data/geography_hierarchy_small.json19
-rw-r--r--includes/js/dojo/tests/data/readOnlyItemFileTestTemplates.js2260
-rw-r--r--includes/js/dojo/tests/data/reference_integrity.json27
-rw-r--r--includes/js/dojo/tests/data/runTests.html9
-rw-r--r--includes/js/dojo/tests/data/utils.js203
-rw-r--r--includes/js/dojo/tests/date.js716
-rw-r--r--includes/js/dojo/tests/date/locale.js398
-rw-r--r--includes/js/dojo/tests/date/stamp.js94
-rw-r--r--includes/js/dojo/tests/dnd/dndDefault.css52
-rw-r--r--includes/js/dojo/tests/dnd/dndDefault.css.commented.css69
-rw-r--r--includes/js/dojo/tests/dnd/flickr_viewer.html168
-rw-r--r--includes/js/dojo/tests/dnd/test_box_constraints.html61
-rw-r--r--includes/js/dojo/tests/dnd/test_container.html74
-rw-r--r--includes/js/dojo/tests/dnd/test_container_markup.html67
-rw-r--r--includes/js/dojo/tests/dnd/test_custom_constraints.html51
-rw-r--r--includes/js/dojo/tests/dnd/test_dnd.html130
-rw-r--r--includes/js/dojo/tests/dnd/test_dnd_handles.html65
-rw-r--r--includes/js/dojo/tests/dnd/test_form.html103
-rw-r--r--includes/js/dojo/tests/dnd/test_moveable.html106
-rw-r--r--includes/js/dojo/tests/dnd/test_moveable_markup.html83
-rw-r--r--includes/js/dojo/tests/dnd/test_params.html61
-rw-r--r--includes/js/dojo/tests/dnd/test_parent_constraints.html53
-rw-r--r--includes/js/dojo/tests/dnd/test_parent_constraints_margins.html51
-rw-r--r--includes/js/dojo/tests/dnd/test_selector.html80
-rw-r--r--includes/js/dojo/tests/dnd/test_selector_markup.html71
-rw-r--r--includes/js/dojo/tests/dnd/test_timed_moveable.html112
-rw-r--r--includes/js/dojo/tests/fx.html310
-rw-r--r--includes/js/dojo/tests/fx.js9
-rw-r--r--includes/js/dojo/tests/i18n.js88
-rw-r--r--includes/js/dojo/tests/io/iframe.html124
-rw-r--r--includes/js/dojo/tests/io/iframe.js8
-rw-r--r--includes/js/dojo/tests/io/iframeResponse.html8
-rw-r--r--includes/js/dojo/tests/io/iframeResponse.js.html7
-rw-r--r--includes/js/dojo/tests/io/iframeResponse.json.html7
-rw-r--r--includes/js/dojo/tests/io/iframeResponse.text.html7
-rw-r--r--includes/js/dojo/tests/io/iframeUploadTest.html50
-rw-r--r--includes/js/dojo/tests/io/script.html101
-rw-r--r--includes/js/dojo/tests/io/script.js8
-rw-r--r--includes/js/dojo/tests/io/scriptJsonp.js57
-rw-r--r--includes/js/dojo/tests/io/scriptSimple.js5
-rw-r--r--includes/js/dojo/tests/io/scriptTimeout.html67
-rw-r--r--includes/js/dojo/tests/io/upload.cgi60
-rw-r--r--includes/js/dojo/tests/manualTests.html12
-rw-r--r--includes/js/dojo/tests/manualTests.js45
-rw-r--r--includes/js/dojo/tests/module.js29
-rw-r--r--includes/js/dojo/tests/nls/ar/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/cs/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/de/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/el/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/en-au/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/en-us-hawaii/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/en-us-new_york-brooklyn/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/en-us-texas/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/es/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/fa/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/fr/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/he/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/hi/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/it/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/ja/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/ko/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/pl/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/pt/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/ru/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/sw/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/th/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/tr/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/yi/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/zh-cn/salutations.js1
-rw-r--r--includes/js/dojo/tests/nls/zh-tw/salutations.js1
-rw-r--r--includes/js/dojo/tests/number.js966
-rw-r--r--includes/js/dojo/tests/parser.html241
-rw-r--r--includes/js/dojo/tests/parser.js8
-rw-r--r--includes/js/dojo/tests/resources/ApplicationState.js28
-rw-r--r--includes/js/dojo/tests/resources/JSON.php724
-rw-r--r--includes/js/dojo/tests/resources/testClass.php20
-rw-r--r--includes/js/dojo/tests/resources/testClass.smd40
-rw-r--r--includes/js/dojo/tests/resources/test_JsonRPCMediator.php43
-rw-r--r--includes/js/dojo/tests/resources/test_css.html100
-rw-r--r--includes/js/dojo/tests/resources/yahoo_smd_v1.smd268
-rw-r--r--includes/js/dojo/tests/rpc.js151
-rw-r--r--includes/js/dojo/tests/runTests.html9
-rw-r--r--includes/js/dojo/tests/string.js31
-rw-r--r--includes/js/dojo/tests/test_FirebugLite.html100
-rw-r--r--includes/js/dojo/tests/test_FirebugLitePopup.html101
-rw-r--r--includes/js/dojo/tests/test_fx.html107
152 files changed, 16304 insertions, 0 deletions
diff --git a/includes/js/dojo/tests/AdapterRegistry.js b/includes/js/dojo/tests/AdapterRegistry.js
new file mode 100644
index 0000000..4565e27
--- /dev/null
+++ b/includes/js/dojo/tests/AdapterRegistry.js
@@ -0,0 +1,75 @@
+if(!dojo._hasResource["tests.AdapterRegistry"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.AdapterRegistry"] = true;
+dojo.provide("tests.AdapterRegistry");
+dojo.require("dojo.AdapterRegistry");
+
+doh.register("tests.AdapterRegistry",
+ [
+ function ctor(t){
+ var taa = new dojo.AdapterRegistry();
+ t.is(0, taa.pairs.length);
+ t.f(taa.returnWrappers);
+
+ var taa = new dojo.AdapterRegistry(true);
+ t.t(taa.returnWrappers);
+ },
+
+ function register(t){
+ var taa = new dojo.AdapterRegistry();
+ taa.register("blah",
+ function(str){ return str == "blah"; },
+ function(){ return "blah"; }
+ );
+ t.is(1, taa.pairs.length);
+ t.is("blah", taa.pairs[0][0]);
+
+ taa.register("thinger");
+ taa.register("prepend", null, null, true, true);
+ t.is("prepend", taa.pairs[0][0]);
+ t.t(taa.pairs[0][3]);
+ },
+
+ /*
+ function match(t){
+ },
+ */
+
+ function noMatch(t){
+ var taa = new dojo.AdapterRegistry();
+ var threw = false;
+ try{
+ taa.match("blah");
+ }catch(e){
+ threw = true;
+ }
+ t.t(threw);
+ },
+
+ function returnWrappers(t){
+ var taa = new dojo.AdapterRegistry();
+ taa.register("blah",
+ function(str){ return str == "blah"; },
+ function(){ return "blah"; }
+ );
+ t.is("blah", taa.match("blah"));
+
+ taa.returnWrappers = true;
+ t.is("blah", taa.match("blah")());
+ },
+
+ function unregister(t){
+ var taa = new dojo.AdapterRegistry();
+ taa.register("blah",
+ function(str){ return str == "blah"; },
+ function(){ return "blah"; }
+ );
+ taa.register("thinger");
+ taa.register("prepend", null, null, true, true);
+ taa.unregister("prepend");
+ t.is(2, taa.pairs.length);
+ t.is("blah", taa.pairs[0][0]);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/DeferredList.js b/includes/js/dojo/tests/DeferredList.js
new file mode 100644
index 0000000..9353bfa
--- /dev/null
+++ b/includes/js/dojo/tests/DeferredList.js
@@ -0,0 +1,206 @@
+if(!dojo._hasResource["tests.DeferredList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.DeferredList"] = true;
+dojo.provide("tests.DeferredList");
+
+dojo.require("dojo.DeferredList");
+
+doh.register("tests.DeferredList",
+ [
+ function callback(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = new dojo.DeferredList([d1, d2]);
+ var fired = false;
+
+ dl.addCallback(function(res){
+ doh.debug("debug from dojo.DeferredList callback");
+ return res;
+ });
+ dl.addCallback(function(res){
+ console.log("res: ", res, res.length);
+ t.assertTrue(res.length == 2);
+ t.assertTrue(res[0][0]);
+ t.assertEqual(res[0][1], "foo");
+ t.assertTrue(res[1][0]);
+ t.assertEqual(res[1][1], "bar");
+ fired = true;
+ return res;
+ });
+ d1.callback("foo");
+ d2.callback("bar");
+ t.assertTrue(fired);
+ },
+
+ function errback(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = new dojo.DeferredList([d1, d2]);
+ var fired = false;
+ var e1 = new Error("foo");
+ var e2 = new Error("bar");
+
+ dl.addCallback(function(res){
+ doh.debug("debug from dojo.DeferredList callback");
+ return res;
+ });
+ dl.addCallback(function(res){
+ t.assertTrue(res.length == 2);
+ t.assertTrue(!res[0][0]);
+
+ t.assertEqual(res[0][1], e1);
+ t.assertTrue(!res[1][0]);
+ t.assertEqual(res[1][1], e2);
+ fired = true;
+ return res;
+ });
+ d1.errback(e1);
+ d2.errback(e2);
+ t.assertTrue(fired);
+ },
+
+
+ function mixed(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = new dojo.DeferredList([d1, d2]);
+ var fired = false;
+ var e = new Error("foo");
+
+ dl.addCallback(function(res){
+ doh.debug("debug from dojo.DeferredList callback");
+ return res;
+ });
+ dl.addCallback(function(res){
+ t.assertTrue(res.length == 2);
+ t.assertTrue(!res[0][0]);
+
+ t.assertEqual(res[0][1], e);
+ t.assertTrue(res[1][0]);
+ t.assertEqual(res[1][1], "bar");
+ fired = true;
+ return res;
+ });
+ d1.errback(e);
+ d2.callback("bar");
+ t.assertTrue(fired);
+ },
+
+ function gather(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = dojo.DeferredList.prototype.gatherResults([d1, d2]);
+ var fired = false;
+ dl.addCallback(function(res){
+ t.assertEqual(res[0], "foo");
+ t.assertEqual(res[1], "bar");
+ fired = true;
+ return res;
+ });
+ d1.callback("foo");
+ d2.callback("bar");
+ t.assertTrue(fired);
+ }
+ ]
+);
+dojo.provide("tests.DeferredList");
+
+dojo.require("dojo.DeferredList");
+
+doh.register("tests.DeferredList",
+ [
+ function callback(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = new dojo.DeferredList([d1, d2]);
+ var fired = false;
+ dl.addCallback(function(res){
+ doh.debug("debug from dojo.DeferredList callback");
+ return res;
+ });
+ dl.addCallback(function(res){
+ t.assertTrue(res.length == 2);
+ t.assertTrue(res[0][0]);
+ t.assertEqual(res[0][1], "foo");
+ t.assertTrue(res[1][0]);
+ t.assertEqual(res[1][1], "bar");
+ fired = true;
+ return res;
+ });
+ d1.callback("foo");
+ d2.callback("bar");
+ t.assertTrue(fired);
+ },
+
+ function errback(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = new dojo.DeferredList([d1, d2]);
+ var fired = false;
+ var e1 = new Error("foo");
+ var e2 = new Error("bar");
+
+ dl.addCallback(function(res){
+ doh.debug("debug from dojo.DeferredList callback");
+ return res;
+ });
+ dl.addCallback(function(res){
+ t.assertTrue(res.length == 2);
+ t.assertTrue(!res[0][0]);
+
+ t.assertEqual(res[0][1], e1);
+ t.assertTrue(!res[1][0]);
+ t.assertEqual(res[1][1], e2);
+ fired = true;
+ return res;
+ });
+ d1.errback(e1);
+ d2.errback(e2);
+ t.assertTrue(fired);
+ },
+
+
+ function mixed(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = new dojo.DeferredList([d1, d2]);
+ var fired = false;
+ var e = new Error("foo");
+
+ dl.addCallback(function(res){
+ doh.debug("debug from dojo.DeferredList callback");
+ return res;
+ });
+ dl.addCallback(function(res){
+ t.assertTrue(res.length == 2);
+ t.assertTrue(!res[0][0]);
+
+ t.assertEqual(res[0][1], e);
+ t.assertTrue(res[1][0]);
+ t.assertEqual(res[1][1], "bar");
+ fired = true;
+ return res;
+ });
+ d1.errback(e);
+ d2.callback("bar");
+ t.assertTrue(fired);
+ },
+
+ function gather(t){
+ var d1 = new dojo.Deferred();
+ var d2 = new dojo.Deferred();
+ var dl = dojo.DeferredList.prototype.gatherResults([d1, d2]);
+ var fired = false;
+ dl.addCallback(function(res){
+ t.assertEqual(res[0], "foo");
+ t.assertEqual(res[1], "bar");
+ fired = true;
+ return res;
+ });
+ d1.callback("foo");
+ d2.callback("bar");
+ t.assertTrue(fired);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/NodeList-fx.html b/includes/js/dojo/tests/NodeList-fx.html
new file mode 100644
index 0000000..07fdbe0
--- /dev/null
+++ b/includes/js/dojo/tests/NodeList-fx.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing dojo.fx extensions to dojo.NodeList</title>
+ <style type="text/css">
+ @import "../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../dojo.js" djConfig="isDebug: true, popup: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.NodeList-fx");
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function fadeOut(){
+ dojo.query("p").style("opacity", 1);
+ var anim = dojo.query("p").fadeOut();
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ doh.t(dojo.query("p").every(function(item){
+ return dojo.style(item, "opacity") == 0;
+ }));
+ d.callback(true);
+ });
+ anim.play();
+ return d;
+ },
+ function fadeIn(){
+ dojo.query("p").style("opacity", 0);
+ var anim = dojo.query("p").fadeIn();
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ doh.t(dojo.query("p").every(function(item){
+ return dojo.style(item, "opacity") == 1;
+ }));
+ d.callback(true);
+ });
+ anim.play();
+ return d;
+ },
+ function wipeOut(){
+ dojo.query("p").style("height", "");
+ var anim = dojo.query("p").wipeOut();
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ doh.t(dojo.query("p").every(function(item){
+ return dojo.style(item, "height") == 0;
+ }));
+ d.callback(true);
+ });
+ anim.play();
+ return d;
+ },
+ function wipeIn(){
+ dojo.query("p").style("height", 0);
+ var anim = dojo.query("p").wipeIn();
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ doh.t(dojo.query("p").every(function(item){
+ // FIXME: need a more robust test for "have wiped all the way in"
+ return dojo.style(item, "height") != 0;
+ }));
+ d.callback(true);
+ });
+ anim.play();
+ return d;
+ },
+ function slideTo(){
+ var anim = dojo.query("p").slideTo({
+ left: 500
+ });
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ doh.t(dojo.query("p").every(function(item){
+ // FIXME: need a more robust test for "have wiped all the way in"
+ return dojo.style(item, "left") == 500;
+ }));
+ d.callback(true);
+ });
+ anim.play();
+ return d;
+ },
+ function anim(){
+ dojo.query("p").style("position", "");
+ dojo.query("p").style("left", "");
+ var anim = dojo.query("p").anim({
+ width: 500
+ });
+ console.debug(anim);
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ /*
+ doh.t(dojo.query("p").every(function(item){
+ // FIXME: need a more robust test for "have wiped all the way in"
+ return dojo.style(item, "width") == 500;
+ }));
+ */
+ d.callback(true);
+ });
+ return d;
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ </head>
+ <body>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper
+ sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta
+ rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+ Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+ Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+ risus.
+ </p>
+ <p>
+ Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+ imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+ nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+ massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+ pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+ quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+ felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+ quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+ rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+ semper velit ante id metus. Praesent massa dolor, porttitor sed,
+ pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+ tortor pharetra congue. Suspendisse pulvinar.
+ </p>
+ <p>
+ Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+ imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+ nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+ massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+ pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+ quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+ felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+ quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+ rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+ semper velit ante id metus. Praesent massa dolor, porttitor sed,
+ pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+ tortor pharetra congue. Suspendisse pulvinar.
+ </p>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/TODO b/includes/js/dojo/tests/TODO
new file mode 100644
index 0000000..c18bc3a
--- /dev/null
+++ b/includes/js/dojo/tests/TODO
@@ -0,0 +1,11 @@
+This file lists tests that need to be implemented or expanded. See ticket #3121
+for changes related to things listed here.
+
+Tests to add:
+-------------
+ * add tests for dojo.place()
+
+Tests to improve:
+-----------------
+ * cookie tests don't seem to test expiry or date functions
+ * NodeList isn't testing several of its public methods (place, orphan, adopt, etc.)
diff --git a/includes/js/dojo/tests/_base.js b/includes/js/dojo/tests/_base.js
new file mode 100644
index 0000000..7bc5301
--- /dev/null
+++ b/includes/js/dojo/tests/_base.js
@@ -0,0 +1,136 @@
+if(!dojo._hasResource["tests._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base"] = true;
+var testGlobal = this;
+try{
+ dojo.provide("tests._base");
+ testGlobal = dojo.global;
+}catch(e){ }
+
+// the test suite for the bootstrap. Requires hostenv and other base tests at
+// the end
+
+if(doh.selfTest){
+
+ doh.register("doh.smokeTest",
+ [
+ function sanityCheckHarness(t){
+ // sanity checks
+ t.assertTrue(true);
+ t.assertFalse(false);
+ t.assertFalse(0);
+ t.assertFalse(null);
+ var tObj = { w00t: false, blarg: true };
+ t.assertEqual(
+ ["thinger", "blah", tObj],
+ ["thinger", "blah", tObj]
+ );
+ t.assertEqual(tObj, tObj);
+ },
+ /*
+ // uncomment to tests exception handling
+ function sanityCheckassertTrue(t){
+ // should throw an error
+ t.assertTrue(false);
+ },
+ function sanityCheckassertFalse(t){
+ // should throw an error
+ t.assertFalse(true);
+ },
+ function sanityCheckassertEqual(t){
+ // should throw an error
+ t.assertEqual("foo", "bar");
+ },
+ */
+ {
+ name: "eqTest",
+ // smoke test the fixture system
+ setUp: function(t){
+ this.foo = "blah";
+ },
+ runTest: function(t){
+ t.assertEqual("blah", this.foo);
+ },
+ tearDown: function(t){
+ }
+ }
+ ]
+ );
+
+ if(testGlobal["dojo"]){
+ doh.register("tests._base",
+ [
+ function dojoIsAvailable(t){
+ t.assertTrue(testGlobal["dojo"]);
+ }
+ ]
+ );
+ }
+
+ if(testGlobal["setTimeout"]){
+ // a stone-stupid async test
+ doh.register("tests.async",
+ [
+ {
+ name: "deferredSuccess",
+ runTest: function(t){
+ var d = new doh.Deferred();
+ setTimeout(d.getTestCallback(function(){
+ t.assertTrue(true);
+ t.assertFalse(false);
+ }), 50);
+ return d;
+ }
+ },
+ {
+ name: "deferredFailure",
+ runTest: function(t){
+ var d = new doh.Deferred();
+ setTimeout(function(){
+ d.errback(new Error("hrm..."));
+ }, 50);
+ return d;
+ }
+ },
+ {
+ name: "timeoutFailure",
+ timeout: 50,
+ runTest: function(t){
+ // timeout of 50
+ var d = new doh.Deferred();
+ setTimeout(function(){
+ d.callback(true);
+ }, 100);
+ return d;
+ }
+ }
+ ]
+ );
+ }
+}
+
+try{
+ // go grab the others
+ dojo.require("tests._base._loader.bootstrap");
+ dojo.require("tests._base._loader.loader");
+ dojo.platformRequire({
+ browser: ["tests._base._loader.hostenv_browser"],
+ rhino: ["tests._base._loader.hostenv_rhino"],
+ spidermonkey: ["tests._base._loader.hostenv_spidermonkey"]
+ });
+ dojo.require("tests._base.array");
+ dojo.require("tests._base.Color");
+ dojo.require("tests._base.lang");
+ dojo.require("tests._base.declare");
+ dojo.require("tests._base.connect");
+ dojo.require("tests._base.Deferred");
+ dojo.require("tests._base.json");
+ // FIXME: add test includes for the rest of the Dojo Base groups here
+ dojo.requireIf(dojo.isBrowser, "tests._base.html");
+ dojo.requireIf(dojo.isBrowser, "tests._base.fx");
+ dojo.requireIf(dojo.isBrowser, "tests._base.query");
+ dojo.requireIf(dojo.isBrowser, "tests._base.xhr");
+}catch(e){
+ doh.debug(e);
+}
+
+}
diff --git a/includes/js/dojo/tests/_base/Color.js b/includes/js/dojo/tests/_base/Color.js
new file mode 100644
index 0000000..fa09842
--- /dev/null
+++ b/includes/js/dojo/tests/_base/Color.js
@@ -0,0 +1,32 @@
+if(!dojo._hasResource["tests._base.Color"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.Color"] = true;
+dojo.provide("tests._base.Color");
+
+(function(){
+ var white = dojo.colorFromString("white").toRgba();
+ var maroon = dojo.colorFromString("maroon").toRgba();
+ var verifyColor = function(t, source, expected){
+ var color = new dojo.Color(source);
+ t.is(expected, color.toRgba());
+ dojo.forEach(color.toRgba(), function(n){ t.is("number", typeof(n)); });
+ }
+
+ doh.register("tests._base.Color",
+ [
+ function testColor1(t){ verifyColor(t, "maroon", maroon); },
+ function testColor2(t){ verifyColor(t, "white", white); },
+ function testColor3(t){ verifyColor(t, "#fff", white); },
+ function testColor4(t){ verifyColor(t, "#ffffff", white); },
+ function testColor5(t){ verifyColor(t, "rgb(255,255,255)", white); },
+ function testColor6(t){ verifyColor(t, "#800000", maroon); },
+ function testColor7(t){ verifyColor(t, "rgb(128, 0, 0)", maroon); },
+ function testColor8(t){ verifyColor(t, "rgba(128, 0, 0, 0.5)", [128, 0, 0, 0.5]); },
+ function testColor9(t){ verifyColor(t, maroon, maroon); },
+ function testColor10(t){ verifyColor(t, [1, 2, 3], [1, 2, 3, 1]); },
+ function testColor11(t){ verifyColor(t, [1, 2, 3, 0.5], [1, 2, 3, 0.5]); },
+ function testColor12(t){ verifyColor(t, dojo.blendColors(new dojo.Color("black"), new dojo.Color("white"), 0.5), [128, 128, 128, 1]); }
+ ]
+ );
+})();
+
+}
diff --git a/includes/js/dojo/tests/_base/Deferred.js b/includes/js/dojo/tests/_base/Deferred.js
new file mode 100644
index 0000000..5dcf003
--- /dev/null
+++ b/includes/js/dojo/tests/_base/Deferred.js
@@ -0,0 +1,76 @@
+if(!dojo._hasResource["tests._base.Deferred"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.Deferred"] = true;
+dojo.provide("tests._base.Deferred");
+
+doh.register("tests._base.Deferred",
+ [
+
+ function callback(t){
+ var nd = new dojo.Deferred();
+ var cnt = 0;
+ nd.addCallback(function(res){
+ doh.debug("debug from dojo.Deferred callback");
+ return res;
+ });
+ nd.addCallback(function(res){
+ // t.debug("val:", res);
+ cnt+=res;
+ return cnt;
+ });
+ nd.callback(5);
+ // t.debug("cnt:", cnt);
+ t.assertEqual(cnt, 5);
+ },
+
+ function callback_extra_args(t){
+ var nd = new dojo.Deferred();
+ var cnt = 0;
+ nd.addCallback(dojo.global, function(base, res){ cnt+=base; cnt+=res; return cnt; }, 30);
+ nd.callback(5);
+ t.assertEqual(cnt, 35);
+ },
+
+ function errback(t){
+ var nd = new dojo.Deferred();
+ var cnt = 0;
+ nd.addErrback(function(val){
+ return ++cnt;
+ });
+ nd.errback();
+ t.assertEqual(cnt, 1);
+ },
+
+ function callbackTwice(t){
+ var nd = new dojo.Deferred();
+ var cnt = 0;
+ nd.addCallback(function(res){
+ return ++cnt;
+ });
+ nd.callback();
+ t.assertEqual(cnt, 1);
+ var thrown = false;
+ try{
+ nd.callback();
+ }catch(e){
+ thrown = true;
+ }
+ t.assertTrue(thrown);
+ },
+
+ function addBoth(t){
+ var nd = new dojo.Deferred();
+ var cnt = 0;
+ nd.addBoth(function(res){
+ return ++cnt;
+ });
+ nd.callback();
+ t.assertEqual(cnt, 1);
+
+ // nd.callback();
+ // t.debug(cnt);
+ // t.assertEqual(cnt, 1);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/NodeList.html b/includes/js/dojo/tests/_base/NodeList.html
new file mode 100644
index 0000000..e3f08c5
--- /dev/null
+++ b/includes/js/dojo/tests/_base/NodeList.html
@@ -0,0 +1,370 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+ we use a strict-mode DTD to ensure that the box model is the same for these
+ basic tests
+-->
+<html>
+ <head>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ html, body {
+ padding: 0px;
+ margin: 0px;
+ border: 0px;
+ }
+
+ #sq100 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ </style>
+ <title>testing dojo.NodeList</title>
+ <script type="text/javascript" src="../../dojo.js"
+ djConfig="isDebug: true, noFirebugLite: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.addOnLoad(function(){
+ var c = dojo.byId("c1");
+ var t = dojo.byId("t");
+ var s = dojo.byId("sq100");
+ var fourElementNL = new dojo.NodeList(c, t, c, t);
+ doh.register("t",
+ [
+ // constructor tests
+ function ctor(){
+ var nl = new dojo.NodeList();
+ nl.push(c);
+ doh.is(1, nl.length);
+ },
+ function ctorArgs(){
+ var nl = new dojo.NodeList(4);
+ nl.push(c);
+ doh.is(5, nl.length);
+ },
+ function ctorArgs2(){
+ var nl = new dojo.NodeList(c, t);
+ doh.is(2, nl.length);
+ doh.is(c, nl[0]);
+ doh.is(t, nl[1]);
+ },
+ // iteration and array tests
+ function forEach(){
+ var lastItem;
+ var nl = new dojo.NodeList(c, t);
+ nl.forEach(function(i){ lastItem = i; });
+ doh.is(t, lastItem);
+
+ var r = nl.forEach(function(i, idx, arr){
+ doh.t(arr.constructor == dojo.NodeList);
+ doh.is(2, arr.length);
+ });
+ doh.t(r.constructor == dojo.NodeList);
+ doh.is(r, nl);
+ },
+
+ function indexOf(){
+ doh.is(0, fourElementNL.indexOf(c));
+ doh.is(1, fourElementNL.indexOf(t));
+ doh.is(-1, fourElementNL.indexOf(null));
+ },
+
+ function lastIndexOf(){
+ doh.is(2, fourElementNL.lastIndexOf(c));
+ doh.is(3, fourElementNL.lastIndexOf(t));
+ doh.is(-1, fourElementNL.lastIndexOf(null));
+ },
+
+ function every(){
+ var ctr = 0;
+ var ret = fourElementNL.every(function(){
+ ctr++;
+ return true;
+ });
+ doh.is(4, ctr);
+ doh.t(ret);
+
+ ctr = 0;
+ var ret = fourElementNL.every(function(){
+ ctr++;
+ return false;
+ });
+ doh.is(1, ctr);
+ doh.f(ret);
+ },
+
+ function some(){
+ var ret = fourElementNL.some(function(){
+ return true;
+ });
+ doh.t(ret);
+
+ var ret = fourElementNL.some(function(i){
+ return (i.id == "t");
+ });
+ doh.t(ret);
+ },
+
+ function map(){
+ var ret = fourElementNL.map(function(){
+ return true;
+ });
+
+ doh.is(ret, [true, true, true, true]);
+ var cnt = 0;
+ var ret = fourElementNL.map(function(){
+ return cnt++;
+ });
+ // doh.is(ret, [0, 1, 2, 3]);
+
+ doh.t(ret.constructor == dojo.NodeList);
+
+ // make sure that map() returns a NodeList
+ var sum = 0;
+ fourElementNL.map(function(){ return 2; }).forEach( function(x){ sum += x; } );
+ doh.is(sum, 8);
+ },
+
+ function slice(){
+ var pnl = new dojo.NodeList(t, t, c);
+ doh.is(2, pnl.slice(1).length);
+ doh.is(3, pnl.length);
+ doh.is(c, pnl.slice(-1)[0]);
+ doh.is(2, pnl.slice(-2).length);
+ },
+
+ function splice(){
+ var pnl = new dojo.NodeList(t, t, c);
+ console.debug(pnl.splice(1));
+ /*
+ doh.is(2, pnl.splice(1).length);
+ doh.is(1, pnl.length);
+ pnl = new dojo.NodeList(t, t, c);
+ doh.is(c, pnl.splice(-1)[0]);
+ doh.is(2, pnl.length);
+ pnl = new dojo.NodeList(t, t, c);
+ doh.is(2, pnl.splice(-2).length);
+ */
+ },
+
+ function spliceInsert(){
+ // insert 1
+ var pnl = new dojo.NodeList(t, t, c);
+ pnl.splice(0, 0, c);
+ doh.is(4, pnl.length);
+ doh.is(c, pnl[0]);
+
+ // insert multiple
+ pnl = new dojo.NodeList(t, t, c);
+ pnl.splice(0, 0, c, s);
+ doh.is(5, pnl.length);
+ doh.is(c, pnl[0]);
+ doh.is(s, pnl[1]);
+ doh.is(t, pnl[2]);
+
+ // insert multiple at offset
+ pnl = new dojo.NodeList(t, t, c);
+ pnl.splice(1, 0, c, s);
+ doh.is(5, pnl.length);
+ doh.is(t, pnl[0]);
+ doh.is(c, pnl[1]);
+ doh.is(s, pnl[2]);
+ doh.is(t, pnl[3]);
+ },
+
+ function spliceDel(){
+ // clobbery 1
+ var pnl = new dojo.NodeList(c, t, s);
+ pnl.splice(0, 1);
+ doh.is(2, pnl.length);
+ doh.is(t, pnl[0]);
+
+ // clobber multiple
+ pnl = new dojo.NodeList(c, t, s);
+ pnl.splice(0, 2);
+ doh.is(1, pnl.length);
+ doh.is(s, pnl[0]);
+
+ // ...at an offset
+ pnl = new dojo.NodeList(c, t, s);
+ pnl.splice(1, 1);
+ doh.is(2, pnl.length);
+ doh.is(c, pnl[0]);
+ doh.is(s, pnl[1]);
+
+ },
+
+ function spliceInsertDel(){
+ // clobbery 1
+ var pnl = new dojo.NodeList(c, t, s);
+ pnl.splice(1, 1, s);
+ doh.is(3, pnl.length);
+ doh.is(dojo.NodeList(c, s, s), pnl);
+
+ pnl = new dojo.NodeList(c, t, s);
+ pnl.splice(1, 2, s);
+ doh.is(2, pnl.length);
+ doh.is(dojo.NodeList(c, s), pnl);
+ },
+
+ // sub-search
+ function query(){
+ var pnl = new dojo.NodeList(t);
+ doh.is(c, pnl.query("span")[0]);
+ doh.is(t, dojo.query("body").query(":last-child")[0]);
+ doh.is(c, dojo.query("body").query(":last-child")[1]);
+ doh.is(1, pnl.query().length);
+ },
+
+ function filter(){
+ doh.is(dojo.query("body :first-child").filter(":last-child")[0], c);
+ doh.is(1, dojo.query("*").filter(function(n){ return (n.nodeName.toLowerCase() == "span"); }).length);
+
+ var filterObj = {
+ filterFunc: function(n){
+ return (n.nodeName.toLowerCase() == "span");
+ }
+ };
+ doh.is(1, dojo.query("*").filter(filterObj.filterFunc).length);
+ doh.is(1, dojo.query("*").filter(filterObj.filterFunc, filterObj).length);
+ },
+
+ // layout DOM functions
+ function coords(){
+ var tnl = new dojo.NodeList(dojo.byId('sq100'))
+ doh.t(dojo.isArray(tnl));
+ doh.is(100, tnl.coords()[0].w);
+ doh.is(100, tnl.coords()[0].h);
+ doh.is(document.body.getElementsByTagName("*").length, dojo.query("body *").coords().length);
+ },
+
+ function styleGet(){
+ // test getting
+ var tnl = new dojo.NodeList(s);
+ doh.is(1, tnl.style("opacity")[0]);
+ tnl.push(t);
+ dojo.style(t, "opacity", 0.5);
+ doh.is(0.5, tnl.style("opacity").slice(-1)[0]);
+ tnl.style("opacity", 1);
+ },
+
+ function styleSet(){
+ // test setting
+ var tnl = new dojo.NodeList(s, t);
+ tnl.style("opacity", 0.5);
+ doh.is(0.5, dojo.style(tnl[0], "opacity"));
+ doh.is(0.5, dojo.style(tnl[1], "opacity"));
+ // reset
+ tnl.style("opacity", 1);
+ },
+
+ function style(){
+ var tnl = new dojo.NodeList(s, t);
+ tnl.style("opacity", 1);
+ doh.is(1, tnl.style("opacity")[0]);
+ dojo.style(t, "opacity", 0.5);
+ doh.is(1.0, tnl.style("opacity")[0]);
+ doh.is(0.5, tnl.style("opacity")[1]);
+ // reset things
+ tnl.style("opacity", 1);
+ },
+
+ function concat(){
+ var spans = dojo.query("span");
+ var divs = dojo.query("div");
+ console.debug(spans.concat(divs));
+ doh.is(spans.concat(divs).constructor, dojo.NodeList);
+ doh.is((divs.length + spans.length), spans.concat(divs).length);
+ },
+
+ function concat2(t){
+ var spans = dojo.query("span");
+ var divs = dojo.query("div");
+ doh.is(spans.concat([]).constructor, dojo.NodeList);
+ },
+
+ function place(t){
+ var ih = "<div><span></span></div><span class='thud'><b>blah</b></span>";
+
+ var tn = document.createElement("div");
+ tn.innerHTML = ih;
+ dojo.body().appendChild(tn);
+ var nl = dojo.query("b", tn).place(tn, "first");
+ doh.t(nl.constructor == dojo.NodeList);
+ doh.is(1, nl.length);
+ doh.is("b", nl[0].nodeName.toLowerCase());
+ doh.is(tn, nl[0].parentNode);
+ doh.is(tn.firstChild, nl[0]);
+ },
+
+ function orphan(t){
+ var ih = "<div><span></span></div><span class='thud'><b>blah</b></span>";
+
+ var tn = document.createElement("div");
+ tn.innerHTML = ih;
+ dojo.body().appendChild(tn);
+ var nl = dojo.query("span", tn).orphan();
+ doh.t(nl.constructor == dojo.NodeList);
+
+ doh.is(2, nl.length);
+ doh.is(1, tn.getElementsByTagName("*").length);
+
+ tn.innerHTML = ih;
+ var nl = dojo.query("*", tn).orphan("b");
+ doh.is(1, nl.length);
+ doh.is("blah", nl[0].innerHTML);
+ },
+
+ /*
+ // FIXME
+ function adopt(t){
+ },
+
+ function addContent(t){
+ },
+ */
+
+ function connect(t){
+ var ih = "<div><span></span></div><span class='thud'><button>blah</button></span>";
+
+ var tn = document.createElement("div");
+ tn.innerHTML = ih;
+ dojo.body().appendChild(tn);
+
+ var ctr = 0;
+ var nl = dojo.query("button", tn).connect("onclick", function(){
+ ctr++;
+ });
+ nl[0].click();
+ doh.is(1, ctr);
+ nl[0].click();
+ nl[0].click();
+ doh.is(3, ctr);
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ </head>
+ <body>
+ <h1>testing dojo.NodeList</h1>
+ <div id="sq100">
+ 100px square, abs
+ </div>
+ <div id="t">
+ <span id="c1">c1</span>
+ </div>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/_loader/addLoadEvents.html b/includes/js/dojo/tests/_base/_loader/addLoadEvents.html
new file mode 100644
index 0000000..53e669f
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/addLoadEvents.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing dojo.addOnLoad() and dojo.addOnUnload()</title>
+ <script type="text/javascript"
+ src="../../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.addOnLoad(function(){
+ console.debug("addOnLoad(func) works");
+ });
+ var scope = {
+ named: function(){ console.debug("addOnLoad(obj, name) works"); },
+ refd: function(){ console.debug("addOnLoad(obj, func) works"); }
+ };
+ dojo.addOnLoad(scope, "named");
+ dojo.addOnLoad(scope, scope.refd);
+ // dojo.addOnLoad(scope, "named");
+ // dojo.addOnLoad(scope, scope.refd);
+
+ dojo.addOnUnload(function(){
+ alert("addOnUnload works");
+ });
+ </script>
+ </head>
+ <body>
+ <h1>Testing dojo.addOnLoad() and dojo.addOnUnload()</h1>
+
+ <p>This page has registers a function with dojo.addOnLoad() and dojo.addOnUnload.</p>
+
+ <p><b>dojo.addOnLoad()</b>: You should see an alert with the page first loads ("addOnLoad works").</p>
+
+ <p><b>dojo.addOnUnload()</b>: You should see an alert if the page is reloaded, or if you navigate to a
+ different web page ("addOnUnload works").
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/_loader/afterOnLoad.html b/includes/js/dojo/tests/_base/_loader/afterOnLoad.html
new file mode 100644
index 0000000..48ebd60
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/afterOnLoad.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing afterOnLoad</title>
+
+ <link rel="stylesheet" type="text/css" href="../../../resources/dojo.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+
+ <script type="text/javascript">
+ window.onload = function(){
+ //Create global djConfig object first. We cannot use the djConfig attribute
+ //on the script tag since it may not be visible in some browsers at the time
+ //dojo.js executes. This causes problems when the "require" property is used
+ //as part of djConfig. Also note that you have to set baseUrl directly, since
+ //it cannot be detected as part of script tag.
+ djConfig = {
+ baseUrl: "../../../",
+ parseOnLoad: true,
+ afterOnLoad:true,
+ require: [
+ 'dojo.parser',
+ 'dijit._Calendar'
+ ],
+ isDebug: true
+ };
+
+ var script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = "../../../dojo.js";
+
+ document.getElementsByTagName("head")[0].appendChild(script);
+ }
+
+ function myHandler(id,newValue){
+ console.debug("onChange for id = " + id + ", value: " + newValue);
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Testing afterOnLoad</h1>
+
+ <p><b>This page only works with a dojo build</b>. It will not work properly if you run it directly from the subversion source.</p>
+
+ <p>This page tests loading dojo after the page is loaded. </p>
+
+ <p>When the window.onload fires, the dojo script tag will be added to the DOM
+ and configured to fire the onload callbacks. If everything works, you should
+ see a Calendar below.</p>
+
+ <p class="tundra">
+ <input id="calendar1" dojoType="dijit._Calendar" onChange="myHandler(this.id,arguments[0])">
+ </p>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/_base/_loader/bootstrap.js b/includes/js/dojo/tests/_base/_loader/bootstrap.js
new file mode 100644
index 0000000..c2605cb
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/bootstrap.js
@@ -0,0 +1,86 @@
+if(!dojo._hasResource["tests._base._loader.bootstrap"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base._loader.bootstrap"] = true;
+dojo.provide("tests._base._loader.bootstrap");
+
+tests.register("tests._base._loader.bootstrap",
+ [
+
+ function hasConsole(t){
+ t.assertTrue("console" in dojo.global);
+ t.assertTrue("assert" in console);
+ t.assertEqual("function", typeof console.assert);
+ },
+
+ {
+ name: "getObject",
+ setUp: function(){
+ //Set an object in global scope.
+ dojo.global.globalValue = {
+ color: "blue",
+ size: 20
+ };
+
+ //Set up an object in a specific scope.
+ this.foo = {
+ bar: {
+ color: "red",
+ size: 100
+ }
+ };
+ },
+ runTest: function(t){
+ //Test for existing object using global as root path.
+ var globalVar = dojo.getObject("globalValue");
+ t.is("object", (typeof globalVar));
+ t.assertEqual("blue", globalVar.color);
+ t.assertEqual(20, globalVar.size);
+ t.assertEqual("blue", dojo.getObject("globalValue.color"));
+
+ //Test for non-existent object using global as root path.
+ //Then create it.
+ t.assertFalse(dojo.getObject("something.thatisNew"));
+ t.assertTrue(typeof(dojo.getObject("something.thatisNew", true)) == "object");
+
+ //Test for existing object using another object as root path.
+ var scopedVar = dojo.getObject("foo.bar", false, this);
+ t.assertTrue(typeof(scopedVar) == "object");
+ t.assertEqual("red", scopedVar.color);
+ t.assertEqual(100, scopedVar.size);
+ t.assertEqual("red", dojo.getObject("foo.bar.color", true, this));
+
+ //Test for existing object using another object as root path.
+ //Then create it.
+ t.assertFalse(dojo.getObject("something.thatisNew", false, this));
+ t.assertTrue(typeof(dojo.getObject("something.thatisNew", true, this)) == "object");
+ },
+ tearDown: function(){
+ //Clean up global object that should not exist if
+ //the test is re-run.
+ try{
+ delete dojo.global.something;
+ delete this.something;
+ }catch(e){}
+ }
+ },
+
+ {
+ name: "exists",
+ setUp: function(){
+ this.foo = {
+ bar: {}
+ };
+ },
+ runTest: function(t){
+ t.assertTrue(dojo.exists("foo.bar", this));
+ t.assertFalse(dojo.exists("foo.bar"));
+ }
+ },
+
+ function evalWorks(t){
+ t.assertTrue(dojo.eval("(true)"));
+ t.assertFalse(dojo.eval("(false)"));
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/_loader/getText.txt b/includes/js/dojo/tests/_base/_loader/getText.txt
new file mode 100644
index 0000000..054e8e8
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/getText.txt
@@ -0,0 +1 @@
+dojo._getText() test data \ No newline at end of file
diff --git a/includes/js/dojo/tests/_base/_loader/hostenv_browser.js b/includes/js/dojo/tests/_base/_loader/hostenv_browser.js
new file mode 100644
index 0000000..255fca5
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/hostenv_browser.js
@@ -0,0 +1,15 @@
+if(!dojo._hasResource["tests._base._loader.hostenv_browser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base._loader.hostenv_browser"] = true;
+dojo.provide("tests._base._loader.hostenv_browser");
+
+tests.register("tests._base._loader.hostenv_browser",
+ [
+ function getText(t){
+ var filePath = dojo.moduleUrl("tests._base._loader", "getText.txt");
+ var text = dojo._getText(filePath);
+ t.assertEqual("dojo._getText() test data", text);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/_loader/hostenv_rhino.js b/includes/js/dojo/tests/_base/_loader/hostenv_rhino.js
new file mode 100644
index 0000000..c121576
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/hostenv_rhino.js
@@ -0,0 +1,17 @@
+if(!dojo._hasResource["tests._base._loader.hostenv_rhino"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base._loader.hostenv_rhino"] = true;
+dojo.provide("tests._base._loader.hostenv_rhino");
+
+tests.register("tests._base._loader.hostenv_rhino",
+ [
+ function getText(t){
+ var filePath = dojo.moduleUrl("tests._base._loader", "getText.txt");
+ var text = (new String(readText(filePath)));
+ //The Java file read seems to add a line return.
+ text = text.replace(/[\r\n]+$/, "");
+ t.assertEqual("dojo._getText() test data", text);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/_loader/hostenv_spidermonkey.js b/includes/js/dojo/tests/_base/_loader/hostenv_spidermonkey.js
new file mode 100644
index 0000000..980d624
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/hostenv_spidermonkey.js
@@ -0,0 +1,15 @@
+if(!dojo._hasResource["tests._base._loader.hostenv_spidermonkey"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base._loader.hostenv_spidermonkey"] = true;
+dojo.provide("tests._base._loader.hostenv_spidermonkey");
+
+tests.register("tests._base._loader.hostenv_spidermonkey",
+ [
+ function getText(t){
+ var filePath = dojo.moduleUrl("tests._base._loader", "getText.txt");
+ var text = readText(filePath);
+ t.assertEqual("dojo._getText() test data", text);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/_loader/loader.js b/includes/js/dojo/tests/_base/_loader/loader.js
new file mode 100644
index 0000000..af1a338
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/loader.js
@@ -0,0 +1,52 @@
+if(!dojo._hasResource["tests._base._loader.loader"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base._loader.loader"] = true;
+dojo.provide("tests._base._loader.loader");
+
+tests.register("tests._base._loader.loader",
+ [
+ function baseUrl(t){
+ var originalBaseUrl = dojo.config["baseUrl"] || "./";
+
+ t.assertEqual(originalBaseUrl, dojo.baseUrl);
+ },
+
+ function modulePaths(t){
+ dojo.registerModulePath("mycoolmod", "../some/path/mycoolpath");
+ dojo.registerModulePath("mycoolmod.widget", "http://some.domain.com/another/path/mycoolpath/widget");
+
+ t.assertEqual("../some/path/mycoolpath/util", dojo._getModuleSymbols("mycoolmod.util").join("/"));
+ t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget", dojo._getModuleSymbols("mycoolmod.widget").join("/"));
+ t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget/thingy", dojo._getModuleSymbols("mycoolmod.widget.thingy").join("/"));
+ },
+
+ function moduleUrls(t){
+ dojo.registerModulePath("mycoolmod", "some/path/mycoolpath");
+ dojo.registerModulePath("mycoolmod2", "/some/path/mycoolpath2");
+ dojo.registerModulePath("mycoolmod.widget", "http://some.domain.com/another/path/mycoolpath/widget");
+
+
+ var basePrefix = dojo.baseUrl;
+ //dojo._Uri will strip off "./" characters, so do the same here
+ if(basePrefix == "./"){
+ basePrefix = "";
+ }
+
+ t.assertEqual(basePrefix + "some/path/mycoolpath/my/favorite.html",
+ dojo.moduleUrl("mycoolmod", "my/favorite.html").toString());
+ t.assertEqual(basePrefix + "some/path/mycoolpath/my/favorite.html",
+ dojo.moduleUrl("mycoolmod.my", "favorite.html").toString());
+
+ t.assertEqual("/some/path/mycoolpath2/my/favorite.html",
+ dojo.moduleUrl("mycoolmod2", "my/favorite.html").toString());
+ t.assertEqual("/some/path/mycoolpath2/my/favorite.html",
+ dojo.moduleUrl("mycoolmod2.my", "favorite.html").toString());
+
+ t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget/my/favorite.html",
+ dojo.moduleUrl("mycoolmod.widget", "my/favorite.html").toString());
+ t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget/my/favorite.html",
+ dojo.moduleUrl("mycoolmod.widget.my", "favorite.html").toString());
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/_loader/scope/scope04.html b/includes/js/dojo/tests/_base/_loader/scope/scope04.html
new file mode 100644
index 0000000..1866e4a
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/scope/scope04.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Multiversion Dojo: 0.4.3 and 1.0</title>
+
+ <link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/css/dijitTests.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css" />
+
+ <script type="text/javascript">
+ //djConfig for 0.4.3 setup.
+ djConfig = {
+ isDebug: true
+ };
+ </script>
+ <script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+
+ <script type="text/javascript">
+ //Need scope map defined in a script block. It will not work as part of the
+ //djConfig attribute on the script that loads Dojo.
+ //Also, just adding properties instead of redefining djConfig, since that
+ //will wipe out djConfig values set up by the 0.4.3 dojo.
+ djConfig.parseOnLoad = true;
+ djConfig.baseUrl = "../../../../";
+ djConfig.scopeMap = [
+ ["dojo", "dojo10"],
+ ["dijit", "dijit10"],
+ ["dojox", "dojox10"]
+ ];
+ </script>
+ <script type="text/javascript" src="../../../../dojo.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.widget.DropdownDatePicker");
+ dojo10.require("dijit._Calendar");
+ dojo10.require("dojo.date.locale");
+ dojo10.require("dojo.parser"); // scan page for widgets
+
+ dojo.addOnLoad(function(){
+ dojo.byId("output043").innerHTML = dojo.version.toString();
+ });
+ dojo10.addOnLoad(function(){
+ dojo.byId("output10").innerHTML = dojo10.version.toString();
+ });
+
+ function myHandler(id,newValue){
+ console.debug("onChange for id = " + id + ", value: " + newValue);
+ }
+
+ function foobar(){
+ dojo.byId("typeOut").innerHTML = (typeof dojo.addClass);
+ }
+ setTimeout(foobar, 2000);
+
+ </script>
+ </head>
+ <body>
+ <h1>Multiversion Dojo: 0.4.3 and 1.0</h1>
+
+ <p><b>NOTE: This test only works with a built version of Dojo</b></p>
+
+ <p>This page loads Dojo 0.4.3 and Dojo 1.0.</p>
+
+ <p>Dojo 0.4.3 version: <span id="output043"></span></p>
+
+ <p>Dojo 1.0 version: <span id="output10"></span></p>
+
+ <p><b>dojo.addClass should be undefined:</b> <span id="typeOut"></span></p>
+
+ <p>
+ <input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+ </p>
+
+ <p class="tundra">
+ <input id="calendar1" dojo10Type="dijit._Calendar" onChange="myHandler(this.id,arguments[0])">
+ </p>
+
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/_loader/scope/scopeContained.html b/includes/js/dojo/tests/_base/_loader/scope/scopeContained.html
new file mode 100644
index 0000000..0acea5b
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/scope/scopeContained.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Multiversion Dojo: 0.4.3 and 1.0</title>
+
+ <link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/css/dijitTests.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css" />
+
+ <script type="text/javascript">
+ //djConfig for 0.4.3 setup.
+ djConfig = {
+ isDebug: true
+ };
+ </script>
+ <script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+
+ <script type="text/javascript">
+ //Scope map for this page is "burned in" via a build command (see HTML notes below).
+ //Also, just adding properties instead of redefining djConfig, since that
+ //will wipe out djConfig values set up by the 0.4.3 dojo.
+ djConfig.parseOnLoad = true;
+ djConfig.baseUrl = "../../../../";
+ </script>
+ <script type="text/javascript" src="../../../../dojo.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.widget.DropdownDatePicker");
+
+ //Notice that dijit._Calendar is required, not jidit._Calendar.
+ //Same for the dojo resources (not jodo resources).
+ jodo.require("dijit._Calendar");
+ jodo.require("dojo.date.locale");
+ jodo.require("dojo.parser"); // scan page for widgets
+
+ dojo.addOnLoad(function(){
+ dojo.byId("output043").innerHTML = dojo.version.toString();
+ });
+ jodo.addOnLoad(function(){
+ dojo.byId("output10").innerHTML = jodo.version.toString();
+ });
+
+ function myHandler(id,newValue){
+ console.debug("onChange for id = " + id + ", value: " + newValue);
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Multiversion Dojo: 0.4.3 and 1.0</h1>
+
+ <p><b>NOTE: This test only works with a built version of Dojo, and it must be built with the scopeMap parameter (the backslashes below are required):</b></p>
+
+ <p style="color: blue; background-color: yellow">build.sh profile=standard action=release scopeMap=[[\"dojo\",\"jodo\"],[\"dijit\",\"jidit\"],[\"dojox\",\"jodox\"]]</p>
+
+ <p>This page loads Dojo 0.4.3 and Dojo 1.0 (under the jodo scope)</p>
+
+ <p>Dojo 0.4.3 version: <span id="output043"></span></p>
+
+ <p>Jodo version: <span id="output10"></span></p>
+
+ <p>
+ <input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+ </p>
+
+ <p class="tundra">
+ <input id="calendar1" jodoType="dijit._Calendar" onChange="myHandler(this.id,arguments[0])">
+ </p>
+
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/_loader/scope/scopeContainedXd.html b/includes/js/dojo/tests/_base/_loader/scope/scopeContainedXd.html
new file mode 100644
index 0000000..c4c2eda
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/scope/scopeContainedXd.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Multiversion Dojo: 0.4.3 and 1.0</title>
+
+ <link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/css/dijitTests.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css" />
+
+ <script type="text/javascript">
+ //djConfig for 0.4.3 setup.
+ djConfig = {
+ isDebug: true
+ };
+ </script>
+ <script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+
+ <script type="text/javascript">
+ //Scope map for this page is "burned in" via a build command (see HTML notes below).
+ //Also, just adding properties instead of redefining djConfig, since that
+ //will wipe out djConfig values set up by the 0.4.3 dojo.
+ djConfig.parseOnLoad = true;
+ djConfig.baseUrl = "../../../../";
+ djConfig.useXDomain = true; //Technically this was set already in the 0.4.3 xd dojo.js file.
+ </script>
+ <script type="text/javascript" src="../../../../dojo.xd.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.widget.DropdownDatePicker");
+
+ //Get base xd path
+ var xdPath = location.href;
+ var lastIndex = location.href.lastIndexOf("/");
+ xdPath = xdPath.substring(0, lastIndex + 1);
+
+ //Set up xdomain locations for dojo/dijit/dojox.
+ jodo.registerModulePath("dojo", xdPath + "../../../../../dojo");
+ jodo.registerModulePath("dijit", xdPath + "../../../../../dijit");
+ jodo.registerModulePath("dojox", xdPath + "../../../../../dojox");
+
+ //Notice that dijit._Calendar is required, not jidit._Calendar.
+ //Same for the dojo resources (not jodo resources).
+ jodo.require("dijit._Calendar");
+ jodo.require("dojo.date.locale");
+ jodo.require("dojo.parser"); // scan page for widgets
+
+ dojo.addOnLoad(function(){
+ dojo.byId("output043").innerHTML = dojo.version.toString();
+ });
+ jodo.addOnLoad(function(){
+ dojo.byId("output10").innerHTML = jodo.version.toString();
+ });
+
+ function myHandler(id,newValue){
+ console.debug("onChange for id = " + id + ", value: " + newValue);
+ }
+ </script>
+ </head>
+ <body>
+ <h1>XDomain Multiversion Dojo: 0.4.3 and 1.0</h1>
+
+ <p><b>NOTE: This test only works with a built, xdomain version of Dojo, and it must be built with the scopeMap parameter (the backslashes below are required):</b></p>
+
+ <p style="color: blue; background-color: yellow">build.sh profile=standard action=release scopeMap=[[\"dojo\",\"jodo\"],[\"dijit\",\"jidit\"],[\"dojox\",\"jodox\"]] xdDojoScopeName=jodo loader=xdomain</p>
+
+ <p><b>Only load this page from an http:// URL</b>. Otherwise, the xd loading will not happen.</p>
+
+ <p>This page xdomain loads Dojo 0.4.3 and Dojo 1.0 (under the jodo scope)</p>
+
+ <p>Dojo 0.4.3 version: <span id="output043"></span></p>
+
+ <p>Jodo version: <span id="output10"></span></p>
+
+ <p>
+ <input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+ </p>
+
+ <p class="tundra">
+ <input id="calendar1" jodoType="dijit._Calendar" onChange="myHandler(this.id,arguments[0])">
+ </p>
+
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/_loader/scope/scopeDjConfig.html b/includes/js/dojo/tests/_base/_loader/scope/scopeDjConfig.html
new file mode 100644
index 0000000..0ef5daa
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/scope/scopeDjConfig.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Multiversion Dojo: 0.4.3 and 1.0 (scoped djConfig)</title>
+
+ <link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/css/dijitTests.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css" />
+
+ <script type="text/javascript">
+ //djConfig for 0.4.3 setup.
+ djConfig = {
+ isDebug: true
+ };
+ </script>
+ <script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+
+ <script type="text/javascript" src="../../../../dojo.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.widget.DropdownDatePicker");
+
+ //Notice that dijit._Calendar is required, not jidit._Calendar.
+ //Same for the dojo resources (not jodo resources).
+ jodo.require("dijit._Calendar");
+ jodo.require("dojo.date.locale");
+ jodo.require("dojo.parser"); // scan page for widgets
+
+ dojo.addOnLoad(function(){
+ dojo.byId("output043").innerHTML = djConfig.baseUrl;
+ });
+ jodo.addOnLoad(function(){
+ dojo.byId("output10").innerHTML = jodo.baseUrl;
+ });
+
+ function myHandler(id,newValue){
+ console.debug("onChange for id = " + id + ", value: " + newValue);
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Multiversion Dojo: 0.4.3 and 1.0 (scoped djConfig)</h1>
+
+ <p><b>NOTE: This test only works with a built version of Dojo, and it must be built with the scopeDjConfig parameter (the backslashes below are required):</b></p>
+
+ <p style="color: blue; background-color: yellow">build.sh profile=standard action=release scopeDjConfig=\{parseOnLoad:true,baseUrl:\"../../../../\",foo:\"bar\",scopeMap:[[\"dojo\",\"jodo\"],[\"dijit\",\"jidit\"],[\"dojox\",\"jodox\"]]\}</p>
+
+ <p>This page loads Dojo 0.4.3 and Dojo 1.0 (under the jodo scope)</p>
+
+ <p>djConfig.baseUrl should <b>not</b> exist: <span id="output043"></span></p>
+
+ <p>jodo.baseUrl should be "../../../../": <span id="output10"></span></p>
+
+ <p>
+ <input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+ </p>
+
+ <p class="tundra">
+ <input id="calendar1" jodoType="dijit._Calendar" onChange="myHandler(this.id,arguments[0])">
+ </p>
+
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/_loader/scope/scopeSingle.html b/includes/js/dojo/tests/_base/_loader/scope/scopeSingle.html
new file mode 100644
index 0000000..759fcbe
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/scope/scopeSingle.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Using scope names inside dojo.require/dojoType</title>
+
+ <link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/css/dijitTests.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css" />
+
+ <script type="text/javascript">
+ //djConfig for 0.4.3 setup.
+ djConfig = {
+ isDebug: true,
+ parseOnLoad: true,
+ baseUrl: "../../../../",
+ scopeMap: [
+ ["dojo", "jodo"],
+ ["dijit", "jidit"],
+ ["dojox", "jodox"]
+ ]
+ };
+ </script>
+
+ <script type="text/javascript" src="../../../../dojo.js"></script>
+ <script type="text/javascript">
+
+ //Notice that dijit._Calendar is required, not jidit._Calendar.
+ //Same for the dojo resources (not jodo resources).
+ jodo.require("dijit._Calendar");
+ jodo.require("dojo.date.locale");
+ jodo.require("dojo.parser"); // scan page for widgets
+
+ jodo.addOnLoad(function(){
+ jodo.byId("output10").innerHTML = jodo.version.toString();
+ });
+
+ function myHandler(id,newValue){
+ console.debug("onChange for id = " + id + ", value: " + newValue);
+ }
+ function foobar(){
+ jodo.byId("typeOut").innerHTML = "typeof dojo: " + (typeof dojo) + "<br>typeof dijit: " + (typeof dijit) + "<br>typeof dojox: " + (typeof dojox);
+ }
+ setTimeout(foobar, 2000);
+ </script>
+ </head>
+ <body>
+ <h1>Using scope names inside dojo.require/dojoType</h1>
+
+ <p><b>NOTE: This test only works with a built version of Dojo.</b></p>
+
+ <p>Jodo version: <span id="output10"></span></p>
+
+ <p><b>typeof dojo, dijit and dojox should be undefined</b>: <br><span id="typeOut"></span></p>
+
+ <p class="tundra">
+ <input id="calendar1" jodoType="jidit._Calendar" onChange="myHandler(this.id,arguments[0])">
+ </p>
+
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/_loader/scope/scopeSingleDaac.html b/includes/js/dojo/tests/_base/_loader/scope/scopeSingleDaac.html
new file mode 100644
index 0000000..8f9d7d8
--- /dev/null
+++ b/includes/js/dojo/tests/_base/_loader/scope/scopeSingleDaac.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Using scope names inside dojo.require/dojoType</title>
+
+ <link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/css/dijitTests.css" />
+ <link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css" />
+
+ <script type="text/javascript">
+ //djConfig for 0.4.3 setup.
+ djConfig = {
+ isDebug: true,
+ debugAtAllCosts: true,
+ parseOnLoad: true,
+ baseUrl: "../../../../",
+ scopeMap: [
+ ["dojo", "jodo"],
+ ["dijit", "jidit"],
+ ["dojox", "jodox"]
+ ]
+ };
+ </script>
+
+ <script type="text/javascript" src="../../../../dojo.js"></script>
+ <script type="text/javascript">
+
+ //Notice that dijit._Calendar is required, not jidit._Calendar.
+ //Same for the dojo resources (not jodo resources).
+ jodo.require("dijit._Calendar");
+ jodo.require("dojo.date.locale");
+ jodo.require("dojo.parser"); // scan page for widgets
+
+ jodo.addOnLoad(function(){
+ jodo.byId("output10").innerHTML = jodo.version.toString();
+ });
+
+ function myHandler(id,newValue){
+ console.debug("onChange for id = " + id + ", value: " + newValue);
+ }
+ function foobar(){
+ jodo.byId("typeOut").innerHTML = "typeof dojo: " + (typeof dojo) + "<br>typeof dijit: " + (typeof dijit) + "<br>typeof dojox: " + (typeof dojox);
+ }
+ setTimeout(foobar, 2000);
+ </script>
+ </head>
+ <body>
+ <h1>Using scope names inside dojo.require/dojoType</h1>
+
+ <p><b>NOTE: This test only works with a built version of Dojo.</b></p>
+
+ <p>Jodo version: <span id="output10"></span></p>
+
+ <p><b>typeof dojo, dijit and dojox should be object, since debugAtAllCosts is ON</b>: <br><span id="typeOut"></span></p>
+
+ <p class="tundra">
+ <input id="calendar1" jodoType="jidit._Calendar" onChange="myHandler(this.id,arguments[0])">
+ </p>
+
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/array.js b/includes/js/dojo/tests/_base/array.js
new file mode 100644
index 0000000..6611257
--- /dev/null
+++ b/includes/js/dojo/tests/_base/array.js
@@ -0,0 +1,301 @@
+if(!dojo._hasResource["tests._base.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.array"] = true;
+dojo.provide("tests._base.array");
+
+tests.register("tests._base.array",
+ [
+ function testIndexOf(t){
+ var foo = [128, 256, 512];
+ var bar = ["aaa", "bbb", "ccc"];
+
+ t.assertEqual(1, dojo.indexOf([45, 56, 85], 56));
+ t.assertEqual(1, dojo.indexOf([Number, String, Date], String));
+ t.assertEqual(1, dojo.indexOf(foo, foo[1]));
+ t.assertEqual(2, dojo.indexOf(foo, foo[2]));
+ t.assertEqual(1, dojo.indexOf(bar, bar[1]));
+ t.assertEqual(2, dojo.indexOf(bar, bar[2]));
+ t.assertEqual(-1, dojo.indexOf({a:1}, "a"));
+
+ foo.push(bar);
+ t.assertEqual(3, dojo.indexOf(foo, bar));
+ },
+
+ function testIndexOfFromIndex(t){
+ var foo = [128, 256, 512];
+ var bar = ["aaa", "bbb", "ccc"];
+
+ t.assertEqual(-1, dojo.indexOf([45, 56, 85], 56, 2));
+ t.assertEqual(1, dojo.indexOf([45, 56, 85], 56, 1));
+ t.assertEqual(1, dojo.indexOf([45, 56, 85], 56, -1));
+ // Make sure going out of bounds doesn't throw us in an infinite loop
+ t.assertEqual(-1, dojo.indexOf([45, 56, 85], 56, 3));
+ },
+
+ function testLastIndexOf(t){
+ var foo = [128, 256, 512];
+ var bar = ["aaa", "bbb", "aaa", "ccc"];
+
+ t.assertEqual(1, dojo.indexOf([45, 56, 85], 56));
+ t.assertEqual(1, dojo.indexOf([Number, String, Date], String));
+ t.assertEqual(1, dojo.lastIndexOf(foo, foo[1]));
+ t.assertEqual(2, dojo.lastIndexOf(foo, foo[2]));
+ t.assertEqual(1, dojo.lastIndexOf(bar, bar[1]));
+ t.assertEqual(2, dojo.lastIndexOf(bar, bar[2]));
+ t.assertEqual(2, dojo.lastIndexOf(bar, bar[0]));
+ },
+
+ function testLastIndexOfFromIndex(t){
+ t.assertEqual(1, dojo.lastIndexOf([45, 56, 85], 56, 1));
+ t.assertEqual(-1, dojo.lastIndexOf([45, 56, 85], 85, 1));
+ t.assertEqual(-1, dojo.lastIndexOf([45, 56, 85], 85, -1));
+ t.assertEqual(0, dojo.lastIndexOf([45, 56, 45], 45, 0));
+ },
+
+ function testForEach(t){
+ var foo = [128, "bbb", 512];
+ dojo.forEach(foo, function(elt, idx, array){
+ switch(idx){
+ case 0: t.assertEqual(128, elt); break;
+ case 1: t.assertEqual("bbb", elt); break;
+ case 2: t.assertEqual(512, elt); break;
+ default: t.assertTrue(false);
+ }
+ });
+
+ var noException = true;
+ try{
+ dojo.forEach(undefined, function(){});
+ }catch(e){
+ noException = false;
+ }
+ t.assertTrue(noException);
+ },
+
+ function testForEach_str(t){
+ var bar = 'abc';
+ dojo.forEach(bar, function(elt, idx, array){
+ switch(idx){
+ case 0: t.assertEqual("a", elt); break;
+ case 1: t.assertEqual("b", elt); break;
+ case 2: t.assertEqual("c", elt); break;
+ default: t.assertTrue(false);
+ }
+ });
+ },
+ // FIXME: test forEach w/ a NodeList()?
+
+ function testForEach_string_callback(t){
+ // Test using strings as callback", which accept the parameters with
+ // the names "item", "index" and "array"!
+ var foo = [128, "bbb", 512];
+ // Test that the variable "item" contains the value of each item.
+ this._res = "";
+ dojo.forEach(foo, 'this._res+=item', this);
+ t.assertEqual(this._res, "128bbb512");
+ // Test that the variable "index" contains each index.
+ this._res = [];
+ dojo.forEach(foo, 'this._res.push(index)', this);
+ t.assertEqual(this._res, [0,1,2]);
+ // Test that the variable "array" always contains the entire array.
+ this._res = [];
+ dojo.forEach(foo, 'this._res.push(array)', this);
+ t.assertEqual(this._res, [[128, "bbb", 512],[128, "bbb", 512],[128, "bbb", 512]]);
+ // Catch undefined variable usage (I used to use "i" :-)).
+ var caughtException = false;
+ try{
+ dojo.forEach(foo, 'this._res+=i', this);
+ }catch(e){
+ caughtException = true;
+ }
+ t.assertTrue(caughtException);
+ },
+
+ // FIXME: test forEach w/ a NodeList()?
+ function testEvery(t){
+ var foo = [128, "bbb", 512];
+
+ t.assertTrue(
+ dojo.every(foo, function(elt, idx, array){
+ t.assertEqual(Array, array.constructor);
+ t.assertTrue(dojo.isArray(array));
+ t.assertTrue(typeof idx == "number");
+ if(idx == 1){ t.assertEqual("bbb" , elt); }
+ return true;
+ })
+ );
+
+ t.assertTrue(
+ dojo.every(foo, function(elt, idx, array){
+ switch(idx){
+ case 0: t.assertEqual(128, elt); return true;
+ case 1: t.assertEqual("bbb", elt); return true;
+ case 2: t.assertEqual(512, elt); return true;
+ default: return false;
+ }
+ })
+ );
+
+ t.assertFalse(
+ dojo.every(foo, function(elt, idx, array){
+ switch(idx){
+ case 0: t.assertEqual(128, elt); return true;
+ case 1: t.assertEqual("bbb", elt); return true;
+ case 2: t.assertEqual(512, elt); return false;
+ default: return true;
+ }
+ })
+ );
+
+ },
+
+ function testEvery_str(t){
+ var bar = 'abc';
+ t.assertTrue(
+ dojo.every(bar, function(elt, idx, array){
+ switch(idx){
+ case 0: t.assertEqual("a", elt); return true;
+ case 1: t.assertEqual("b", elt); return true;
+ case 2: t.assertEqual("c", elt); return true;
+ default: return false;
+ }
+ })
+ );
+
+ t.assertFalse(
+ dojo.every(bar, function(elt, idx, array){
+ switch(idx){
+ case 0: t.assertEqual("a", elt); return true;
+ case 1: t.assertEqual("b", elt); return true;
+ case 2: t.assertEqual("c", elt); return false;
+ default: return true;
+ }
+ })
+ );
+ },
+ // FIXME: test NodeList for every()?
+
+ function testSome(t){
+ var foo = [128, "bbb", 512];
+ t.assertTrue(
+ dojo.some(foo, function(elt, idx, array){
+ t.assertEqual(3, array.length);
+ return true;
+ })
+ );
+
+ t.assertTrue(
+ dojo.some(foo, function(elt, idx, array){
+ if(idx < 1){ return true; }
+ return false;
+ })
+ );
+
+ t.assertFalse(
+ dojo.some(foo, function(elt, idx, array){
+ return false;
+ })
+ );
+
+ t.assertTrue(
+ dojo.some(foo, function(elt, idx, array){
+ t.assertEqual(Array, array.constructor);
+ t.assertTrue(dojo.isArray(array));
+ t.assertTrue(typeof idx == "number");
+ if(idx == 1){ t.assertEqual("bbb" , elt); }
+ return true;
+ })
+ );
+ },
+
+ function testSome_str(t){
+ var bar = 'abc';
+ t.assertTrue(
+ dojo.some(bar, function(elt, idx, array){
+ t.assertEqual(3, array.length);
+ switch(idx){
+ case 0: t.assertEqual("a", elt); return true;
+ case 1: t.assertEqual("b", elt); return true;
+ case 2: t.assertEqual("c", elt); return true;
+ default: return false;
+ }
+ })
+ );
+
+ t.assertTrue(
+ dojo.some(bar, function(elt, idx, array){
+ switch(idx){
+ case 0: t.assertEqual("a", elt); return true;
+ case 1: t.assertEqual("b", elt); return true;
+ case 2: t.assertEqual("c", elt); return false;
+ default: return true;
+ }
+ })
+ );
+
+ t.assertFalse(
+ dojo.some(bar, function(elt, idx, array){
+ return false;
+ })
+ );
+ },
+ // FIXME: need to add scoping tests for all of these!!!
+
+ function testFilter(t){
+ var foo = ["foo", "bar", 10];
+
+ t.assertEqual(["foo"],
+ dojo.filter(foo, function(elt, idx, array){
+ return idx < 1;
+ })
+ );
+
+ t.assertEqual(["foo"],
+ dojo.filter(foo, function(elt, idx, array){
+ return elt == "foo";
+ })
+ );
+
+ t.assertEqual([],
+ dojo.filter(foo, function(elt, idx, array){
+ return false;
+ })
+ );
+
+ t.assertEqual([10],
+ dojo.filter(foo, function(elt, idx, array){
+ return typeof elt == "number";
+ })
+ );
+ },
+
+ function testFilter_str(t){
+ var foo = "thinger blah blah blah";
+ t.assertEqual(["t", "h", "i"],
+ dojo.filter(foo, function(elt, idx, array){
+ return idx < 3;
+ })
+ );
+
+ t.assertEqual([],
+ dojo.filter(foo, function(elt, idx, array){
+ return false;
+ })
+ );
+ },
+
+ function testMap(t){
+ t.assertEqual([],
+ dojo.map([], function(){ return true; })
+ );
+
+ t.assertEqual([1, 2, 3],
+ dojo.map(["cat", "dog", "mouse"], function(elt, idx, array){
+ return idx+1;
+ })
+ );
+ }
+ ]
+);
+
+
+}
diff --git a/includes/js/dojo/tests/_base/connect.js b/includes/js/dojo/tests/_base/connect.js
new file mode 100644
index 0000000..3761861
--- /dev/null
+++ b/includes/js/dojo/tests/_base/connect.js
@@ -0,0 +1,225 @@
+if(!dojo._hasResource["tests._base.connect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.connect"] = true;
+dojo.provide("tests._base.connect");
+
+hub = function(){
+}
+
+failures = 0;
+bad = function(){
+ failures++;
+}
+
+good = function(){
+}
+
+// make 'iterations' connections to hub
+// roughly half of which will be to 'good' and
+// half to 'bad'
+// all connections to 'bad' are disconnected
+// test can then be performed on the values
+// 'failures' and 'successes'
+markAndSweepTest = function(iterations){
+ var marked = [];
+ // connections
+ for(var i=0; i<iterations; i++){
+ if(Math.random() < 0.5){
+ marked.push(dojo.connect('hub', bad));
+ }else{
+ dojo.connect('hub', good);
+ }
+ }
+ // Randomize markers (only if the count isn't very high)
+ if(i < Math.pow(10, 4)){
+ var rm = [ ];
+ while(marked.length){
+ var m = Math.floor(Math.random() * marked.length);
+ rm.push(marked[m]);
+ marked.splice(m, 1);
+ }
+ marked = rm;
+ }
+ for(var m=0; m<marked.length; m++){
+ dojo.disconnect(marked[m]);
+ }
+ // test
+ failures = 0;
+ hub();
+ // return number of disconnected functions that fired (should be 0)
+ return failures;
+}
+
+markAndSweepSubscribersTest = function(iterations){
+ var topic = "hubbins";
+ var marked = [];
+ // connections
+ for(var i=0; i<iterations; i++){
+ if(Math.random() < 0.5){
+ marked.push(dojo.subscribe(topic, bad));
+ }else{
+ dojo.subscribe(topic, good);
+ }
+ }
+ // Randomize markers (only if the count isn't very high)
+ if(i < Math.pow(10, 4)){
+ var rm = [ ];
+ while(marked.length){
+ var m = Math.floor(Math.random() * marked.length);
+ rm.push(marked[m]);
+ marked.splice(m, 1);
+ }
+ marked = rm;
+ }
+ for(var m=0; m<marked.length; m++){
+ dojo.unsubscribe(marked[m]);
+ }
+ // test
+ failures = 0;
+ dojo.publish(topic);
+ // return number of unsubscribed functions that fired (should be 0)
+ return failures;
+}
+
+tests.register("tests._base.connect",
+ [
+ function smokeTest(t){
+ // foo sets ok to false
+ var ok = false;
+ var foo = { "foo": function(){ ok=false; } };
+ // connected function sets ok to true
+ dojo.connect(foo, "foo", null, function(){ ok=true; });
+ foo.foo();
+ t.is(true, ok);
+ },
+ function basicTest(t) {
+ var out = '';
+ var obj = {
+ foo: function() {
+ out += 'foo';
+ },
+ bar: function() {
+ out += 'bar';
+ },
+ baz: function() {
+ out += 'baz';
+ }
+ };
+ //
+ var foobar = dojo.connect(obj, "foo", obj, "bar");
+ dojo.connect(obj, "bar", obj, "baz");
+ //
+ out = '';
+ obj.foo();
+ t.is('foobarbaz', out);
+ //
+ out = '';
+ obj.bar();
+ t.is('barbaz', out);
+ //
+ out = '';
+ obj.baz();
+ t.is('baz', out);
+ //
+ dojo.connect(obj, "foo", obj, "baz");
+ dojo.disconnect(foobar);
+ //
+ out = '';
+ obj.foo();
+ t.is('foobaz', out);
+ //
+ out = '';
+ obj.bar();
+ t.is('barbaz', out);
+ //
+ out = '';
+ obj.baz();
+ t.is('baz', out);
+ },
+ function hubConnectDisconnect1000(t){
+ t.is(0, markAndSweepTest(1000));
+ },
+ function args4Test(t){
+ // standard 4 args test
+ var ok, obj = { foo: function(){ok=false;}, bar: function(){ok=true} };
+ dojo.connect(obj, "foo", obj, "bar");
+ obj.foo();
+ t.is(true, ok);
+ },
+ function args3Test(t){
+ // make some globals
+ var ok;
+ dojo.global["gFoo"] = function(){ok=false;};
+ dojo.global["gOk"] = function(){ok=true;};
+ // 3 arg shorthand for globals (a)
+ var link = dojo.connect("gFoo", null, "gOk");
+ gFoo();
+ dojo.disconnect(link);
+ t.is(true, ok);
+ // 3 arg shorthand for globals (b)
+ link = dojo.connect(null, "gFoo", "gOk");
+ gFoo();
+ dojo.disconnect(link);
+ t.is(true, ok);
+ // verify disconnections
+ gFoo();
+ t.is(false, ok);
+ },
+ function args2Test(t){
+ // make some globals
+ var ok;
+ dojo.global["gFoo"] = function(){ok=false;};
+ dojo.global["gOk"] = function(){ok=true;};
+ // 2 arg shorthand for globals
+ var link = dojo.connect("gFoo", "gOk");
+ gFoo();
+ dojo.disconnect(link);
+ t.is(true, ok);
+ // 2 arg shorthand for globals, alternate scoping
+ link = dojo.connect("gFoo", gOk);
+ gFoo();
+ dojo.disconnect(link);
+ t.is(true, ok);
+ },
+ function scopeTest1(t){
+ var foo = { ok: true, foo: function(){this.ok=false;} };
+ var bar = { ok: false, bar: function(){this.ok=true} };
+ // link foo.foo to bar.bar with natural scope
+ var link = dojo.connect(foo, "foo", bar, "bar");
+ foo.foo();
+ t.is(false, foo.ok);
+ t.is(true, bar.ok);
+ },
+ function scopeTest2(t){
+ var foo = { ok: true, foo: function(){this.ok=false;} };
+ var bar = { ok: false, bar: function(){this.ok=true} };
+ // link foo.foo to bar.bar such that scope is always 'foo'
+ var link = dojo.connect(foo, "foo", bar.bar);
+ foo.foo();
+ t.is(true, foo.ok);
+ t.is(false, bar.ok);
+ },
+ function connectPublisher(t){
+ var foo = { inc: 0, foo: function(){ this.inc++; } };
+ var bar = { inc: 0, bar: function(){ this.inc++; } };
+ var c1h = dojo.connectPublisher("/blah", foo, "foo");
+ var c2h = dojo.connectPublisher("/blah", foo, "foo");
+ dojo.subscribe("/blah", bar, "bar");
+ foo.foo();
+ t.is(1, foo.inc);
+ t.is(2, bar.inc);
+ dojo.disconnect(c1h);
+ foo.foo();
+ t.is(2, foo.inc);
+ t.is(3, bar.inc);
+ dojo.disconnect(c2h);
+ foo.foo();
+ t.is(3, foo.inc);
+ t.is(3, bar.inc);
+ },
+ function publishSubscribe1000(t){
+ t.is(markAndSweepSubscribersTest(1000), 0);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/declare.js b/includes/js/dojo/tests/_base/declare.js
new file mode 100644
index 0000000..11720ec
--- /dev/null
+++ b/includes/js/dojo/tests/_base/declare.js
@@ -0,0 +1,197 @@
+if(!dojo._hasResource["tests._base.declare"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.declare"] = true;
+dojo.provide("tests._base.declare");
+
+tests.register("tests._base.declare",
+ [
+ function smokeTest(t){
+ dojo.declare("tests._base.declare.tmp");
+ var tmp = new tests._base.declare.tmp();
+ dojo.declare("testsFoo");
+ var tmp = new testsFoo();
+ },
+ function smokeTest2(t){
+ dojo.declare("tests._base.declare.foo", null, {
+ foo: "thonk"
+ });
+ var tmp = new tests._base.declare.foo();
+ t.is("thonk", tmp.foo);
+
+ dojo.declare("testsFoo2", null, {
+ foo: "thonk"
+ });
+ var tmp2 = new testsFoo2();
+ t.is("thonk", tmp2.foo);
+ },
+ function smokeTestWithCtor(t){
+ dojo.declare("tests._base.declare.fooBar", null, {
+ constructor: function(){
+ this.foo = "blah";
+ },
+ foo: "thonk"
+ });
+ var tmp = new tests._base.declare.fooBar();
+ t.is("blah", tmp.foo);
+ },
+ function smokeTestCompactArgs(t){
+ dojo.declare("tests._base.declare.fooBar2", null, {
+ foo: "thonk"
+ });
+ var tmp = new tests._base.declare.fooBar2();
+ t.is("thonk", tmp.foo);
+ },
+ function subclass(t){
+ dojo.declare("tests._base.declare.tmp3", null, {
+ foo: "thonk"
+ });
+ dojo.declare("tests._base.declare.tmp4", tests._base.declare.tmp3);
+ var tmp = new tests._base.declare.tmp4();
+ t.is("thonk", tmp.foo);
+ },
+ function subclassWithCtor(t){
+ dojo.declare("tests._base.declare.tmp5", null, {
+ constructor: function(){
+ this.foo = "blah";
+ },
+ foo: "thonk"
+ });
+ dojo.declare("tests._base.declare.tmp6", tests._base.declare.tmp5);
+ var tmp = new tests._base.declare.tmp6();
+ t.is("blah", tmp.foo);
+ },
+ function mixinSubclass(t){
+ dojo.declare("tests._base.declare.tmp7", null, {
+ foo: "thonk"
+ });
+ dojo.declare("tests._base.declare.tmp8", null, {
+ constructor: function(){
+ this.foo = "blah";
+ }
+ });
+ var tmp = new tests._base.declare.tmp8();
+ t.is("blah", tmp.foo);
+ dojo.declare("tests._base.declare.tmp9",
+ [
+ tests._base.declare.tmp7, // prototypal
+ tests._base.declare.tmp8 // mixin
+ ]);
+ var tmp2 = new tests._base.declare.tmp9();
+ t.is("blah", tmp2.foo);
+ },
+ function superclassRef(t){
+ dojo.declare("tests._base.declare.tmp10", null, {
+ foo: "thonk"
+ });
+ dojo.declare("tests._base.declare.tmp11", tests._base.declare.tmp10, {
+ constructor: function(){
+ this.foo = "blah";
+ }
+ });
+ var tmp = new tests._base.declare.tmp11();
+ t.is("blah", tmp.foo);
+ t.is("thonk", tests._base.declare.tmp11.superclass.foo);
+ },
+ function inheritedCall(t){
+ var foo = "xyzzy";
+ dojo.declare("tests._base.declare.tmp12", null, {
+ foo: "thonk",
+ bar: function(arg1, arg2){
+ if(arg1){
+ this.foo = arg1;
+ }
+ if(arg2){
+ foo = arg2;
+ }
+ }
+ });
+ dojo.declare("tests._base.declare.tmp13", tests._base.declare.tmp12, {
+ constructor: function(){
+ this.foo = "blah";
+ }
+ });
+ var tmp = new tests._base.declare.tmp13();
+ t.is("blah", tmp.foo);
+ t.is("xyzzy", foo);
+ tmp.bar("zot");
+ t.is("zot", tmp.foo);
+ t.is("xyzzy", foo);
+ tmp.bar("trousers", "squiggle");
+ t.is("trousers", tmp.foo);
+ t.is("squiggle", foo);
+ },
+ function inheritedExplicitCall(t){
+ var foo = "xyzzy";
+ dojo.declare("tests._base.declare.tmp14", null, {
+ foo: "thonk",
+ bar: function(arg1, arg2){
+ if(arg1){
+ this.foo = arg1;
+ }
+ if(arg2){
+ foo = arg2;
+ }
+ }
+ });
+ dojo.declare("tests._base.declare.tmp15", tests._base.declare.tmp14, {
+ constructor: function(){
+ this.foo = "blah";
+ },
+ bar: function(arg1, arg2){
+ this.inherited("bar", arguments, [arg2, arg1]);
+ },
+ baz: function(arg1, arg2){
+ tests._base.declare.tmp15.superclass.bar.apply(this, arguments);
+ }
+ });
+ var tmp = new tests._base.declare.tmp15();
+ t.is("blah", tmp.foo);
+ t.is("xyzzy", foo);
+ tmp.baz("zot");
+ t.is("zot", tmp.foo);
+ t.is("xyzzy", foo);
+ tmp.bar("trousers", "squiggle");
+ t.is("squiggle", tmp.foo);
+ t.is("trousers", foo);
+ },
+ function inheritedMixinCalls(t){
+ dojo.declare("tests._base.declare.tmp16", null, {
+ foo: "",
+ bar: function(){
+ this.foo += "tmp16";
+ }
+ });
+ dojo.declare("tests._base.declare.mixin16", null, {
+ bar: function(){
+ this.inherited(arguments);
+ this.foo += ".mixin16";
+ }
+ });
+ dojo.declare("tests._base.declare.mixin17", tests._base.declare.mixin16, {
+ bar: function(){
+ this.inherited(arguments);
+ this.foo += ".mixin17";
+ }
+ });
+ dojo.declare("tests._base.declare.tmp17", [tests._base.declare.tmp16, tests._base.declare.mixin17], {
+ bar: function(){
+ this.inherited(arguments);
+ this.foo += ".tmp17";
+ }
+ });
+ var tmp = new tests._base.declare.tmp17();
+ tmp.bar();
+ t.is("tmp16.mixin16.mixin17.tmp17", tmp.foo);
+ },
+ function mixinPreamble(t){
+ var passed = false;
+ dojo.declare("tests._base.declare.tmp16");
+ new tests._base.declare.tmp16({ preamble: function(){ passed = true; } });
+ t.t(passed);
+ }
+ // FIXME: there are still some permutations to test like:
+ // - ctor arguments
+ // - multi-level inheritance + L/R conflict checks
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/fx.html b/includes/js/dojo/tests/_base/fx.html
new file mode 100644
index 0000000..2ef751c
--- /dev/null
+++ b/includes/js/dojo/tests/_base/fx.html
@@ -0,0 +1,342 @@
+<html>
+ <head>
+ <title>testing Core FX</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js"
+ djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../_base/fx.js"></script>
+ <script type="text/javascript">
+ var duration = 500;
+ var timeout = 750;
+ dojo.require("doh.runner");
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ {
+ name: "fadeOut",
+ timeout: timeout,
+ runTest: function(){
+ var opacity = dojo.style('foo', 'opacity');
+ doh.is(1, opacity);
+ var anim = dojo.fadeOut({ node: 'foo', duration: duration });
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ var opacity = dojo.style('foo', 'opacity');
+ var elapsed = (new Date()) - anim._start;
+ doh.is(0, opacity);
+ doh.t(elapsed >= duration);
+ d.callback(true);
+ });
+ anim._start = new Date();
+ anim.play();
+ return d;
+ }
+ },
+ {
+ name: "fadeIn",
+ timeout: timeout,
+ runTest: function(){
+ var opacity = dojo.style('foo', 'opacity');
+ doh.is(0, opacity);
+ var anim = dojo.fadeIn({ node: 'foo', duration: duration });
+ var d = new doh.Deferred();
+ dojo.connect(anim, "onEnd", function(){
+ var opacity = dojo.style('foo', 'opacity');
+ var elapsed = (new Date()) - anim._start;
+ doh.is(1, opacity);
+ doh.t(elapsed >= duration);
+ d.callback(true);
+ });
+ anim._start = new Date();
+ anim.play();
+ return d;
+ }
+ },
+ {
+ name: "animateColor",
+ timeout: timeout,
+ runTest: function(){
+ var d = new doh.Deferred();
+ var anim = dojo.animateProperty({
+ node: "foo",
+ duration: duration,
+ properties: {
+ color: { start: "black", end: "white" },
+ backgroundColor: { start: "white", end: "black" }
+ }
+ });
+ dojo.connect(anim, "onEnd", anim, function(){
+ d.callback(true);
+ });
+ anim.play();
+ return d;
+ }
+ },
+ {
+ name: "animateColorBack",
+ timeout: timeout,
+ runTest: function(){
+ var d = new doh.Deferred();
+ var anim = dojo.animateProperty({
+ node: "foo",
+ duration: duration,
+ properties: {
+ color: { end: "black" },
+ backgroundColor: { end: "#5d81b4" },
+ letterSpacing: { start: 0, end: 10 }
+ }
+ });
+ dojo.connect(anim, "onEnd", anim, function(){
+ d.callback(true);
+ });
+ anim.play();
+ return d;
+ }
+ },
+ {
+ name: "animateHeight",
+ timeout: timeout,
+ runTest: function(t){
+ dojo.byId("foo").style.height = "";
+ var startHeight = dojo.marginBox("foo").h;
+ var endHeight = Math.round(startHeight / 2);
+
+ var anim = dojo.animateProperty({
+ node: "foo",
+ properties: { height: { end: endHeight } },
+ duration: duration
+ });
+
+ var d = new doh.Deferred();
+
+ dojo.connect(anim, "onEnd", anim, function(){
+ var elapsed = (new Date().valueOf()) - anim._startTime;
+ doh.t(elapsed >= duration);
+ var height = dojo.marginBox("foo").h;
+ doh.is(height, endHeight);
+ d.callback(true);
+ });
+
+ anim.play();
+ return d;
+ }
+ },
+ {
+ name: "animateHeight_defaults_syntax",
+ timeout: timeout,
+ runTest: function(){
+ dojo.byId("foo").style.height = "";
+ var startHeight = dojo.marginBox("foo").h;
+ var endHeight = Math.round(startHeight / 2);
+
+ var anim = dojo.animateProperty({
+ node: "foo",
+ properties: { height: endHeight },
+ duration: duration
+ });
+
+ var d = new doh.Deferred();
+
+ dojo.connect(anim, "onEnd", anim, function(){
+ var elapsed = (new Date().valueOf()) - anim._startTime;
+ doh.t(elapsed >= duration);
+ var height = dojo.marginBox("foo").h;
+ doh.is(height, endHeight);
+ d.callback(true);
+ });
+
+ anim.play();
+ return d;
+ }
+ },
+ {
+ name: "inlineWidth",
+ timeout: timeout,
+ runTest: function(){
+ dojo.style("foo", "display", "none");
+ dojo.style("bar", "display", "");
+ var startWidth = dojo.marginBox("bar").w;
+ var endWidth = Math.round(startWidth / 2);
+
+ var anim = dojo.animateProperty({
+ node: "bar",
+ properties: { width: endWidth },
+ duration: duration
+ });
+
+ var d = new doh.Deferred();
+
+ dojo.connect(anim, "onEnd", anim, function(){
+ var elapsed = (new Date().valueOf()) - anim._startTime;
+ doh.t(elapsed >= duration);
+ doh.is(dojo.marginBox("bar").w, endWidth);
+ d.callback(true);
+ });
+
+ anim.play();
+ return d;
+ }
+ },
+ {
+ name: "anim",
+ timeout: timeout+500,
+ runTest: function(){
+ var id = "baz";
+ dojo.style("bar", "display", "none");
+ dojo.style(id, "display", "");
+ var kickoff = new Date().valueOf();
+ var startWidth = dojo.marginBox(id).w;
+ var endWidth = Math.round(startWidth / 2);
+
+ var d = new doh.Deferred();
+ var anim = dojo.anim(
+ id,
+ {
+ width: endWidth,
+ opacity: 0
+ },
+ duration,
+ null,
+ function(){
+ var elapsed = (new Date().valueOf()) - anim._startTime;
+ doh.t(elapsed >= duration);
+ doh.t((new Date().valueOf()) >= (kickoff+duration+500));
+ doh.is(dojo.marginBox(id).w, endWidth);
+ doh.is(dojo.style(id, "opacity"), 0);
+ d.callback(true);
+ },
+ 500
+ );
+ return d;
+ }
+ },
+ {
+ name: "anim_defaults",
+ timeout: 1000,
+ runTest: function(){
+ var id = "thud";
+ dojo.style("baz", "display", "none");
+ dojo.style(id, "display", "");
+ var startWidth = dojo.marginBox(id).w;
+ var endWidth = Math.round(startWidth / 2);
+
+ var d = new doh.Deferred();
+ var anim = dojo.anim(id, { width: endWidth });
+ dojo.connect(anim, "onEnd", function(){
+ var elapsed = (new Date().valueOf()) - anim._startTime;
+ doh.t(elapsed >= dojo._Animation.prototype.duration); // the default
+ doh.is(dojo.marginBox(id).w, endWidth);
+ d.callback(true);
+ });
+ return d;
+ }
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <style type="text/css">
+ body {
+ margin: 1em;
+ background-color: #DEDEDE;
+ }
+
+ .box {
+ color: #292929;
+ /* color: #424242; */
+ /* text-align: left; */
+ width: 300px;
+ border: 1px solid #BABABA;
+ background-color: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ margin-left: 10px;
+ -o-border-radius: 10px;
+ -moz-border-radius: 12px;
+ -webkit-border-radius: 10px;
+ /* -opera-border-radius: 10px; */
+ border-radius: 10px;
+ -moz-box-sizing: border-box;
+ -opera-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -khtml-box-sizing: border-box;
+ box-sizing: border-box;
+ overflow: hidden;
+ /* position: absolute; */
+ }
+ </style>
+ </head>
+ <body>
+ <h1>testing Core FX</h1>
+ <form name="testForm">
+ <input type="button" onClick="dojo.fadeOut({ node: 'foo', duration: 1000 }).play()" value="fade out"></input>
+ <input type="button" onClick="dojo.fadeIn({ node: 'foo', duration: 1000 }).play()" value="fade in"></input>
+ </form>
+ <div id="foo" class="box" style="float: left;">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+ semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+ Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla
+ facilisi. Maecenas luctus venenatis nulla. In sit amet dui non mi
+ semper iaculis. Sed molestie tortor at ipsum. Morbi dictum rutrum
+ magna. Sed vitae risus.
+ </p>
+ <p>
+ Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+ imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+ lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+ id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+ mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+ pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+ tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+ elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+ ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+ pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+ massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+ nec est. Aenean id risus blandit tortor pharetra congue.
+ Suspendisse pulvinar.
+ </p>
+ </div>
+ <p id="bar" style="display: none;">
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper
+ sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta
+ rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+ Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+ Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+ risus.
+ </p>
+ <p id="baz" style="display: none;">
+ Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+ imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+ nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+ massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+ pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+ quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+ felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+ quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+ rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+ semper velit ante id metus. Praesent massa dolor, porttitor sed,
+ pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+ tortor pharetra congue. Suspendisse pulvinar.
+ </p>
+ <p id="thud" style="display: none;">
+ Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+ imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+ nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+ massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+ pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+ quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+ felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+ quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+ rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+ semper velit ante id metus. Praesent massa dolor, porttitor sed,
+ pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+ tortor pharetra congue. Suspendisse pulvinar.
+ </p>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/fx.js b/includes/js/dojo/tests/_base/fx.js
new file mode 100644
index 0000000..acb1ca3
--- /dev/null
+++ b/includes/js/dojo/tests/_base/fx.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.fx"] = true;
+dojo.provide("tests._base.fx");
+if(dojo.isBrowser){
+ doh.registerUrl("tests._base.fx", dojo.moduleUrl("tests", "_base/fx.html"), 15000);
+}
+
+}
diff --git a/includes/js/dojo/tests/_base/fx_delay.html b/includes/js/dojo/tests/_base/fx_delay.html
new file mode 100644
index 0000000..c2a1cd9
--- /dev/null
+++ b/includes/js/dojo/tests/_base/fx_delay.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<style type="text/css">
+#inner { width: 200px; height: 200px; background-color: #484}
+</style>
+<script type="text/javascript" src="../../dojo.js"></script>
+<script type="text/javascript">
+dojo.require("dojo._base.fx");
+dojo.require("dojo._base.html");
+dojo.addOnLoad(function(){
+ var box = dojo.byId("box");
+ dojo.connect(box, "onclick", function(){
+ dojo.style(box, "opacity", "0");
+ dojo.fadeIn({node:box, delay:1}).play();
+ });
+});
+</script>
+</head>
+<body>
+<div id="box"><button id="inner">click me</button></div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/_base/html.html b/includes/js/dojo/tests/_base/html.html
new file mode 100644
index 0000000..912c8a6
--- /dev/null
+++ b/includes/js/dojo/tests/_base/html.html
@@ -0,0 +1,556 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+ we use a strict-mode DTD to ensure that the box model is the same for these
+ basic tests
+-->
+<html>
+ <head>
+ <title>testing Core HTML/DOM/CSS/Style utils</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js"
+ djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+
+ function getIframeDocument(/*DOMNode*/iframeNode){
+ //summary: Returns the document object associated with the iframe DOM Node argument.
+ var doc = iframeNode.contentDocument || // W3
+ (
+ (iframeNode.contentWindow)&&(iframeNode.contentWindow.document)
+ ) || // IE
+ (
+ (iframeNode.name)&&(documendoh.frames[iframeNode.name])&&
+ (documendoh.frames[iframeNode.name].document)
+ ) || null;
+ return doc;
+ }
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ "doh.is(100, dojo.marginBox('sq100').w);",
+ "doh.is(100, dojo.marginBox('sq100').h);",
+
+ "doh.is(120, dojo.marginBox('sq100margin10').w);",
+ "doh.is(120, dojo.marginBox('sq100margin10').h);",
+ "doh.is(100, dojo.contentBox('sq100margin10').w);",
+ "doh.is(100, dojo.contentBox('sq100margin10').h);",
+
+ "doh.is(140, dojo.marginBox('sq100margin10pad10').w);",
+ "doh.is(140, dojo.marginBox('sq100margin10pad10').h);",
+
+ "doh.is(120, dojo.marginBox('sq100pad10').w);",
+ "doh.is(120, dojo.marginBox('sq100pad10').h);",
+
+ "doh.is(110, dojo.marginBox('sq100ltpad10').w);",
+ "doh.is(110, dojo.marginBox('sq100ltpad10').h);",
+ "doh.is(100, dojo.contentBox('sq100ltpad10').w);",
+ "doh.is(100, dojo.contentBox('sq100ltpad10').h);",
+
+ "doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w);",
+ "doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h);",
+
+ "doh.is(120, dojo.marginBox('sq100border10').w);",
+ "doh.is(120, dojo.marginBox('sq100border10').h);",
+ "doh.is(100, dojo.contentBox('sq100border10').w);",
+ "doh.is(100, dojo.contentBox('sq100border10').h);",
+
+ "doh.is(140, dojo.marginBox('sq100border10margin10').w);",
+ "doh.is(140, dojo.marginBox('sq100border10margin10').h);",
+ "doh.is(100, dojo.contentBox('sq100border10margin10').w);",
+ "doh.is(100, dojo.contentBox('sq100border10margin10').h);",
+
+ "doh.is(160, dojo.marginBox('sq100border10margin10pad10').w);",
+ "doh.is(160, dojo.marginBox('sq100border10margin10pad10').h);",
+ "doh.is(100, dojo.contentBox('sq100border10margin10pad10').w);",
+ "doh.is(100, dojo.contentBox('sq100border10margin10pad10').h);",
+
+ // FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+ // "doh.is(100, dojo.marginBox('sq100nopos').w);",
+ "doh.is(100, dojo.marginBox('sq100nopos').h);",
+
+ "doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).l);",
+ "doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).t);",
+ "doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).w);",
+ "doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).h);",
+
+ "doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).l);",
+ "doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).t);",
+ "doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).w);",
+ "doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).h);",
+
+ "doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).l);",
+ "doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).t);",
+ "doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).w);",
+ "doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).h);",
+
+ "doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).l);",
+ "doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).t);",
+ "doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).w);",
+ "doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).h);",
+
+ function coordsBasic(t){
+ var pos = dojo.coords("sq100", false);
+ // console.debug(pos);
+ doh.is(100, pos.x);
+ doh.is(100, pos.y);
+ doh.is(100, pos.w);
+ doh.is(100, pos.h);
+ },
+ function coordsMargin(t){
+ // coords is getting us the margin-box location, is
+ // this right?
+ var pos = dojo.coords("sq100margin10", false);
+ doh.is(260, pos.x);
+ doh.is(110, pos.y);
+ doh.is(120, pos.w);
+ doh.is(120, pos.h);
+ },
+ function coordsBorder(t){
+ var pos = dojo.coords("sq100border10", false);
+ doh.is(100, pos.x);
+ doh.is(400, pos.y);
+ },
+ function sq100nopos(t){
+ var pos = dojo.coords("sq100nopos", false);
+ // console.debug(pos);
+ doh.is(0, pos.x);
+ doh.t(pos.y > 0);
+ // FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+ // doh.is(100, pos.w);
+ doh.is(100, pos.h);
+ },
+ function coordsScrolled(t) {
+ var s = document.createElement('div');
+ var c = document.createElement('div');
+ document.body.appendChild(s);
+ s.appendChild(c);
+ var x=257, y= 285;
+ with (s.style) {
+ position = 'absolute';
+ overflow = 'scroll';
+ border = "10px solid black";
+ }
+ dojo._setMarginBox(s, x, y, 100, 100);
+ dojo._setMarginBox(c, 0, 0, 500, 500);
+ s.scrollTop = 200;
+ var pos = dojo.coords(s, true);
+ doh.is(x, pos.x);
+ doh.is(y, pos.y);
+ },
+ "doh.is(1, dojo.style('sq100nopos', 'opacity'));",
+ "doh.is(0.1, dojo.style('sq100nopos', 'opacity', 0.1));",
+ "doh.is(0.8, dojo.style('sq100nopos', 'opacity', 0.8));",
+ function styleObject(){
+ dojo.style('sq100nopos', { 'opacity': 0.1 });
+ doh.is(0.1, dojo.style('sq100nopos', 'opacity'));
+ dojo.style('sq100nopos', { 'opacity': 0.8 });
+ doh.is(0.8, dojo.style('sq100nopos', 'opacity'));
+ },
+ "doh.is('static', dojo.style('sq100nopos', 'position'));",
+ function getBgcolor(t){
+ var bgc = dojo.style('sq100nopos', 'backgroundColor');
+ doh.t((bgc == "rgb(0, 0, 0)")||(bgc == "black")||(bgc == "#000000"));
+ },
+ function isDescendant(t){
+ doh.t(dojo.isDescendant("sq100", dojo.body()));
+ doh.t(dojo.isDescendant("sq100", dojo.doc));
+ doh.t(dojo.isDescendant("sq100", "sq100"));
+ doh.t(dojo.isDescendant(dojo.byId("sq100"), "sq100"));
+ doh.f(dojo.isDescendant("sq100", dojo.byId("sq100").firstChild));
+ doh.t(dojo.isDescendant(dojo.byId("sq100").firstChild, "sq100"));
+ },
+ function isDescendantIframe(t){
+ var bif = dojo.byId("blah");
+ getIframeDocument(bif).write("<html><body><div id='subDiv'></div></body></html>");
+ getIframeDocument(bif).close();
+ // this test barely makes sense. disabling it for now.
+ // doh.t(dojo.isDescendant(bif.contentDocument.getElementById("subDiv"), bif.parentNode));
+ var subDiv = getIframeDocument(bif).getElementById("subDiv");
+ doh.t(dojo.isDescendant(subDiv, subDiv));
+ doh.t(dojo.isDescendant(subDiv, subDiv.parentNode));
+ doh.f(dojo.isDescendant(subDiv.parentNode, subDiv));
+
+ },
+ function testClassFunctions(t){
+ var node = dojo.byId("sq100");
+ dojo.addClass(node, "a");
+ doh.is("a", node.className);
+ dojo.removeClass(node, "c");
+ doh.is("a", node.className);
+ t.assertTrue(dojo.hasClass(node, "a"));
+ t.assertFalse(dojo.hasClass(node, "b"));
+ dojo.addClass(node, "b");
+ doh.is("a b", node.className);
+ t.assertTrue(dojo.hasClass(node, "a"));
+ t.assertTrue(dojo.hasClass(node, "b"));
+ dojo.removeClass(node, "a");
+ doh.is("b", node.className);
+ t.assertFalse(dojo.hasClass(node, "a"));
+ t.assertTrue(dojo.hasClass(node, "b"));
+ dojo.toggleClass(node, "a");
+ doh.is("b a", node.className);
+ t.assertTrue(dojo.hasClass(node, "a"));
+ t.assertTrue(dojo.hasClass(node, "b"));
+ dojo.toggleClass(node, "a");
+ doh.is("b", node.className);
+ t.assertFalse(dojo.hasClass(node, "a"));
+ t.assertTrue(dojo.hasClass(node, "b"));
+ dojo.toggleClass(node, "b");
+ doh.is("", node.className);
+ t.assertFalse(dojo.hasClass(node, "a"));
+ t.assertFalse(dojo.hasClass(node, "b"));
+ dojo.removeClass(node, "c");
+ t.assertTrue(!node.className);
+ },
+ function getTypeInput(t){
+ doh.f(dojo.hasAttr(dojo.byId("input-no-type"), "type"));
+ doh.is("text", dojo.attr(dojo.byId("input-no-type"), "type"));
+ doh.t(dojo.hasAttr(dojo.byId("input-with-type"), "type"));
+ doh.is("checkbox", dojo.attr(dojo.byId("input-with-type"), "type"));
+ },
+ function getWithString(t){
+ doh.f(dojo.hasAttr("input-no-type", "type"));
+ doh.is("text", dojo.attr("input-no-type", "type"));
+ doh.t(dojo.hasAttr("input-with-type", "type"));
+ doh.is("checkbox", dojo.attr("input-with-type", "type"));
+ },
+ function attrId(t){
+ doh.t(dojo.hasAttr("div-no-tabindex", "id"));
+ doh.is("div-no-tabindex", dojo.attr("div-no-tabindex", "id"));
+ var div = document.createElement("div");
+ doh.f(dojo.hasAttr(div, "id"));
+ doh.is(null, dojo.attr(div, "id"));
+ dojo.attr(div, "id", "attrId1");
+ doh.t(dojo.hasAttr(div, "id"));
+ doh.is("attrId1", dojo.attr(div, "id"));
+ dojo.removeAttr(div, "id");
+ doh.f(dojo.hasAttr(div, "id"));
+ doh.is(null, dojo.attr(div, "id"));
+ },
+ function getTabindexDiv(t){
+ doh.f(dojo.hasAttr("div-no-tabindex", "tabindex"));
+ doh.is(null, dojo.attr("div-no-tabindex", "tabindex"));
+ doh.t(dojo.hasAttr("div-tabindex-minus-1", "tabindex"));
+ if(!dojo.isOpera){
+ // Opera (at least <= 9) does not support tabindex="-1"
+ doh.is(-1, dojo.attr("div-tabindex-minus-1", "tabindex"));
+ }
+ doh.t(dojo.hasAttr("div-tabindex-0", "tabindex"));
+ doh.is(0, dojo.attr("div-tabindex-0", "tabindex"));
+ doh.is(1, dojo.attr("div-tabindex-1", "tabindex"));
+ },
+ function getTabindexInput(t){
+ doh.f(dojo.hasAttr("input-no-tabindex", "tabindex"));
+ doh.is(null, dojo.attr("input-no-tabindex", "tabindex"));
+ doh.t(dojo.hasAttr("input-tabindex-minus-1", "tabindex"));
+ if(!dojo.isOpera){
+ // Opera (at least <= 9) does not support tabindex="-1"
+ doh.is(-1, dojo.attr("input-tabindex-minus-1", "tabindex"));
+ }
+ doh.t(dojo.hasAttr("input-tabindex-0", "tabindex"));
+ doh.is(0, dojo.attr("input-tabindex-0", "tabindex"));
+ doh.is(1, dojo.attr("input-tabindex-1", "tabindex"));
+ },
+ function setTabindexDiv(t){
+ var div = document.createElement("div");
+ doh.is(null, dojo.attr(div, "tabindex"));
+ dojo.attr(div, "tabindex", -1);
+ if(!dojo.isOpera){
+ // Opera (at least <= 9) does not support tabindex="-1"
+ doh.is(-1, dojo.attr(div, "tabindex"));
+ }
+ dojo.attr(div, "tabindex", 0);
+ doh.is(0, dojo.attr(div, "tabindex"));
+ dojo.attr(div, "tabindex", 1);
+ doh.is(1, dojo.attr(div, "tabindex"));
+ },
+ function setTabindexInput(t){
+ var input = document.createElement("input");
+ doh.is(null, dojo.attr(input, "tabindex"));
+ dojo.attr(input, "tabindex", -1);
+ if(!dojo.isOpera){
+ // Opera (at least <= 9) does not support tabindex="-1"
+ doh.is(-1, dojo.attr(input, "tabindex"));
+ }
+ dojo.attr(input, "tabindex", 0);
+ doh.is(0, dojo.attr(input, "tabindex"));
+ dojo.attr(input, "tabindex", 1);
+ doh.is(1, dojo.attr(input, "tabindex"));
+ },
+ function removeTabindexFromDiv(t){
+ var div = document.createElement("div");
+ dojo.attr(div, "tabindex", 1);
+ doh.is(1, dojo.attr(div, "tabindex"));
+ dojo.removeAttr(div, "tabindex");
+ doh.is(null, dojo.attr(div, "tabindex"));
+ },
+ function removeTabindexFromInput(t){
+ var input = document.createElement("input");
+ dojo.attr(input, "tabindex", 1);
+ doh.is(1, dojo.attr(input, "tabindex"));
+ dojo.removeAttr(input, "tabindex");
+ doh.is(null, dojo.attr(input, "tabindex"));
+ },
+ function attr_map(t){
+ var input = document.createElement("input");
+ var ctr= 0;
+ dojo.attr(input, {
+ "tabindex": 1,
+ "type": "text",
+ "onfocus": function(e){
+ ctr++;
+ }
+ });
+ dojo.body().appendChild(input);
+ doh.is(1, dojo.attr(input, "tabindex"));
+ doh.is("text", dojo.attr(input, "type"));
+ doh.is(0, ctr);
+ var def = new doh.Deferred();
+ input.focus();
+ setTimeout(function(){
+ doh.is(1, ctr);
+ input.blur();
+ input.focus();
+ setTimeout(function(){
+ doh.is(2, ctr);
+ def.callback(true);
+ }, 10);
+ }, 10);
+ return def;
+ },
+ function attr_reconnect(t){
+ var input = document.createElement("input");
+ var ctr = 0;
+ dojo.attr(input, "type", "text");
+ dojo.attr(input, "onfocus", function(e){ ctr++; });
+ dojo.attr(input, "onfocus", function(e){ ctr++; });
+ dojo.attr(input, "onfocus", function(e){ ctr++; });
+ dojo.body().appendChild(input);
+ doh.is("text", dojo.attr(input, "type"));
+ doh.is(0, ctr);
+ var def = new doh.Deferred();
+ input.focus();
+ setTimeout(function(){
+ doh.is(1, ctr);
+ input.blur();
+ input.focus();
+ setTimeout(function(){
+ doh.is(2, ctr);
+ def.callback(true);
+ }, 10);
+ }, 10);
+ return def;
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <style type="text/css">
+ html, body {
+ padding: 0px;
+ margin: 0px;
+ border: 0px;
+ }
+
+ #sq100 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100margin10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 250px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 0px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100margin10pad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 400px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 10px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100pad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 250px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 10px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100ltpad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 250px;
+ top: 250px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding-left: 10px;
+ padding-top: 10px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100ltpad10rbmargin10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 400px;
+ top: 250px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding-left: 10px;
+ padding-top: 10px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ margin-left: 0px;
+ margin-top: 0px;
+ margin-right: 10px;
+ margin-bottom: 10px;
+ overflow: hidden;
+ }
+
+ #sq100border10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 400px;
+ width: 100px;
+ height: 100px;
+ border: 10px solid yellow;
+ padding: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100border10margin10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 250px;
+ top: 400px;
+ width: 100px;
+ height: 100px;
+ border: 10px solid yellow;
+ padding: 0px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100border10margin10pad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 400px;
+ top: 400px;
+ width: 100px;
+ height: 100px;
+ border: 10px solid yellow;
+ padding: 10px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100nopos {
+ background-color: black;
+ color: white;
+ width: 100px;
+ height: 100px;
+ padding: 0px;
+ margin: 0px;
+ }
+
+ </style>
+ </head>
+ <body>
+ <h1>testing Core HTML/DOM/CSS/Style utils</h1>
+ <div id="sq100">
+ 100px square, abs
+ </div>
+ <div id="sq100margin10">
+ 100px square, abs, 10px margin
+ </div>
+ <div id="sq100margin10pad10">
+ 100px square, abs, 10px margin, 10px padding
+ </div>
+ <div id="sq100pad10">
+ 100px square, abs, 10px padding
+ </div>
+ <div id="sq100ltpad10">
+ 100px square, abs, 10px left and top padding
+ </div>
+ <div id="sq100ltpad10rbmargin10">
+ 100px square, abs, 10px left and top padding, 10px bottom and right margin
+ </div>
+ <div id="sq100border10">
+ 100px square, abs, 10px yellow border
+ </div>
+ <div id="sq100border10margin10">
+ 100px square, abs, 10px yellow border, 10px margin
+ </div>
+ <div id="sq100border10margin10pad10">
+ 100px square, abs, 10px yellow border, 10px margin, 10px padding
+ </div>
+ <div id="sq100nopos">
+ 100px square, no positioning
+ </div>
+ <iframe id="blah"></iframe>
+
+ <div id="div-no-tabindex"></div>
+ <div id="div-tabindex-minus-1" tabindex="-1"></div>
+ <div id="div-tabindex-0" tabindex="0"></div>
+ <div id="div-tabindex-1" tabindex="1"></div>
+
+ <div>
+ <input id="input-no-type">
+ <input id="input-with-type" type="checkbox">
+ <input id="input-no-tabindex">
+ <input id="input-tabindex-minus-1" tabindex="-1">
+ <input id="input-tabindex-0" tabindex="0">
+ <input id="input-tabindex-1" tabindex="1">
+ </div>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/html.js b/includes/js/dojo/tests/_base/html.js
new file mode 100644
index 0000000..99fe80b
--- /dev/null
+++ b/includes/js/dojo/tests/_base/html.js
@@ -0,0 +1,12 @@
+if(!dojo._hasResource["tests._base.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.html"] = true;
+dojo.provide("tests._base.html");
+if(dojo.isBrowser){
+ doh.registerUrl("tests._base.html", dojo.moduleUrl("tests", "_base/html.html"), 15000);
+ doh.registerUrl("tests._base.html_rtl", dojo.moduleUrl("tests", "_base/html_rtl.html"), 15000);
+ doh.registerUrl("tests._base.html_quirks", dojo.moduleUrl("tests", "_base/html_quirks.html"), 15000);
+ doh.registerUrl("tests._base.html_box", dojo.moduleUrl("tests", "_base/html_box.html"), 35000);
+ doh.registerUrl("tests._base.html_box_quirks", dojo.moduleUrl("tests", "_base/html_box_quirks.html"), 35000);
+}
+
+}
diff --git a/includes/js/dojo/tests/_base/html_box.html b/includes/js/dojo/tests/_base/html_box.html
new file mode 100644
index 0000000..fd7ec53
--- /dev/null
+++ b/includes/js/dojo/tests/_base/html_box.html
@@ -0,0 +1,207 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+ we use a strict-mode DTD to ensure that the box model is the same for these
+ basic tests
+-->
+<html>
+ <head>
+ <title> test html.js Box utils</title>
+ <style type="text/css">
+ /*@import "../../resources/dojo.css";*/
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js"
+ djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+
+ var margin = '1px';
+ var border = '3px solid black';
+ var padding = '5px';
+ var defaultStyles = {
+ height: '100px',
+ width: '100px',
+ position: 'absolute',
+ backgroundColor: 'red'
+ };
+
+ var defaultChildStyles = {
+ height: '20px',
+ width: '20px',
+ backgroundColor: 'blue'
+ }
+
+ var testStyles = [
+ {},
+ {margin: margin},
+ {border: border},
+ {padding: padding},
+ {margin: margin, border: border},
+ {margin: margin, padding: padding},
+ {border: border, padding: padding},
+ {margin: margin, border: border, padding: padding}
+ ]
+
+
+ function sameBox(inBox1, inBox2) {
+ for (var i in inBox1)
+ if (inBox1[i] != inBox2[i]) {
+ console.log((arguments[2]||'box1') + '.' + i + ': ', inBox1[i], ' != ', (arguments[3]||'box2') + '.' + i + ': ', inBox2[i]);
+ return false;
+ }
+ return true;
+ }
+
+ function reciprocalMarginBoxTest(inNode, inBox) {
+ var s = inBox || dojo.marginBox(inNode);
+ dojo.marginBox(inNode, s);
+ var e = dojo.marginBox(inNode);
+ return sameBox(s, e);
+ }
+
+ function fitTest(inParent, inChild) {
+ var pcb = dojo.contentBox(inParent);
+ return reciprocalMarginBoxTest(inChild, pcb);
+ }
+
+ function createStyledElement(inStyle, inParent, inElement, inNoDefault) {
+ inStyle = inStyle||{};
+ if (!inNoDefault) {
+ for (var i in defaultStyles)
+ if (!inStyle[i])
+ inStyle[i] = defaultStyles[i];
+ }
+ var n = document.createElement(inElement || 'div');
+ (inParent||document.body).appendChild(n);
+ dojo.mixin(n.style, inStyle);
+ return n;
+ }
+
+ var _testTopInc = 0;
+ var _testTop = 150;
+ var _testInitTop = 250;
+ function styleIncTop(inStyle) {
+ inStyle = dojo.mixin({}, inStyle||{});
+ inStyle.top = (_testInitTop + _testTop*_testTopInc) + 'px';
+ _testTopInc++;
+ return inStyle;
+ }
+
+ function removeTestNode(inNode) {
+ // leave nodes for inspection or don't return to delete them
+ return;
+ inNode = dojo.byId(inNode);
+ inNode.parentNode.removeChild(inNode);
+ _testTopInc--;
+ }
+
+ function testAndCallback(inTest, inAssert, inComment, inOk, inErr) {
+ inTest.assertTrue('/* ' + inComment + '*/' + inAssert);
+ if (inAssert)
+ inOk&&inOk();
+ else
+ inErr&&inErr();
+ }
+
+ // args are (styles, parent, element name, no default)
+ function mixCreateElementArgs(inMix, inArgs) {
+ args = [{}];
+ if (inArgs&&inArgs[0])
+ dojo.mixin(args[0], inArgs[0]);
+ if (inMix.length)
+ dojo.mixin(args[0], inMix[0]||{});
+ // parent comes from source
+ if (inMix.length > 1)
+ args[1] = inMix[1];
+ args[2] = inArgs[2];
+ args[3] = inArgs[3]
+ return args;
+ };
+
+ function createStyledNodes(inArgs, inFunc) {
+ for (var i=0, n; (s=testStyles[i]); i++) {
+ n = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inArgs));
+ inFunc&&inFunc(n);
+ }
+ }
+
+ function createStyledParentChild(inParentArgs, inChildArgs, inFunc) {
+ for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+ p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+ c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+ inFunc&&inFunc(p, c);
+ }
+ }
+
+ function createStyledParentChildren(inParentArgs, inChildArgs, inFunc) {
+ for (var i=0, s, p; (s=testStyles[i]); i++)
+ for (var j=0, sc, c, props; (sc=testStyles[j]); j++) {
+ p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+ c = createStyledElement.apply(this, mixCreateElementArgs([sc, p], inChildArgs));
+ inFunc&&inFunc(p, c);
+ }
+
+ for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+ p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+ c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+ inFunc&&inFunc(p, c);
+ }
+ }
+
+
+ function runFitTest(inTest, inParentStyles, inChildStyles) {
+ createStyledParentChildren([inParentStyles], [inChildStyles], function(p, c) {
+ testAndCallback(inTest, fitTest(p, c), '', function() {removeTestNode(p); });
+ });
+ }
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function reciprocalTests(t) {
+ createStyledNodes([], function(n) {
+ testAndCallback(t, reciprocalMarginBoxTest(n), '', function() {removeTestNode(n); });
+ });
+ },
+ function fitTests(t) {
+ runFitTest(t, null, dojo.mixin({}, defaultChildStyles));
+ },
+ function fitTestsOverflow(t) {
+ runFitTest(t, null, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+ runFitTest(t, {overflow: 'hidden'}, dojo.mixin({}, defaultChildStyles));
+ runFitTest(t, {overflow: 'hidden'}, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+ },
+ function fitTestsFloat(t) {
+ runFitTest(t, null, dojo.mixin({float: 'left'}, defaultChildStyles));
+ runFitTest(t, {float: 'left'}, dojo.mixin({}, defaultChildStyles));
+ runFitTest(t, {float: 'left'}, dojo.mixin({float: 'left'}, defaultChildStyles));
+ },
+ function reciprocalTestsInline(t) {
+ createStyledParentChild([], [{}, null, 'span'], function(p, c) {
+ c.innerHTML = 'Hello World';
+ testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+ });
+ },
+ function reciprocalTestsButtonChild(t) {
+ createStyledParentChild([], [{}, null, 'button'], function(p, c) {
+ c.innerHTML = 'Hello World';
+ testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+ });
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <style type="text/css">
+ html, body {
+ padding: 0px;
+ margin: 0px;
+ border: 0px;
+ }
+ </style>
+ </head>
+ <body>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/html_box_quirks.html b/includes/js/dojo/tests/_base/html_box_quirks.html
new file mode 100644
index 0000000..f87ca44
--- /dev/null
+++ b/includes/js/dojo/tests/_base/html_box_quirks.html
@@ -0,0 +1,205 @@
+<!--
+ we use a quirks-mode DTD to check for quirks!
+-->
+<html>
+ <head>
+ <title> test html.js Box utils</title>
+ <style type="text/css">
+ /*@import "../../resources/dojo.css";*/
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js"
+ djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+
+ var margin = '1px';
+ var border = '3px solid black';
+ var padding = '5px';
+ var defaultStyles = {
+ height: '100px',
+ width: '100px',
+ position: 'absolute',
+ backgroundColor: 'red'
+ };
+
+ var defaultChildStyles = {
+ height: '20px',
+ width: '20px',
+ backgroundColor: 'blue'
+ }
+
+ var testStyles = [
+ {},
+ {margin: margin},
+ {border: border},
+ {padding: padding},
+ {margin: margin, border: border},
+ {margin: margin, padding: padding},
+ {border: border, padding: padding},
+ {margin: margin, border: border, padding: padding}
+ ]
+
+
+ function sameBox(inBox1, inBox2) {
+ for (var i in inBox1)
+ if (inBox1[i] != inBox2[i]) {
+ console.log((arguments[2]||'box1') + '.' + i + ': ', inBox1[i], ' != ', (arguments[3]||'box2') + '.' + i + ': ', inBox2[i]);
+ return false;
+ }
+ return true;
+ }
+
+ function reciprocalMarginBoxTest(inNode, inBox) {
+ var s = inBox || dojo.marginBox(inNode);
+ dojo.marginBox(inNode, s);
+ var e = dojo.marginBox(inNode);
+ return sameBox(s, e);
+ }
+
+ function fitTest(inParent, inChild) {
+ var pcb = dojo.contentBox(inParent);
+ return reciprocalMarginBoxTest(inChild, pcb);
+ }
+
+ function createStyledElement(inStyle, inParent, inElement, inNoDefault) {
+ inStyle = inStyle||{};
+ if (!inNoDefault) {
+ for (var i in defaultStyles)
+ if (!inStyle[i])
+ inStyle[i] = defaultStyles[i];
+ }
+ var n = document.createElement(inElement || 'div');
+ (inParent||document.body).appendChild(n);
+ dojo.mixin(n.style, inStyle);
+ return n;
+ }
+
+ var _testTopInc = 0;
+ var _testTop = 150;
+ var _testInitTop = 250;
+ function styleIncTop(inStyle) {
+ inStyle = dojo.mixin({}, inStyle||{});
+ inStyle.top = (_testInitTop + _testTop*_testTopInc) + 'px';
+ _testTopInc++;
+ return inStyle;
+ }
+
+ function removeTestNode(inNode) {
+ // leave nodes for inspection or don't return to delete them
+ return;
+ inNode = dojo.byId(inNode);
+ inNode.parentNode.removeChild(inNode);
+ _testTopInc--;
+ }
+
+ function testAndCallback(inTest, inAssert, inComment, inOk, inErr) {
+ inTest.assertTrue('/* ' + inComment + '*/' + inAssert);
+ if (inAssert)
+ inOk&&inOk();
+ else
+ inErr&&inErr();
+ }
+
+ // args are (styles, parent, element name, no default)
+ function mixCreateElementArgs(inMix, inArgs) {
+ args = [{}];
+ if (inArgs&&inArgs[0])
+ dojo.mixin(args[0], inArgs[0]);
+ if (inMix.length)
+ dojo.mixin(args[0], inMix[0]||{});
+ // parent comes from source
+ if (inMix.length > 1)
+ args[1] = inMix[1];
+ args[2] = inArgs[2];
+ args[3] = inArgs[3]
+ return args;
+ };
+
+ function createStyledNodes(inArgs, inFunc) {
+ for (var i=0, n; (s=testStyles[i]); i++) {
+ n = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inArgs));
+ inFunc&&inFunc(n);
+ }
+ }
+
+ function createStyledParentChild(inParentArgs, inChildArgs, inFunc) {
+ for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+ p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+ c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+ inFunc&&inFunc(p, c);
+ }
+ }
+
+ function createStyledParentChildren(inParentArgs, inChildArgs, inFunc) {
+ for (var i=0, s, p; (s=testStyles[i]); i++)
+ for (var j=0, sc, c, props; (sc=testStyles[j]); j++) {
+ p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+ c = createStyledElement.apply(this, mixCreateElementArgs([sc, p], inChildArgs));
+ inFunc&&inFunc(p, c);
+ }
+
+ for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+ p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+ c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+ inFunc&&inFunc(p, c);
+ }
+ }
+
+
+ function runFitTest(inTest, inParentStyles, inChildStyles) {
+ createStyledParentChildren([inParentStyles], [inChildStyles], function(p, c) {
+ testAndCallback(inTest, fitTest(p, c), '', function() {removeTestNode(p); });
+ });
+ }
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function reciprocalTests(t) {
+ createStyledNodes([], function(n) {
+ testAndCallback(t, reciprocalMarginBoxTest(n), '', function() {removeTestNode(n); });
+ });
+ },
+ function fitTests(t) {
+ runFitTest(t, null, dojo.mixin({}, defaultChildStyles));
+ },
+ function fitTestsOverflow(t) {
+ runFitTest(t, null, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+ runFitTest(t, {overflow: 'hidden'}, dojo.mixin({}, defaultChildStyles));
+ runFitTest(t, {overflow: 'hidden'}, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+ },
+ function fitTestsFloat(t) {
+ runFitTest(t, null, dojo.mixin({float: 'left'}, defaultChildStyles));
+ runFitTest(t, {float: 'left'}, dojo.mixin({}, defaultChildStyles));
+ runFitTest(t, {float: 'left'}, dojo.mixin({float: 'left'}, defaultChildStyles));
+ },
+ function reciprocalTestsInline(t) {
+ createStyledParentChild([], [{}, null, 'span'], function(p, c) {
+ c.innerHTML = 'Hello World';
+ testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+ });
+ },
+ function reciprocalTestsButtonChild(t) {
+ createStyledParentChild([], [{}, null, 'button'], function(p, c) {
+ c.innerHTML = 'Hello World';
+ testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+ });
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <style type="text/css">
+ html, body {
+ padding: 0px;
+ margin: 0px;
+ border: 0px;
+ }
+ </style>
+ </head>
+ <body>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/html_quirks.html b/includes/js/dojo/tests/_base/html_quirks.html
new file mode 100644
index 0000000..ddc7825
--- /dev/null
+++ b/includes/js/dojo/tests/_base/html_quirks.html
@@ -0,0 +1,322 @@
+<html>
+ <!--
+ we use a quirks-mode DTD on purpose to ensure that things go tilt. Wheee!!
+ -->
+ <head>
+ <title>testing Core HTML/DOM/CSS/Style utils in quirks mode</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js"
+ djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ "t.is(100, dojo.marginBox('sq100').w);",
+ "t.is(100, dojo.marginBox('sq100').h);",
+
+ "t.is(120, dojo.marginBox('sq100margin10').w);",
+ "t.is(120, dojo.marginBox('sq100margin10').h);",
+ "t.is(100, dojo.contentBox('sq100margin10').w);",
+ "t.is(100, dojo.contentBox('sq100margin10').h);",
+
+ // FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+ //"t.is(100, dojo.marginBox('sq100nopos').w);",
+ "t.is(100, dojo.marginBox('sq100nopos').h);",
+
+ function coordsBasic(t){
+ var pos = dojo.coords("sq100", false);
+ // console.debug(pos);
+ t.is(100, pos.x);
+ t.is(100, pos.y);
+ t.is(100, pos.w);
+ t.is(100, pos.h);
+ },
+ function coordsMargin(t){
+ // coords is getting us the margin-box location, is
+ // this right?
+ var pos = dojo.coords("sq100margin10", false);
+ t.is(260, pos.x);
+ t.is(110, pos.y);
+ t.is(120, pos.w);
+ t.is(120, pos.h);
+ },
+ function coordsBorder(t){
+ var pos = dojo.coords("sq100border10", false);
+ t.is(100, pos.x);
+ t.is(400, pos.y);
+ },
+ function sq100nopos(t){
+ var pos = dojo.coords("sq100nopos", false);
+ // console.debug(pos);
+ t.is(0, pos.x);
+ t.t(pos.y > 0);
+ // FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+ //t.is(100, pos.w);
+ t.is(100, pos.h);
+ }
+ ]
+ );
+ if(dojo.isIE){
+ // IE collapses padding in quirks mode. We just report on it.
+ doh.register("t",
+ [
+ "t.is(120, dojo.marginBox('sq100margin10pad10').w);",
+ "t.is(120, dojo.marginBox('sq100margin10pad10').h);",
+
+ "t.is(100, dojo.marginBox('sq100pad10').w);",
+ "t.is(100, dojo.marginBox('sq100pad10').h);",
+
+ "t.is(100, dojo.marginBox('sq100ltpad10').w);",
+ "t.is(100, dojo.marginBox('sq100ltpad10').h);",
+ "t.is(90, dojo.contentBox('sq100ltpad10').w);",
+ "t.is(90, dojo.contentBox('sq100ltpad10').h);",
+
+ "t.is(110, dojo.marginBox('sq100ltpad10rbmargin10').w);",
+ "t.is(110, dojo.marginBox('sq100ltpad10rbmargin10').h);",
+
+ "t.is(100, dojo.marginBox('sq100border10').w);",
+ "t.is(100, dojo.marginBox('sq100border10').h);",
+ "t.is(80, dojo.contentBox('sq100border10').w);",
+ "t.is(80, dojo.contentBox('sq100border10').h);",
+
+ "t.is(120, dojo.marginBox('sq100border10margin10').w);",
+ "t.is(120, dojo.marginBox('sq100border10margin10').h);",
+ "t.is(80, dojo.contentBox('sq100border10margin10').w);",
+ "t.is(80, dojo.contentBox('sq100border10margin10').h);",
+
+ "t.is(120, dojo.marginBox('sq100border10margin10pad10').w);",
+ "t.is(120, dojo.marginBox('sq100border10margin10pad10').h);",
+ "t.is(60, dojo.contentBox('sq100border10margin10pad10').w);",
+ "t.is(60, dojo.contentBox('sq100border10margin10pad10').h);"
+ ]
+ );
+ }else{
+ doh.register("t",
+ [
+ "t.is(140, dojo.marginBox('sq100margin10pad10').w);",
+ "t.is(140, dojo.marginBox('sq100margin10pad10').h);",
+
+ "t.is(120, dojo.marginBox('sq100pad10').w);",
+ "t.is(120, dojo.marginBox('sq100pad10').h);",
+
+ "t.is(110, dojo.marginBox('sq100ltpad10').w);",
+ "t.is(110, dojo.marginBox('sq100ltpad10').h);",
+ "t.is(100, dojo.contentBox('sq100ltpad10').w);",
+ "t.is(100, dojo.contentBox('sq100ltpad10').h);",
+
+ "t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w);",
+ "t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h);",
+
+ "t.is(120, dojo.marginBox('sq100border10').w);",
+ "t.is(120, dojo.marginBox('sq100border10').h);",
+ "t.is(100, dojo.contentBox('sq100border10').w);",
+ "t.is(100, dojo.contentBox('sq100border10').h);",
+
+ "t.is(140, dojo.marginBox('sq100border10margin10').w);",
+ "t.is(140, dojo.marginBox('sq100border10margin10').h);",
+ "t.is(100, dojo.contentBox('sq100border10margin10').w);",
+ "t.is(100, dojo.contentBox('sq100border10margin10').h);",
+
+ "t.is(160, dojo.marginBox('sq100border10margin10pad10').w);",
+ "t.is(160, dojo.marginBox('sq100border10margin10pad10').h);",
+ "t.is(100, dojo.contentBox('sq100border10margin10pad10').w);",
+ "t.is(100, dojo.contentBox('sq100border10margin10pad10').h);"
+ ]
+ );
+ }
+
+ doh.run();
+ });
+ </script>
+ <style type="text/css">
+ html, body {
+ padding: 0px;
+ margin: 0px;
+ border: 0px;
+ }
+
+ #sq100 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100margin10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 250px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 0px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100margin10pad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 400px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 10px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100pad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 250px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 10px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100ltpad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 250px;
+ top: 250px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding-left: 10px;
+ padding-top: 10px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100ltpad10rbmargin10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 400px;
+ top: 250px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding-left: 10px;
+ padding-top: 10px;
+ padding-right: 0px;
+ padding-bottom: 0px;
+ margin-left: 0px;
+ margin-top: 0px;
+ margin-right: 10px;
+ margin-bottom: 10px;
+ overflow: hidden;
+ }
+
+ #sq100border10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 400px;
+ width: 100px;
+ height: 100px;
+ border: 10px solid yellow;
+ padding: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ #sq100border10margin10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 250px;
+ top: 400px;
+ width: 100px;
+ height: 100px;
+ border: 10px solid yellow;
+ padding: 0px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100border10margin10pad10 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 400px;
+ top: 400px;
+ width: 100px;
+ height: 100px;
+ border: 10px solid yellow;
+ padding: 10px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ #sq100nopos {
+ background-color: black;
+ color: white;
+ width: 100px;
+ height: 100px;
+ padding: 0px;
+ margin: 0px;
+ }
+
+ </style>
+ </head>
+ <body>
+ <h1>testing Core HTML/DOM/CSS/Style utils</h1>
+ <div id="sq100">
+ 100px square, abs
+ </div>
+ <div id="sq100margin10">
+ 100px square, abs, 10px margin
+ </div>
+ <div id="sq100margin10pad10">
+ 100px square, abs, 10px margin, 10px padding
+ </div>
+ <div id="sq100pad10">
+ 100px square, abs, 10px padding
+ </div>
+ <div id="sq100ltpad10">
+ 100px square, abs, 10px left and top padding
+ </div>
+ <div id="sq100ltpad10rbmargin10">
+ 100px square, abs, 10px left and top padding, 10px bottom and right margin
+ </div>
+ <div id="sq100border10">
+ 100px square, abs, 10px yellow border
+ </div>
+ <div id="sq100border10margin10">
+ 100px square, abs, 10px yellow border, 10px margin
+ </div>
+ <div id="sq100border10margin10pad10">
+ 100px square, abs, 10px yellow border, 10px margin, 10px padding
+ </div>
+ <div id="sq100nopos">
+ 100px square, no positioning
+ </div>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/html_rtl.html b/includes/js/dojo/tests/_base/html_rtl.html
new file mode 100644
index 0000000..8d74afa
--- /dev/null
+++ b/includes/js/dojo/tests/_base/html_rtl.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html dir="rtl">
+ <head>
+ <title>testing Core HTML/DOM/CSS/Style utils</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js"
+ djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function coordsWithVertScrollbar(t){
+ // show vertical scrollbar
+ dojo.byId("rect_vert").style.display = "";
+ try{
+ t.is(100, dojo.coords('rect100').x);
+ }finally{
+ dojo.byId("rect_vert").style.display = "none";
+ }
+ },
+
+ function coordsWithHorzScrollbar(t){
+ // show horizonal scrollbar & scroll a bit left
+ dojo.byId("rect_horz").style.display = "";
+ scrollBy(-50, 0);
+ try{
+ t.is(100, dojo.coords('rect100', true).x);
+ }finally{
+ dojo.byId("rect_horz").style.display = "none";
+ }
+ },
+
+ function eventClientXY(t){ // IE only test
+ if(dojo.isIE){
+ // show vertical scrollbar
+ dojo.byId("rect_vert").style.display = "";
+
+ var rect = dojo.byId("rect100");
+ var assertException = null;
+
+ function rect_onclick(e){
+ // move the rectangle to the mouse point
+ rect.style.left = e.pageX + "px";
+ rect.style.top = e.pageY + "px";
+ window.alert("Do NOT move your mouse!!!\n\n" +
+ "The black rectangle's top-left point should be under the mouse point.\n\n" +
+ "If not, you will see a failure in the test report later.\n\n" +
+ "Now press the space bar, but do NOT move your mouse.");
+ rect.fireEvent('ondblclick');
+ }
+
+ function rect_ondblclick(){
+ // test if the rectangle is really under the mouse point
+ try{
+ t.is(0, event.offsetX);
+ t.is(0, event.offsetY);
+ }catch (e){ // allow the exception in a event handler go to the event firer
+ assertException = e;
+ }
+ }
+
+ dojo.connect(rect, "onclick", null, rect_onclick);
+ dojo.connect(rect, "ondblclick", null, rect_ondblclick);
+ window.alert("Move the mouse to anywhere in this page, and then press the space bar.");
+ rect.fireEvent('onclick');
+ if(assertException != null){
+ throw assertException;
+ }
+ }
+ }
+
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <style type="text/css">
+ #rect100 {
+ background-color: black;
+ color: white;
+ position: absolute;
+ left: 100px;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ border: 0px;
+ padding: 0px;
+ margin: 0px;
+ overflow: hidden;
+ }
+
+ </style>
+ </head>
+ <body>
+ <h1>testing Core HTML/DOM/CSS/Style utils</h1>
+ <div id="rect100">
+ 100px rect, abs,
+ mouse point is at top-left after the test "eventClientXY"
+ </div>
+ <div id="rect_vert" style="height:1600px;display:none">show vertical scrollbar</div>
+ <div id="rect_horz" style="width:1600px;display:none">show horizonal scrollbar</div>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/json.js b/includes/js/dojo/tests/_base/json.js
new file mode 100644
index 0000000..3a9a24c
--- /dev/null
+++ b/includes/js/dojo/tests/_base/json.js
@@ -0,0 +1,37 @@
+if(!dojo._hasResource["tests._base.json"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.json"] = true;
+dojo.provide("tests._base.json");
+
+tests.register("tests._base.json",
+ [
+ //Not testing dojo.toJson() on its own since Rhino will output the object properties in a different order.
+ //Still valid json, but just in a different order than the source string.
+
+ // take a json-compatible object, convert it to a json string, then put it back into json.
+ function toAndFromJson(t){
+ var testObj = {a:"a", b:1, c:"c", d:"d", e:{e1:"e1", e2:2}, f:[1,2,3], g:"g",h:{h1:{h2:{h3:"h3"}}}};
+
+ var mirrorObj = dojo.fromJson(dojo.toJson(testObj));
+ t.assertEqual("a", mirrorObj.a);
+ t.assertEqual(1, mirrorObj.b);
+ t.assertEqual("c", mirrorObj.c);
+ t.assertEqual("d", mirrorObj.d);
+ t.assertEqual("e1", mirrorObj.e.e1);
+ t.assertEqual(2, mirrorObj.e.e2);
+ t.assertEqual(1, mirrorObj.f[0]);
+ t.assertEqual(2, mirrorObj.f[1]);
+ t.assertEqual(3, mirrorObj.f[2]);
+ t.assertEqual("g", mirrorObj.g);
+ t.assertEqual("h3", mirrorObj.h.h1.h2.h3);
+ var badJson;
+ try{
+ badJson = dojo.fromJson("bad json"); // this should throw an exception, and not set badJson
+ }catch(e){
+ }
+ t.assertEqual(undefined,badJson);
+ }
+ ]
+);
+
+
+}
diff --git a/includes/js/dojo/tests/_base/lang.js b/includes/js/dojo/tests/_base/lang.js
new file mode 100644
index 0000000..38acbff
--- /dev/null
+++ b/includes/js/dojo/tests/_base/lang.js
@@ -0,0 +1,180 @@
+if(!dojo._hasResource["tests._base.lang"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.lang"] = true;
+dojo.provide("tests._base.lang");
+
+tests.register("tests._base.lang",
+ [
+ function mixin(t){
+ var src = {
+ foo: function(){
+ t.debug("foo");
+ },
+ bar: "bar"
+ };
+ var dest = {};
+ dojo.mixin(dest, src);
+ t.assertEqual("function", typeof dest["foo"]);
+ t.assertEqual("string", typeof dest["bar"]);
+ },
+
+ function extend(t){
+ var src = {
+ foo: function(){
+ t.debug("foo");
+ },
+ bar: "bar"
+ };
+ function dest(){}
+ dojo.extend(dest, src);
+ var test = new dest();
+ t.assertEqual("function", typeof test["foo"]);
+ t.assertEqual("string", typeof test["bar"]);
+ },
+
+ function isObject(t){
+ t.assertFalse(dojo.isObject(true));
+ t.assertFalse(dojo.isObject(false));
+ t.assertFalse(dojo.isObject("foo"));
+ t.assertTrue(dojo.isObject(new String("foo")));
+ t.assertTrue(dojo.isObject(null));
+ t.assertTrue(dojo.isObject({}));
+ t.assertTrue(dojo.isObject([]));
+ t.assertTrue(dojo.isObject(new Array()));
+ },
+
+ function isArray(t){
+ t.assertTrue(dojo.isArray([]));
+ t.assertTrue(dojo.isArray(new Array()));
+ t.assertFalse(dojo.isArray({}));
+ },
+
+ function isArrayLike(t){
+ t.assertFalse(dojo.isArrayLike("thinger"));
+ t.assertTrue(dojo.isArrayLike(new Array()));
+ t.assertFalse(dojo.isArrayLike({}));
+ t.assertTrue(dojo.isArrayLike(arguments));
+ },
+
+ function isString(t){
+ t.assertFalse(dojo.isString(true));
+ t.assertFalse(dojo.isString(false));
+ t.assertTrue(dojo.isString("foo"));
+ t.assertTrue(dojo.isString(new String("foo")));
+ t.assertFalse(dojo.isString(null));
+ t.assertFalse(dojo.isString({}));
+ t.assertFalse(dojo.isString([]));
+ },
+
+ function partial(t){
+ var scope = { foo: "bar" };
+ var scope2 = { foo: "baz" };
+ function thinger(arg1, arg2){
+ return [this.foo, arg1, arg2];
+ }
+
+ var st1 = dojo.partial(thinger);
+ t.assertEqual("bar", st1.call(scope)[0]);
+ t.assertEqual(undefined, st1()[0]);
+ var st2 = dojo.partial(thinger, "foo", "bar");
+ t.assertEqual("bar", st2()[2]);
+ var st3 = dojo.partial(thinger, "foo", "bar");
+ },
+
+ function nestedPartial(t){
+ function thinger(arg1, arg2){
+ return [arg1, arg2];
+ }
+
+ var st1 = dojo.partial(thinger, "foo");
+ t.assertEqual(undefined, st1()[1]);
+ t.assertEqual("bar", st1("bar")[1]);
+
+ // partials can accumulate
+ var st2 = dojo.partial(st1, "thud");
+ t.assertEqual("foo", st2()[0]);
+ t.assertEqual("thud", st2()[1]);
+ },
+
+ function hitch(t){
+ var scope = { foo: "bar" };
+ var scope2 = { foo: "baz" };
+ function thinger(){
+ return [this.foo, arguments.length];
+ }
+
+ var st1 = dojo.hitch(scope, thinger);
+ t.assertEqual("bar", st1()[0]);
+ t.assertEqual(0, st1()[1]);
+
+ var st2 = dojo.hitch(scope2, thinger);
+ t.assertEqual("baz", st2()[0]);
+ t.assertEqual(0, st1()[1]);
+ t.assertEqual(1, st1("blah")[1]);
+
+ // st2 should be "scope proof"
+ t.assertEqual("baz", st2.call(scope)[0]);
+ },
+
+ function hitchWithArgs(t){
+ var scope = { foo: "bar" };
+ var scope2 = { foo: "baz" };
+ function thinger(){
+ return [this.foo, arguments.length];
+ }
+
+ var st1 = dojo.hitch(scope, thinger, "foo", "bar");
+ t.assertEqual("bar", st1()[0]);
+ t.assertEqual(2, st1()[1]);
+ var st2 = dojo.hitch(scope2, thinger, "foo", "bar");
+ t.assertEqual("baz", st2()[0]);
+ t.assertEqual(2, st2()[1]);
+ },
+
+ function hitchAsPartial(t){
+ var scope = { foo: "bar" };
+ var scope2 = { foo: "baz" };
+ function thinger(arg1, arg2){
+ return [this.foo, arg1, arg2];
+ }
+
+ var st1 = dojo.hitch(null, thinger);
+ t.assertEqual("bar", st1.call(scope)[0]);
+ t.assertEqual(undefined, st1()[0]);
+ var st2 = dojo.hitch(null, thinger, "foo", "bar");
+ t.assertEqual("bar", st2()[2]);
+ var st3 = dojo.hitch(null, thinger, "foo", "bar");
+ },
+
+ function _toArray(t){
+ var obj1 = [ 'foo', 'bar', 'spam', 'ham' ];
+
+ function thinger(){
+ return dojo._toArray(arguments);
+ }
+ var obj2 = thinger.apply(this, obj1);
+ t.assertEqual(obj1[0], obj2[0]);
+ },
+
+ function clone(t) {
+ var obj1 = {foo: 'bar', answer: 42, jan102007: new Date(2007, 0, 10),
+ baz: {
+ a: null,
+ b: [
+ 1, "b", 2.3, true, false
+ //, function(){ return 4; }, /\d+/gm
+ ]
+ }
+ };
+ var obj2 = dojo.clone(obj1);
+ t.assertEqual(obj1.foo, obj2.foo);
+ t.assertEqual(obj1.answer, obj2.answer);
+ t.assertEqual(obj1.jan102007, obj2.jan102007);
+ t.assertEqual(obj1.baz.a, obj2.baz.a);
+ for(var i = 0; i < obj1.baz.b.length; ++i){
+ t.assertEqual(obj1.baz.b[i], obj2.baz.b[i]);
+ }
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/_base/query.html b/includes/js/dojo/tests/_base/query.html
new file mode 100644
index 0000000..5c92221
--- /dev/null
+++ b/includes/js/dojo/tests/_base/query.html
@@ -0,0 +1,154 @@
+<html>
+ <head>
+ <title>testing dojo.query()</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript" src="../../dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, noFirebugLite: true"></script>
+ <script type="text/javascript" src="../../../util/doh/runner.js"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojox.data.dom");
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ // basic sanity checks
+ "doh.is(4, (dojo.query('h3')).length);",
+ "doh.is(1, (dojo.query('h1:first-child')).length);",
+ "doh.is(2, (dojo.query('h3:first-child')).length);",
+ "doh.is(1, (dojo.query('#t')).length);",
+ "doh.is(1, (dojo.query('#bug')).length);",
+ "doh.is(4, (dojo.query('#t h3')).length);",
+ "doh.is(1, (dojo.query('div#t')).length);",
+ "doh.is(4, (dojo.query('div#t h3')).length);",
+ "doh.is(0, (dojo.query('span#t')).length);",
+ "doh.is(1, (dojo.query('#t div > h3')).length);",
+ "doh.is(2, (dojo.query('.foo')).length);",
+ "doh.is(1, (dojo.query('.foo.bar')).length);",
+ "doh.is(2, (dojo.query('.baz')).length);",
+ "doh.is(3, (dojo.query('#t > h3')).length);",
+ // syntactic equivalents
+ "doh.is(12, (dojo.query('#t > *')).length);",
+ "doh.is(12, (dojo.query('#t >')).length);",
+ "doh.is(3, (dojo.query('.foo >')).length);",
+ "doh.is(3, (dojo.query('.foo > *')).length);",
+ // with a root, by ID
+ "doh.is(3, (dojo.query('> *', 'container')).length);",
+ "doh.is(3, (dojo.query('> h3', 't')).length);",
+ // compound queries
+ "doh.is(2, (dojo.query('.foo, .bar')).length);",
+ "doh.is(2, (dojo.query('.foo,.bar')).length);",
+ // multiple class attribute
+ "doh.is(1, (dojo.query('.foo.bar')).length);",
+ "doh.is(2, (dojo.query('.foo')).length);",
+ "doh.is(2, (dojo.query('.baz')).length);",
+ // case sensitivity
+ "doh.is(1, (dojo.query('span.baz')).length);",
+ "doh.is(1, (dojo.query('sPaN.baz')).length);",
+ "doh.is(1, (dojo.query('SPAN.baz')).length);",
+ "doh.is(1, (dojo.query('[class = \"foo bar\"]')).length);",
+ "doh.is(2, (dojo.query('[foo~=\"bar\"]')).length);",
+ "doh.is(2, (dojo.query('[ foo ~= \"bar\" ]')).length);",
+ // "t.is(0, (dojo.query('[ foo ~= \"\\'bar\\'\" ]')).length);",
+ "doh.is(3, (dojo.query('[foo]')).length);",
+ "doh.is(1, (dojo.query('[foo$=\"thud\"]')).length);",
+ "doh.is(1, (dojo.query('[foo$=thud]')).length);",
+ "doh.is(1, (dojo.query('[foo$=\"thudish\"]')).length);",
+ "doh.is(1, (dojo.query('#t [foo$=thud]')).length);",
+ "doh.is(1, (dojo.query('#t [ title $= thud ]')).length);",
+ "doh.is(0, (dojo.query('#t span[ title $= thud ]')).length);",
+ "doh.is(1, (dojo.query('[foo|=\"bar\"]')).length);",
+ "doh.is(1, (dojo.query('[foo|=\"bar-baz\"]')).length);",
+ "doh.is(0, (dojo.query('[foo|=\"baz\"]')).length);",
+ "doh.is(dojo.byId('_foo'), dojo.query('.foo:nth-child(2)')[0]);",
+ "doh.is(dojo.query('style')[0], dojo.query(':nth-child(2)')[0]);",
+ // descendant selectors
+ "doh.is(3, dojo.query('>', 'container').length);",
+ "doh.is(3, dojo.query('> *', 'container').length);",
+ "doh.is(2, dojo.query('> [qux]', 'container').length);",
+ "doh.is('child1', dojo.query('> [qux]', 'container')[0].id);",
+ "doh.is('child3', dojo.query('> [qux]', 'container')[1].id);",
+ "doh.is(3, dojo.query('>', 'container').length);",
+ "doh.is(3, dojo.query('> *', 'container').length);",
+ "doh.is('passed', dojo.query('#bug')[0].value);",
+ // sibling selectors
+ "doh.is(1, dojo.query('+', 'container').length);",
+ "doh.is(3, dojo.query('~', 'container').length);",
+ "doh.is(1, (dojo.query('.foo + span')).length);",
+ "doh.is(4, (dojo.query('.foo ~ span')).length);",
+ "doh.is(1, (dojo.query('#foo ~ *')).length);",
+ "doh.is(1, (dojo.query('#foo ~')).length);",
+ // sub-selector parsing
+ "doh.is(1, dojo.query('#t span.foo:not(span:first-child)').length);",
+ "doh.is(1, dojo.query('#t span.foo:not(:first-child)').length);",
+
+ // nth-child tests
+ "doh.is(2, dojo.query('#t > h3:nth-child(odd)').length);",
+ "doh.is(3, dojo.query('#t h3:nth-child(odd)').length);",
+ "doh.is(3, dojo.query('#t h3:nth-child(2n+1)').length);",
+ "doh.is(1, dojo.query('#t h3:nth-child(even)').length);",
+ "doh.is(1, dojo.query('#t h3:nth-child(2n)').length);",
+ "doh.is(0, dojo.query('#t h3:nth-child(2n+3)').length);",
+ "doh.is(2, dojo.query('#t h3:nth-child(1)').length);",
+ "doh.is(1, dojo.query('#t > h3:nth-child(1)').length);",
+ "doh.is(3, dojo.query('#t :nth-child(3)').length);",
+ "doh.is(0, dojo.query('#t > div:nth-child(1)').length);",
+ "doh.is(7, dojo.query('#t span').length);",
+ // :empty pseudo-selector
+ "doh.is(4, dojo.query('#t > span:empty').length);",
+ "doh.is(6, dojo.query('#t span:empty').length);",
+ "doh.is(0, dojo.query('h3 span:empty').length);",
+ "doh.is(1, dojo.query('h3 :not(:empty)').length);",
+ // escaping of ":" chars inside an ID
+ function silly_IDs1(){
+ doh.t(document.getElementById("silly:id::with:colons"));
+ doh.is(1, dojo.query("#silly\\:id\\:\\:with\\:colons").length);
+ },
+ function NodeList_identity(){
+ var foo = new dojo.NodeList([dojo.byId("container")]);
+ doh.is(foo, dojo.query(foo));
+ },
+ function xml(){
+ try{
+ var doc = dojox.data.dom.createDocument("<ResultSet><Result>One</Result><Result>Two</Result></ResultSet>");
+ console.debug(doc);
+ console.debug(dojox.data.dom.innerXML(doc.documentElement));
+ console.debug(dojo.query("Result", doc.documentElement).length);
+ }catch(e){ console.debug(e); }
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ </head>
+ <body>
+ <h1>testing dojo.query()</h1>
+ <div id="t">
+ <h3>h3 <span>span</span> endh3 </h3>
+ <!-- comment to throw things off -->
+ <div class="foo bar" id="_foo">
+ <h3>h3</h3>
+ <span id="foo"></span>
+ <span></span>
+ </div>
+ <h3>h3</h3>
+ <h3 class="baz" title="thud">h3</h3>
+ <span class="foobar baz foo"></span>
+ <span foo="bar"></span>
+ <span foo="baz bar thud"></span>
+ <!-- FIXME: should foo="bar-baz-thud" match? [foo$=thud] ??? -->
+ <span foo="bar-baz-thudish" id="silly:id::with:colons"></span>
+ <div id="container">
+ <div id="child1" qux="true"></div>
+ <div id="child2"></div>
+ <div id="child3" qux="true"></div>
+ </div>
+ <div qux="true"></div>
+ <input id="notbug" name="bug" type="hidden" value="failed" />
+ <input id="bug" type="hidden" value="passed" />
+ </div>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/query.js b/includes/js/dojo/tests/_base/query.js
new file mode 100644
index 0000000..20d2fc4
--- /dev/null
+++ b/includes/js/dojo/tests/_base/query.js
@@ -0,0 +1,9 @@
+if(!dojo._hasResource["tests._base.query"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.query"] = true;
+dojo.provide("tests._base.query");
+if(dojo.isBrowser){
+ doh.registerUrl("tests._base.query", dojo.moduleUrl("tests", "_base/query.html"));
+ doh.registerUrl("tests._base.NodeList", dojo.moduleUrl("tests", "_base/NodeList.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/_base/timeout.php b/includes/js/dojo/tests/_base/timeout.php
new file mode 100644
index 0000000..560b0d3
--- /dev/null
+++ b/includes/js/dojo/tests/_base/timeout.php
@@ -0,0 +1,7 @@
+<?php
+
+$callbackName = $_REQUEST["callback"];
+sleep(5);
+print "SuperXFooBarVariable = 'Oh no! SuperXFooBarVariable is defined (should not be for timeout case).'; {$callbackName}({Status: 'good'});";
+
+?>
diff --git a/includes/js/dojo/tests/_base/xhr.html b/includes/js/dojo/tests/_base/xhr.html
new file mode 100644
index 0000000..ddc1bb4
--- /dev/null
+++ b/includes/js/dojo/tests/_base/xhr.html
@@ -0,0 +1,404 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>testing form and xhr utils</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.addOnLoad(function(){
+ var f1fo = { 'blah': "blah" };
+ var f1foStr = "blah=blah";
+ var f1foJson = '{"blah":"blah"}';
+
+ var f2fo = {
+ blah: "blah",
+ multi: [
+ "thud",
+ "thonk"
+ ],
+ textarea: "textarea_value"
+ };
+ var f2foStr = "blah=blah&multi=thud&multi=thonk&textarea=textarea_value";
+ var f2foJson = '{"blah":"blah","multi":["thud","thonk"],"textarea":"textarea_value"}';
+
+ var f3fo = {
+ spaces: "string with spaces"
+ };
+ var f3foStr = "spaces=string%20with%20spaces&";
+ var f3foJson = '{"spaces":"string with spaces"}';
+
+ var f5fo = { 'blåh': "bláh" };
+ var f5foStr = "bl%C3%A5h=bl%C3%A1h";
+ var f5foJson = '{"blåh":"bláh"}';
+
+
+ doh.register("t",
+ [
+ function formNodeToObject(t){
+ t.is(f1fo , dojo.formToObject(dojo.byId("f1")));
+ t.is(f5fo , dojo.formToObject(dojo.byId("f5")));
+ },
+ function formIdToObject(t){
+ t.is(f1fo , dojo.formToObject("f1"));
+ t.is(f5fo , dojo.formToObject("f5"));
+ },
+ function formToObjectWithMultiSelect(t){
+ t.is(f2fo , dojo.formToObject("f2"));
+ },
+ function objectToQuery(t){
+ t.is(f1foStr , dojo.objectToQuery(f1fo));
+ t.is(f5foStr , dojo.objectToQuery(f5fo));
+ },
+ function objectToQueryArr(t){
+ t.is(f2foStr, dojo.objectToQuery(f2fo));
+ },
+ function formToQuery(t){
+ t.is(f1foStr, dojo.formToQuery("f1"));
+ t.is(f5foStr, dojo.formToQuery("f5"));
+ },
+ function formToQueryArr(t){
+ t.is(f2foStr, dojo.formToQuery("f2"));
+ },
+ function formToJson(t){
+ t.is(f1foJson, dojo.formToJson("f1"));
+ t.is(f5foJson, dojo.formToJson("f5"));
+ },
+ function formToJsonArr(t){
+ t.is(f2foJson, dojo.formToJson("f2"));
+ },
+ function queryToObject(t){
+ t.is(f1fo , dojo.queryToObject(f1foStr));
+ t.is(f2fo , dojo.queryToObject(f2foStr));
+ t.is(f3fo , dojo.queryToObject(f3foStr));
+ t.is(f5fo , dojo.queryToObject(f5foStr));
+ },
+ function textContentHandler(t){
+ t.is("foo bar baz ",
+ dojo._contentHandlers.text({
+ responseText: "foo bar baz "
+ })
+ );
+ },
+ function jsonContentHandler(t){
+ var jsonObj = {
+ foo: "bar",
+ baz: [
+ { thonk: "blarg" },
+ "xyzzy!"
+ ]
+ };
+ t.is(jsonObj,
+ dojo._contentHandlers.json({
+ responseText: dojo.toJson(jsonObj)
+ })
+ );
+ },
+ function jsonCFContentHandler(t){
+ var jsonObj = {
+ foo: "bar",
+ baz: [
+ { thonk: "blarg" },
+ "xyzzy!"
+ ]
+ };
+ var e;
+ try{
+ dojo._contentHandlers["json-comment-filtered"]({
+ responseText: dojo.toJson(jsonObj)
+ })
+ }catch(ex){
+ e = ex;
+ }finally{
+ // did we fail closed?
+ t.is((typeof e), "object");
+ }
+ t.is(jsonObj,
+ dojo._contentHandlers["json-comment-filtered"]({
+ responseText: "\tblag\n/*"+dojo.toJson(jsonObj)+"*/\n\r\t\r"
+ })
+ );
+ },
+ function jsContentHandler(t){
+ var jsonObj = {
+ foo: "bar",
+ baz: [
+ { thonk: "blarg" },
+ "xyzzy!"
+ ]
+ };
+ t.is(jsonObj,
+ dojo._contentHandlers["javascript"]({
+ responseText: "("+dojo.toJson(jsonObj)+")"
+ })
+ );
+ t.t(dojo._contentHandlers["javascript"]({
+ responseText: "true;"
+ })
+ );
+ t.f(dojo._contentHandlers["javascript"]({
+ responseText: "false;"
+ })
+ );
+ },
+ function xmlContentHandler(t){
+ var fauxObj = {
+ foo: "bar",
+ baz: [
+ { thonk: "blarg" },
+ "xyzzy!"
+ ]
+ };
+ t.is(fauxObj,
+ dojo._contentHandlers["xml"]({ responseXML: fauxObj })
+ );
+ },
+ function xhrGet(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrGet({
+ url: "xhr.html", // self
+ preventCache: true,
+ load: function(text, ioArgs){
+ t.is(4, ioArgs.xhr.readyState);
+ return text; //must return a value here or the parent test deferred fails.
+ }
+ });
+ t.t(td instanceof dojo.Deferred);
+ td.addCallback(d, "callback");
+ return d;
+ },
+ function xhrGet404(t){
+ var d = new doh.Deferred();
+ try{
+ var td = dojo.xhrGet({
+ url: "xhr_blarg.html", // doesn't exist
+ error: function(err, ioArgs){
+ t.is(404, ioArgs.xhr.status);
+ return err; //must return a value here or the parent test deferred fails.
+ }
+ });
+ // td.addErrback(d, "callback");
+ }catch(e){
+ d.callback(true);
+ }
+ // return d;
+ },
+ function xhrGetContent(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrGet({
+ url: "xhr.html?color=blue",
+ content: {
+ foo: [ "bar", "baz" ],
+ thud: "thonk",
+ xyzzy: 3
+ }
+ });
+ td.addCallback(function(text){
+ // console.debug(td, td.xhr, td.args);
+ t.is("xhr.html?color=blue&foo=bar&foo=baz&thud=thonk&xyzzy=3",
+ td.ioArgs.url);
+ d.callback(true);
+ });
+ return d;
+ },
+ function xhrGetForm(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrGet({
+ url: "xhr.html", // self
+ form: "f3"
+ });
+ td.addCallback(function(xhr){
+ // console.debug(td.args.url);
+ t.is("xhr.html?spaces=string%20with%20spaces", td.ioArgs.url);
+ d.callback(true);
+ });
+ return d;
+ },
+ function xhrGetFormWithContent(t){
+ // ensure that stuff passed via content over-rides
+ // what's specified in the form
+ var d = new doh.Deferred();
+ var td = dojo.xhrGet({
+ url: "xhr.html", // self
+ form: "f3",
+ content: { spaces: "blah" }
+ });
+ td.addCallback(function(xhr){
+ // console.debug(td.args.url);
+ t.is("xhr.html?spaces=blah", td.ioArgs.url);
+ d.callback(true);
+ });
+ return d;
+ },
+ function xhrPost(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrPost({
+ url: "xhr.html?foo=bar", // self
+ content: { color: "blue"},
+ handle: function(res, ioArgs){
+ if((dojo._isDocumentOk(ioArgs.xhr))||
+ (ioArgs.xhr.status == 405)
+ ){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ // t.t(td instanceof dojo.Deferred);
+ return d;
+ },
+ function xhrPostWithContent(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrPost({
+ url: "xhr.html",
+ content: {
+ foo: [ "bar", "baz" ],
+ thud: "thonk",
+ xyzzy: 3
+ }
+ });
+ td.addBoth(function(text){
+ t.is("foo=bar&foo=baz&thud=thonk&xyzzy=3",
+ td.ioArgs.query);
+ if( (dojo._isDocumentOk(td.ioArgs.xhr))||
+ (td.ioArgs.xhr.status == 405)
+ ){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ });
+ return d;
+ },
+ function xhrPostForm(t){
+ var d = new doh.Deferred();
+ var form = dojo.byId("f4");
+
+ //Make sure we can send a form to its
+ //action URL. See trac: #2844.
+ var td = dojo.xhrPost({
+ form: form
+ });
+ td.addCallback(function(){
+ d.callback(true);
+ });
+ td.addErrback(function(error){
+ d.callback(error);
+ });
+ // t.t(td instanceof dojo.Deferred);
+ return d;
+ },
+ function rawXhrPost(t){
+ var d = new doh.Deferred();
+ var td = dojo.rawXhrPost({
+ url: "xhr.html", // self
+ postContent: "foo=bar&color=blue&height=average",
+ handle: function(res, ioArgs){
+ if((dojo._isDocumentOk(ioArgs.xhr))||
+ (ioArgs.xhr.status == 405)
+ ){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ // t.t(td instanceof dojo.Deferred);
+ return d;
+ },
+ function xhrPut(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrPut({
+ url: "xhrDummyMethod.php?foo=bar", // self
+ content: { color: "blue"},
+ handle: function(res, ioArgs){
+ if((dojo._isDocumentOk(ioArgs.xhr))||
+ (ioArgs.xhr.status == 403)
+ ){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ // t.t(td instanceof dojo.Deferred);
+ return d;
+ },
+ function xhrDelete(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrDelete({
+ url: "xhrDummyMethod.php", // self
+ preventCache: true,
+ handle: function(res, ioArgs){
+ if((dojo._isDocumentOk(ioArgs.xhr))||
+ (ioArgs.xhr.status == 403)
+ ){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ // t.t(td instanceof dojo.Deferred);
+ return d;
+ },
+ function xhrCancel(t){
+ var d = new doh.Deferred();
+ var td = dojo.xhrPost({
+ url: "xhrDummyMethod.php", // self
+ handle: function(res, ioArgs){
+ if(res instanceof Error && res.dojoType == "cancel"){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ td.cancel();
+ // t.t(td instanceof dojo.Deferred);
+ return d;
+ }
+ // FIXME: need to add tests for wrapForm
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ </head>
+ <body>
+ <form id="f1" style="border: 1px solid black;">
+ <input type="text" name="blah" value="blah">
+ <input type="text" name="no_value" value="blah" disabled>
+ <input type="button" name="no_value2" value="blah">
+ </form>
+ <form id="f2" style="border: 1px solid black;">
+ <input type="text" name="blah" value="blah">
+ <input type="text" name="no_value" value="blah" disabled>
+ <input type="button" name="no_value2" value="blah">
+ <select type="select" multiple name="multi" size="5">
+ <option value="blah">blah</option>
+ <option value="thud" selected>thud</option>
+ <option value="thonk" selected>thonk</option>
+ </select>
+ <textarea name="textarea">textarea_value</textarea>
+ </form>
+ <form id="f3" style="border: 1px solid black;">
+ <input type="hidden" name="spaces" value="string with spaces">
+ </form>
+ <form id="f4" style="border: 1px solid black;" action="xhrDummyMethod.php">
+ <input type="hidden" name="action" value="Form with input named action">
+ </form>
+ <form id="f5" style="border: 1px solid black;">
+ <input type="text" name="blåh" value="bláh">
+ <input type="text" name="no_value" value="blah" disabled>
+ <input type="button" name="no_value2" value="blah">
+ </form>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/_base/xhr.js b/includes/js/dojo/tests/_base/xhr.js
new file mode 100644
index 0000000..885bbfe
--- /dev/null
+++ b/includes/js/dojo/tests/_base/xhr.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests._base.xhr"] = true;
+dojo.provide("tests._base.xhr");
+if(dojo.isBrowser){
+ doh.registerUrl("tests._base.xhr", dojo.moduleUrl("tests", "_base/xhr.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/_base/xhrDummyMethod.php b/includes/js/dojo/tests/_base/xhrDummyMethod.php
new file mode 100644
index 0000000..c9206fe
--- /dev/null
+++ b/includes/js/dojo/tests/_base/xhrDummyMethod.php
@@ -0,0 +1,7 @@
+<?php
+//Just a dummy end point to use in HTTP method calls like PUT and DELETE.
+//This avoids getting a 405 method not allowed calls for the tests that reference
+//this file.
+
+header("HTTP/1.1 200 OK");
+?>
diff --git a/includes/js/dojo/tests/back-hash.js b/includes/js/dojo/tests/back-hash.js
new file mode 100644
index 0000000..3fef2c5
--- /dev/null
+++ b/includes/js/dojo/tests/back-hash.js
@@ -0,0 +1,33 @@
+if(!dojo._hasResource["tests.back-hash"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.back-hash"] = true;
+dojo.provide("tests.back-hash");
+
+dojo.require("dojo.back");
+
+(function(){
+ tests.register("tests.back.hash", [
+ function getAndSet(t) {
+ var cases = [
+ "test",
+ "test with spaces",
+ "test%20with%20encoded",
+ "test+with+pluses",
+ " leading",
+ "trailing ",
+ "under_score",
+ "extra#mark",
+ "extra?instring",
+ "extra&instring",
+ "#leadinghash"
+ ];
+ var b = dojo.back;
+ function verify(s){
+ dojo.back.setHash(s);
+ t.is(s, dojo.back.getHash(s));
+ }
+ dojo.forEach(cases, verify);
+ }
+ ]);
+})();
+
+}
diff --git a/includes/js/dojo/tests/back.html b/includes/js/dojo/tests/back.html
new file mode 100644
index 0000000..1b9ca1c
--- /dev/null
+++ b/includes/js/dojo/tests/back.html
@@ -0,0 +1,107 @@
+<html>
+<head>
+ <script language="JavaScript" type="text/javascript">
+ // Dojo configuration
+ djConfig = {
+ //debugAtAllCosts: true, //Don't normally need this in applications.
+ isDebug: true,
+ dojoIframeHistoryUrl: "../../resources/iframe_history.html" //for xdomain
+ };
+ </script>
+ <script type="text/javascript"
+ src="../dojo.js"
+ djConfig="isDebug:true, dojoIframeHistoryUrl: '../resources/iframe_history.html'"></script>
+ <script type="text/javascript" src="../back.js"></script>
+ <script type="text/javascript">
+ ApplicationState = function(stateData, outputDivId, backForwardOutputDivId, bookmarkValue){
+ this.stateData = stateData;
+ this.outputDivId = outputDivId;
+ this.backForwardOutputDivId = backForwardOutputDivId;
+ this.changeUrl = bookmarkValue || false;
+ }
+
+ dojo.extend(ApplicationState, {
+ back: function(){
+ this.showBackForwardMessage("BACK for State Data: " + this.stateData);
+ this.showStateData();
+ },
+ forward: function(){
+ this.showBackForwardMessage("FORWARD for State Data: " + this.stateData);
+ this.showStateData();
+ },
+ showStateData: function(){
+ dojo.byId(this.outputDivId).innerHTML += this.stateData + '<br />';
+ },
+ showBackForwardMessage: function(message){
+ dojo.byId(this.backForwardOutputDivId).innerHTML += message + '<br />';
+ }
+ });
+
+ var data = {
+ link0: "This is the initial state (page first loaded)",
+ "link with spaces": "This is data for a state with spaces",
+ "link%20with%20encoded": "This is data for a state with encoded bits",
+ "link+with+pluses": "This is data for a state with pluses",
+ link1: "This is data for link 1",
+ link2: "This is data for link 2",
+ link3: "This is data for link 3",
+ link4: "This is data for link 4",
+ link5: "This is data for link 5",
+ link6: "This is data for link 6",
+ link7: "This is data for link 7"
+ };
+
+ function goNav(id){
+ var appState = new ApplicationState(data[id], "output", "dataOutput", id);
+ appState.showStateData();
+ dojo.back.addToHistory(appState);
+ }
+
+ dojo.addOnLoad(function(){
+ var appState = new ApplicationState(data["link0"], "output", "dataOutput");
+ appState.showStateData();
+ dojo.back.setInitialState(appState);
+ });
+ </script>
+</head>
+<body>
+ <script type="text/javascript">dojo.back.init();</script>
+ <div style="padding-bottom: 20px; width: 100%; border-bottom: 1px solid gray">
+ <h3>dojo.back test</h3>
+
+
+ <p>This page tests the dojo.back back/forward code.</p>
+
+ <p>The buttons that start with "Link" on them don't use any dojo.xhr* calls,
+ just JS data already in the page.</p>
+
+ <ul>
+ <li>Don't test this page using local disk for MSIE. MSIE will not
+ create a history list for iframe_history.html if served from a file:
+ URL. Serve the test pages from a web server to test in that browser.</li>
+ <li>Safari 2.0.3+ (and probably 1.3.2+): Only the back button works OK
+ (not the forward button).</li>
+ <li>Opera 8.5.3: Does not work.</li>
+ <li>Konqueror: Unknown. The latest may have Safari's behavior.</li>
+ </ul>
+ </div>
+ <div style="float:left; padding: 20px">
+ <button onclick="goNav('link1')">Link 1</button><br />
+ <button onclick="goNav('link with spaces')">Link with Spaces</button><br />
+ <button onclick="goNav('link%20with%20encoded')">Link with Encoded</button><br />
+ <button onclick="goNav('link+with+pluses')">Link with Pluses</button><br />
+ <button onclick="goNav('link3')">Link 3</button><br />
+ <button onclick="goNav('link4')">Link 4</button><br />
+ <button onclick="goNav('link5')">Link 5</button><br />
+ <button onclick="goNav('link6')">Link 6</button><br />
+ <button onclick="goNav('link7')">Link 7</button><br />
+ </div>
+ <div style="float: left; padding: 20px">
+ <b>Data Output:</b><br />
+ <div id="output"></div>
+ <hr />
+ <i>Back/Forward Info:</i><br />
+ <div id="dataOutput"></div>
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/back.js b/includes/js/dojo/tests/back.js
new file mode 100644
index 0000000..0565716
--- /dev/null
+++ b/includes/js/dojo/tests/back.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests.back"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.back"] = true;
+dojo.provide("tests.back");
+if(dojo.isBrowser){
+ doh.registerUrl("tests.back", dojo.moduleUrl("tests", "back.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/behavior.html b/includes/js/dojo/tests/behavior.html
new file mode 100644
index 0000000..280fc29
--- /dev/null
+++ b/includes/js/dojo/tests/behavior.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing dojo.behavior</title>
+ <style type="text/css">
+ @import "../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../dojo.js" djConfig="isDebug: true, popup: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.behavior");
+
+ var applyCount = 0;
+
+ var behaviorObj = {
+ ".bar": function(elem){
+ dojo.style(elem, "opacity", 0.5);
+ applyCount++;
+ },
+ ".foo > span": function(elem){
+ elem.style.fontStyle = "italic";
+ applyCount++;
+ }
+ }
+
+ topicCount = 0;
+ dojo.subscribe("/foo", function(){ topicCount++; });
+
+ // no behaviors should be executed when onload fires
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function add(t){
+ t.f(dojo.behavior._behaviors[".bar"]);
+ t.f(dojo.behavior._behaviors[".foo > span"]);
+ dojo.behavior.add(behaviorObj);
+ // make sure they got plopped in
+ t.t(dojo.behavior._behaviors[".bar"]);
+ t.is(1, dojo.behavior._behaviors[".bar"].length);
+ t.t(dojo.behavior._behaviors[".foo > span"]);
+ t.is(1, dojo.behavior._behaviors[".foo > span"].length);
+ },
+ function apply(t){
+ t.is(0, applyCount);
+ dojo.behavior.apply();
+ t.is(2, applyCount);
+
+ // reapply and make sure we only match once
+ dojo.behavior.apply();
+ t.is(2, applyCount);
+ },
+ function reapply(t){
+ t.is(2, applyCount);
+ // add the rules again
+ dojo.behavior.add(behaviorObj);
+ dojo.behavior.apply();
+ t.is(4, applyCount);
+ // dojo.behavior.apply();
+ // t.is(4, applyCount);
+ // dojo.query(".bar").styles("opacity", 1.0);
+ },
+ function topics(t){
+ var d = new doh.Deferred();
+ t.is(0, topicCount);
+ dojo.behavior.add({ ".foo": "/foo" });
+ dojo.behavior.apply();
+ t.is(2, topicCount);
+
+ dojo.behavior.add({ ".foo": {
+ "onfocus": "/foo"
+ }
+ });
+ dojo.behavior.apply();
+ t.is(2, topicCount);
+ dojo.byId("blah").focus();
+ dojo.byId("blah").blur();
+ dojo.byId("blah").focus();
+ setTimeout(function(){
+ // blur/focus event generation isn't synchronous on IE
+ try{
+ t.is(4, topicCount);
+ d.callback(true);
+ }catch(e){
+ d.errback(e);
+ }
+ }, 10);
+ return d;
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ </head>
+ <body>
+ <div class="foo" id="fooOne">
+ <span>.foo &gt; span</span>
+ <div class="bar">
+ <span>.foo &gt; .bar &gt; span</span>
+ </div>
+ </div>
+ <input type="text" id="blah" class="foo blah" name="thinger" value="thinger" tabIndex="0">
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/behavior.js b/includes/js/dojo/tests/behavior.js
new file mode 100644
index 0000000..e09de9d
--- /dev/null
+++ b/includes/js/dojo/tests/behavior.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests.behavior"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.behavior"] = true;
+dojo.provide("tests.behavior");
+if(dojo.isBrowser){
+ doh.registerUrl("tests.behavior", dojo.moduleUrl("tests", "behavior.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/cldr.js b/includes/js/dojo/tests/cldr.js
new file mode 100644
index 0000000..e9edfad
--- /dev/null
+++ b/includes/js/dojo/tests/cldr.js
@@ -0,0 +1,19 @@
+if(!dojo._hasResource["tests.cldr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.cldr"] = true;
+dojo.provide("tests.cldr");
+
+dojo.require("dojo.cldr.supplemental");
+dojo.require("dojo.cldr.monetary");
+
+tests.register("tests.cldr",
+ [
+ function test_date_getWeekend(t){
+ t.is(6, dojo.cldr.supplemental.getWeekend('en-us').start);
+ t.is(0, dojo.cldr.supplemental.getWeekend('en-us').end);
+ t.is(5, dojo.cldr.supplemental.getWeekend('he-il').start);
+ t.is(6, dojo.cldr.supplemental.getWeekend('he-il').end);
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/colors.js b/includes/js/dojo/tests/colors.js
new file mode 100644
index 0000000..7f3808e
--- /dev/null
+++ b/includes/js/dojo/tests/colors.js
@@ -0,0 +1,48 @@
+if(!dojo._hasResource["tests.colors"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.colors"] = true;
+dojo.provide("tests.colors");
+dojo.require("dojo.colors");
+
+(function(){
+ var verifyColor = function(t, source, expected){
+ var source = new dojo.Color(source);
+ var expected = new dojo.Color(expected);
+ t.is(expected.toRgba(), source.toRgba());
+ dojo.forEach(source.toRgba(), function(n){ t.is("number", typeof(n)); });
+ }
+
+ doh.register("tests.colors",
+ [
+ // all tests below are taken from #4.2 of the CSS3 Color Module
+ function testColorEx01(t){ verifyColor(t, "black", [0, 0, 0]); },
+ function testColorEx02(t){ verifyColor(t, "white", [255, 255, 255]); },
+ function testColorEx03(t){ verifyColor(t, "maroon", [128, 0, 0]); },
+ function testColorEx04(t){ verifyColor(t, "olive", [128, 128, 0]); },
+ function testColorEx05(t){ verifyColor(t, "#f00", "red"); },
+ function testColorEx06(t){ verifyColor(t, "#ff0000", "red"); },
+ function testColorEx07(t){ verifyColor(t, "rgb(255, 0, 0)", "red"); },
+ function testColorEx08(t){ verifyColor(t, "rgb(100%, 0%, 0%)", "red"); },
+ function testColorEx09(t){ verifyColor(t, "rgb(300, 0, 0)", "red"); },
+ function testColorEx10(t){ verifyColor(t, "rgb(255, -10, 0)", "red"); },
+ function testColorEx11(t){ verifyColor(t, "rgb(110%, 0%, 0%)", "red"); },
+ function testColorEx12(t){ verifyColor(t, "rgba(255, 0, 0, 1)", "red"); },
+ function testColorEx13(t){ verifyColor(t, "rgba(100%, 0%, 0%, 1)", "red"); },
+ function testColorEx14(t){ verifyColor(t, "rgba(0, 0, 255, 0.5)", [0, 0, 255, 0.5]); },
+ function testColorEx15(t){ verifyColor(t, "rgba(100%, 50%, 0%, 0.1)", [255, 128, 0, 0.1]); },
+ function testColorEx16(t){ verifyColor(t, "hsl(0, 100%, 50%)", "red"); },
+ function testColorEx17(t){ verifyColor(t, "hsl(120, 100%, 50%)", "lime"); },
+ function testColorEx18(t){ verifyColor(t, "hsl(120, 100%, 25%)", "green"); },
+ function testColorEx19(t){ verifyColor(t, "hsl(120, 100%, 75%)", "#80ff80"); },
+ function testColorEx20(t){ verifyColor(t, "hsl(120, 50%, 50%)", "#40c040"); },
+ function testColorEx21(t){ verifyColor(t, "hsla(120, 100%, 50%, 1)", "lime"); },
+ function testColorEx22(t){ verifyColor(t, "hsla(240, 100%, 50%, 0.5)", [0, 0, 255, 0.5]); },
+ function testColorEx23(t){ verifyColor(t, "hsla(30, 100%, 50%, 0.1)", [255, 128, 0, 0.1]); },
+ function testColorEx24(t){ verifyColor(t, "transparent", [0, 0, 0, 0]); },
+ // all tests below test greyscale colors
+ function testColorEx25(t){ verifyColor(t, dojo.colors.makeGrey(5), [5, 5, 5, 1]); },
+ function testColorEx26(t){ verifyColor(t, dojo.colors.makeGrey(2, 0.3), [2, 2, 2, 0.3]); }
+ ]
+ );
+})();
+
+}
diff --git a/includes/js/dojo/tests/cookie.html b/includes/js/dojo/tests/cookie.html
new file mode 100644
index 0000000..a89b0f8
--- /dev/null
+++ b/includes/js/dojo/tests/cookie.html
@@ -0,0 +1,84 @@
+<html>
+ <head>
+ <title>testing Cookies</title>
+ <style type="text/css">
+ @import "../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../dojo.js"
+ djConfig="isDebug:true"></script>
+ <script type="text/javascript" src="../cookie.js"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ {
+ name: "basicSet",
+ runTest: function(t){
+ // make sure the cookie is dead
+ var old = new Date(1976, 8, 15);
+ document.cookie = "dojo_test=blah; expires=" + old.toUTCString();
+ t.is(-1, document.cookie.indexOf("dojo_test="));
+
+ // set the new one
+ var n = "dojo_test";
+ var v = "test value";
+ dojo.cookie(n, v);
+ t.t(document.cookie.indexOf(n+"=") >= 0);
+ var start = document.cookie.indexOf(n+"=") + n.length + 1;
+ var end = document.cookie.indexOf(";", start);
+ if(end == -1){ end = document.cookie.length; }
+ t.is(v, decodeURIComponent(document.cookie.substring(start, end)));
+ }
+ },
+ {
+ name: "basicGet",
+ runTest: function(t){
+ // set the cookie
+ var n = "dojo_test";
+ var v = "foofoo";
+ document.cookie = n + "=" + v;
+
+ t.is(v, dojo.cookie(n));
+ }
+ },
+ {
+ name: "daysAsNumber",
+ runTest: function(t){
+ // set a cookie with a numerical expires
+ dojo.cookie("dojo_num", "foo", { expires: 10 });
+ t.is("foo", dojo.cookie("dojo_num"));
+
+ // remove the cookie by setting it with a negative
+ // numerical expires. value doesn't really matter here
+ dojo.cookie("dojo_num", "-deleted-", { expires: -10 });
+ t.is(null, dojo.cookie("dojo_num"));
+ }
+ },
+ {
+ name: "nameSuffix",
+ runTest: function(t){
+ // set two cookies with the same suffix
+ dojo.cookie("user", "123", { expires: 10 });
+ dojo.cookie("xuser", "abc", { expires: 10 });
+ t.is("123", dojo.cookie("user"));
+ t.is("abc", dojo.cookie("xuser"));
+
+ // remove the cookie by setting it with a negative
+ // numerical expires. value doesn't really matter here
+ dojo.cookie("user", "-deleted-", { expires: -10 });
+ t.is(null, dojo.cookie("user"));
+ dojo.cookie("xuser", "-deleted-", { expires: -10 });
+ t.is(null, dojo.cookie("xuser"));
+ }
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/cookie.js b/includes/js/dojo/tests/cookie.js
new file mode 100644
index 0000000..46cd519
--- /dev/null
+++ b/includes/js/dojo/tests/cookie.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests.cookie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.cookie"] = true;
+dojo.provide("tests.cookie");
+if(dojo.isBrowser){
+ doh.registerUrl("tests.cookie", dojo.moduleUrl("tests", "cookie.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/currency.js b/includes/js/dojo/tests/currency.js
new file mode 100644
index 0000000..8375725
--- /dev/null
+++ b/includes/js/dojo/tests/currency.js
@@ -0,0 +1,48 @@
+if(!dojo._hasResource["tests.currency"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.currency"] = true;
+dojo.provide("tests.currency");
+
+dojo.require("dojo.currency");
+
+tests.register("tests.currency",
+ [
+ {
+ // Test formatting and parsing of currencies in various locales pre-built in dojo.cldr
+ // NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+ // load resources here for specific locales:
+
+ name: "currency",
+ setUp: function(){
+ var partLocaleList = ["en-us", "en-ca", "de-de"];
+ for(var i = 0 ; i < partLocaleList.length; i ++){
+ dojo.requireLocalization("dojo.cldr","currency",partLocaleList[i], "zh,en-ca,pt,en-us,de,ja,en,en-au,ROOT,fr,es,ko,zh-tw,it");
+ dojo.requireLocalization("dojo.cldr","number",partLocaleList[i], "zh-cn,zh,ko-kr,pt,en-us,en-gb,de,ja,ja-jp,en,ROOT,en-au,fr,es,ko,zh-tw,it,es-es,de-de");
+ }
+ },
+ runTest: function(t){
+ t.is("\u20ac123.45", dojo.currency.format(123.45, {currency: "EUR", locale: "en-us"}));
+ t.is("$123.45", dojo.currency.format(123.45, {currency: "USD", locale: "en-us"}));
+ t.is("$1,234.56", dojo.currency.format(1234.56, {currency: "USD", locale: "en-us"}));
+ t.is("US$123.45", dojo.currency.format(123.45, {currency: "USD", locale: "en-ca"}));
+ t.is("$123.45", dojo.currency.format(123.45, {currency: "CAD", locale: "en-ca"}));
+ t.is("Can$123.45", dojo.currency.format(123.45, {currency: "CAD", locale: "en-us"}));
+ t.is("123,45 \u20ac", dojo.currency.format(123.45, {currency: "EUR", locale: "de-de"}));
+ t.is("1.234,56 \u20ac", dojo.currency.format(1234.56, {currency: "EUR", locale: "de-de"}));
+ // There is no special currency symbol for ADP, so expect the ISO code instead
+ t.is("ADP123", dojo.currency.format(123, {currency: "ADP", locale: "en-us"}));
+
+ t.is(123.45, dojo.currency.parse("$123.45", {currency: "USD", locale: "en-us"}));
+ t.is(1234.56, dojo.currency.parse("$1,234.56", {currency: "USD", locale: "en-us"}));
+ t.is(123.45, dojo.currency.parse("123,45 \u20ac", {currency: "EUR", locale: "de-de"}));
+ t.is(1234.56, dojo.currency.parse("1.234,56 \u20ac", {currency: "EUR", locale: "de-de"}));
+ t.is(1234.56, dojo.currency.parse("1.234,56\u20ac", {currency: "EUR", locale: "de-de"}));
+
+ t.is(1234, dojo.currency.parse("$1,234", {currency: "USD", locale: "en-us"}));
+ t.is(1234, dojo.currency.parse("$1,234", {currency: "USD", fractional: false, locale: "en-us"}));
+ t.t(isNaN(dojo.currency.parse("$1,234", {currency: "USD", fractional: true, locale: "en-us"})));
+ }
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/data.js b/includes/js/dojo/tests/data.js
new file mode 100644
index 0000000..6556236
--- /dev/null
+++ b/includes/js/dojo/tests/data.js
@@ -0,0 +1,12 @@
+if(!dojo._hasResource["tests.data"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.data"] = true;
+dojo.provide("tests.data");
+//Squelch any json comment messages for now, since the UT allows for both.
+dojo.config.usePlainJson = true;
+dojo.require("tests.data.utils");
+dojo.require("tests.data.ItemFileReadStore");
+dojo.require("tests.data.ItemFileWriteStore");
+
+
+
+}
diff --git a/includes/js/dojo/tests/data/ItemFileReadStore.js b/includes/js/dojo/tests/data/ItemFileReadStore.js
new file mode 100644
index 0000000..19d37da
--- /dev/null
+++ b/includes/js/dojo/tests/data/ItemFileReadStore.js
@@ -0,0 +1,10 @@
+if(!dojo._hasResource["tests.data.ItemFileReadStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.data.ItemFileReadStore"] = true;
+dojo.provide("tests.data.ItemFileReadStore");
+dojo.require("tests.data.readOnlyItemFileTestTemplates");
+dojo.require("dojo.data.ItemFileReadStore");
+
+tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore("dojo.data.ItemFileReadStore");
+
+
+}
diff --git a/includes/js/dojo/tests/data/ItemFileWriteStore.js b/includes/js/dojo/tests/data/ItemFileWriteStore.js
new file mode 100644
index 0000000..9dd938e
--- /dev/null
+++ b/includes/js/dojo/tests/data/ItemFileWriteStore.js
@@ -0,0 +1,1402 @@
+if(!dojo._hasResource["tests.data.ItemFileWriteStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.data.ItemFileWriteStore"] = true;
+dojo.provide("tests.data.ItemFileWriteStore");
+dojo.require("tests.data.readOnlyItemFileTestTemplates");
+
+dojo.require("dojo.data.ItemFileWriteStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+dojo.require("dojo.data.api.Write");
+dojo.require("dojo.data.api.Notification");
+
+
+// First, make sure ItemFileWriteStore can still pass all the same unit tests
+// that we use for its superclass, ItemFileReadStore:
+tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore("dojo.data.ItemFileWriteStore");
+
+tests.data.ItemFileWriteStore.getTestData = function(name){
+ var data = {};
+ if(name === "reference_integrity"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/reference_integrity.json").toString() };
+ }else{
+ data =
+ { data: {
+ "identifier": "id",
+ "label": "name",
+ "items": [
+ {"id": 1, "name": "Item 1"},
+ {"id": 2, "name": "Item 2"},
+ {"id": 3, "name": "Item 3"},
+ {"id": 4, "name": "Item 4"},
+ {"id": 5, "name": "Item 5"},
+ {"id": 6, "name": "Item 6"},
+ {"id": 7, "name": "Item 7"},
+ {"id": 8, "name": "Item 8"},
+ {"id": 9, "name": "Item 9"},
+ {"id": 10, "name": "Item 10", "friends": [{"_reference": 1},{"_reference": 3},{"_reference": 5}]},
+ {"id": 11, "name": "Item 11", "friends": [{"_reference": 10}], "siblings": [{"_reference": 10}]},
+ {"id": 12, "name": "Item 12", "friends": [{"_reference": 3},{"_reference": 7}], "enemies": [{"_reference": 10}]},
+ {"id": 13, "name": "Item 13", "friends": [{"_reference": 10}]},
+ {"id": 14, "name": "Item 14", "friends": [{"_reference": 11}]},
+ {"id": 15, "name": "item 15", "friends": [{"id": 16, "name": "Item 16"}]}
+ ]
+ }
+ }
+ }
+ }
+ return data;
+};
+
+
+// Now run some tests that are specific to the write-access features:
+doh.register("tests.data.ItemFileWriteStore",
+ [
+ function test_getFeatures(){
+ // summary:
+ // Simple test of the getFeatures function of the store
+ // description:
+ // Simple test of the getFeatures function of the store
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var features = store.getFeatures();
+
+ // make sure we have the expected features:
+ doh.assertTrue(features["dojo.data.api.Read"] != null);
+ doh.assertTrue(features["dojo.data.api.Identity"] != null);
+ doh.assertTrue(features["dojo.data.api.Write"] != null);
+ doh.assertTrue(features["dojo.data.api.Notification"] != null);
+ doh.assertFalse(features["iggy"]);
+
+ // and only the expected features:
+ var count = 0;
+ for(var i in features){
+ doh.assertTrue((i === "dojo.data.api.Read" ||
+ i === "dojo.data.api.Identity" ||
+ i === "dojo.data.api.Write" ||
+ i === "dojo.data.api.Notification"));
+ count++;
+ }
+ doh.assertEqual(count, 4);
+ },
+ function testWriteAPI_setValue(){
+ // summary:
+ // Simple test of the setValue API
+ // description:
+ // Simple test of the setValue API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onComplete(items, request){
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "capital", "Cairo"));
+
+ // FIXME:
+ // Okay, so this seems very odd. Maybe I'm just being dense.
+ // These tests works:
+ doh.assertEqual(store.isDirty(item), false);
+ doh.assertTrue(store.isDirty(item) == false);
+ // But these seemingly equivalent tests will not work:
+ // doh.assertFalse(store.isDirty(item));
+ // doh.assertTrue(!(store.isDirty(item)));
+ //
+ // All of which seems especially weird, given that this *does* work:
+ doh.assertFalse(store.isDirty());
+
+
+ doh.assertTrue(store.isDirty(item) == false);
+ doh.assertTrue(!store.isDirty());
+ store.setValue(item, "capital", "New Cairo");
+ doh.assertTrue(store.isDirty(item));
+ doh.assertTrue(store.isDirty());
+ doh.assertEqual(store.getValue(item, "capital").toString(), "New Cairo");
+ deferred.callback(true);
+ }
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_setValues(){
+ // summary:
+ // Simple test of the setValues API
+ // description:
+ // Simple test of the setValues API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onComplete(items, request){
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+ doh.assertTrue(store.isDirty(item) == false);
+ doh.assertTrue(!store.isDirty());
+ store.setValues(item, "name", ["Egypt 1", "Egypt 2"]);
+ doh.assertTrue(store.isDirty(item));
+ doh.assertTrue(store.isDirty());
+ var values = store.getValues(item, "name");
+ doh.assertTrue(values[0] == "Egypt 1");
+ doh.assertTrue(values[1] == "Egypt 2");
+ deferred.callback(true);
+ }
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_unsetAttribute(){
+ // summary:
+ // Simple test of the unsetAttribute API
+ // description:
+ // Simple test of the unsetAttribute API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onComplete(items, request) {
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+ doh.assertTrue(store.isDirty(item) == false);
+ doh.assertTrue(!store.isDirty());
+ store.unsetAttribute(item, "name");
+ doh.assertTrue(store.isDirty(item));
+ doh.assertTrue(store.isDirty());
+ doh.assertTrue(!store.hasAttribute(item, "name"));
+ deferred.callback(true);
+ }
+ function onError(error, request) {
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_newItem(){
+ // summary:
+ // Simple test of the newItem API
+ // description:
+ // Simple test of the newItem API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ doh.assertTrue(!store.isDirty());
+
+ var onNewInvoked = false;
+ store.onNew = function(newItem, parentInfo){
+
+ doh.assertTrue(newItem !== null);
+ doh.assertTrue(parentInfo === null);
+ doh.assertTrue(store.isItem(newItem));
+ onNewInvoked = true;
+ };
+ var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
+ doh.assertTrue(onNewInvoked);
+
+ doh.assertTrue(store.isDirty(canada));
+ doh.assertTrue(store.isDirty());
+ doh.assertTrue(store.getValues(canada, "name") == "Canada");
+ function onComplete(items, request){
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Canada"));
+ deferred.callback(true);
+ }
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Canada"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_newItem_withParent(){
+ // summary:
+ // Simple test of the newItem API with a parent assignment
+ // description:
+ // Simple test of the newItem API with a parent assignment
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ doh.assertTrue(!store.isDirty());
+ function onComplete(items, request){
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+
+ //Attach an onNew to validate we get expected values.
+ var onNewInvoked = false;
+ store.onNew = function(newItem, parentInfo){
+ doh.assertEqual(item, parentInfo.item);
+ doh.assertEqual("cities", parentInfo.attribute);
+ doh.assertTrue(parentInfo.oldValue === undefined);
+ doh.assertTrue(parentInfo.newValue === newItem);
+ onNewInvoked = true;
+ };
+
+ //Attach an onSet and verify onSet is NOT called in this case.
+ store.onSet = function(item, attribute, oldValue, newValue){
+ doh.assertTrue(false);
+ };
+
+ //See if we can add in a new item representing the city of Cairo.
+ //This should also call the onNew set above....
+ var newItem = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
+ doh.assertTrue(onNewInvoked);
+
+ function onCompleteNewItemShallow(items, request){
+ doh.assertEqual(0, items.length);
+ function onCompleteNewItemDeep(items, request){
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertEqual("Cairo", store.getValue(item, "name"));
+ deferred.callback(true);
+ }
+ //Do a deep search now, should find the new item of the city with name attribute Cairo.
+ store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemDeep, onError: onError, queryOptions: {deep:true}});
+ }
+ //Do a shallow search first, should find nothing.
+ store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemShallow, onError: onError});
+ }
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+
+ function testWriteAPI_newItem_multiple_withParent(){
+ // summary:
+ // Simple test of the newItem API with a parent assignment multiple times.
+ // description:
+ // Simple test of the newItem API with a parent assignment multiple times.
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+
+ doh.assertTrue(!store.isDirty());
+
+ function onComplete(items, request){
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+
+ //Attach an onNew to validate we get expected values.
+ store.onNew = function(newItem, parentInfo){
+ doh.assertEqual(item, parentInfo.item);
+ doh.assertEqual("cities", parentInfo.attribute);
+
+ doh.assertTrue(parentInfo.oldValue === undefined);
+
+ doh.assertTrue(parentInfo.newValue === newItem);
+ };
+
+ //See if we can add in a new item representing the city of Cairo.
+ //This should also call the onNew set above....
+ var newItem1 = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
+
+ //Attach a new onNew to validate we get expected values.
+ store.onNew = function(newItem, parentInfo){
+ doh.assertEqual(item, parentInfo.item);
+ doh.assertEqual("cities", parentInfo.attribute);
+
+ console.log(parentInfo.oldValue);
+ doh.assertTrue(parentInfo.oldValue == newItem1);
+
+ doh.assertTrue(parentInfo.newValue[0] == newItem1);
+ doh.assertTrue(parentInfo.newValue[1] == newItem);
+ };
+ var newItem2 = store.newItem({name: "Banha", abbr: "Banha"}, {parent: item, attribute: "cities"});
+
+ //Attach a new onNew to validate we get expected values.
+ store.onNew = function(newItem, parentInfo){
+ doh.assertEqual(item, parentInfo.item);
+ doh.assertEqual("cities", parentInfo.attribute);
+
+ doh.assertTrue(parentInfo.oldValue[0] == newItem1);
+ doh.assertTrue(parentInfo.oldValue[1] == newItem2);
+
+ doh.assertTrue(parentInfo.newValue[0] == newItem1);
+ doh.assertTrue(parentInfo.newValue[1] == newItem2);
+ doh.assertTrue(parentInfo.newValue[2] == newItem);
+ };
+ var newItem3 = store.newItem({name: "Damanhur", abbr: "Damanhur"}, {parent: item, attribute: "cities"});
+ deferred.callback(true);
+ }
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+
+ function testWriteAPI_deleteItem(){
+ // summary:
+ // Simple test of the deleteItem API
+ // description:
+ // Simple test of the deleteItem API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onComplete(items, request){
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+ doh.assertTrue(store.isDirty(item) == false);
+ doh.assertTrue(!store.isDirty());
+ store.deleteItem(item);
+ doh.assertTrue(store.isDirty(item));
+ doh.assertTrue(store.isDirty());
+ function onCompleteToo(itemsToo, requestToo) {
+ doh.assertEqual(0, itemsToo.length);
+ deferred.callback(true);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
+ }
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_isDirty(){
+ // summary:
+ // Simple test of the isDirty API
+ // description:
+ // Simple test of the isDirty API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onComplete(items, request) {
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+ store.setValue(item, "name", "Egypt 2");
+ doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
+ doh.assertTrue(store.isDirty(item));
+ deferred.callback(true);
+ }
+ function onError(error, request) {
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_revert(){
+ // summary:
+ // Simple test of the revert API
+ // description:
+ // Simple test of the revert API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onComplete(items, request) {
+ doh.assertEqual(1, items.length);
+ var item = items[0];
+ doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+ doh.assertTrue(store.isDirty(item) == false);
+ doh.assertTrue(!store.isDirty());
+ store.setValue(item, "name", "Egypt 2");
+ doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
+ doh.assertTrue(store.isDirty(item));
+ doh.assertTrue(store.isDirty());
+ store.revert();
+
+ //Fetch again to see if it reset the state.
+ function onCompleteToo(itemsToo, requestToo){
+ doh.assertEqual(1, itemsToo.length);
+ var itemToo = itemsToo[0];
+ doh.assertTrue(store.containsValue(itemToo, "name", "Egypt"));
+ deferred.callback(true);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
+ }
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_save(){
+ // summary:
+ // Simple test of the save API
+ // description:
+ // Simple test of the save API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onItem(item){
+ store.setValue(item, "capital", "New Cairo");
+ function onComplete() {
+ deferred.callback(true);
+ }
+ store.save({onComplete:onComplete, onError:onError});
+ }
+ store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_saveVerifyState(){
+ // summary:
+ // Simple test of the save API
+ // description:
+ // Simple test of the save API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onItem(item){
+ store.setValue(item, "capital", "New Cairo");
+ function onComplete() {
+ //Check internal state. Note: Users should NOT do this, this is a UT verification
+ //of internals in this case. Ref tracker: #4394
+ doh.assertTrue(!store._saveInProgress);
+ deferred.callback(true);
+ }
+ store.save({onComplete:onComplete, onError:onError});
+ }
+ store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_saveEverything(){
+ // summary:
+ // Simple test of the save API
+ // description:
+ // Simple test of the save API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ var egypt;
+ store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+ var struct = dojo.fromJson(newFileContentString);
+ doh.assertEqual(struct.identifier, store.getIdentityAttributes(egypt)[0]);
+ doh.assertEqual(struct.label, store.getLabelAttributes(egypt)[0]);
+ doh.assertEqual(struct.items.length, 7);
+
+ var cloneStore = new dojo.data.ItemFileWriteStore({data:struct});
+ function onItemClone(itemClone){
+ var egyptClone = itemClone;
+ doh.assertEqual(store.getIdentityAttributes(egypt)[0], cloneStore.getIdentityAttributes(egyptClone)[0]);
+ doh.assertEqual(store.getLabelAttributes(egypt)[0], cloneStore.getLabelAttributes(egyptClone)[0]);
+ doh.assertEqual(store.getValue(egypt, "name"), cloneStore.getValue(egyptClone, "name"));
+ }
+ cloneStore.fetchItemByIdentity({identity:"eg", onItem:onItemClone, onError:onError});
+
+ saveCompleteCallback();
+ };
+
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onItem(item){
+ egypt = item;
+ function onComplete() {
+ deferred.callback(true);
+ }
+ store.setValue(egypt, "capital", "New Cairo");
+ store.save({onComplete:onComplete, onError:onError});
+ }
+ store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_saveEverything_withDateType(){
+ // summary:
+ // Simple test of the save API with a non-atomic type (Date) that has a type mapping.
+ // description:
+ // Simple test of the save API with a non-atomic type (Date) that has a type mapping.
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+
+ //Now load the new data into a datastore and validate that it stored the date right.
+ var dataset = dojo.fromJson(newFileContentString);
+ var newStore = new dojo.data.ItemFileWriteStore({data: dataset});
+
+ function gotItem(item){
+ var independenceDate = newStore.getValue(item,"independence");
+ doh.assertTrue(independenceDate instanceof Date);
+ doh.assertTrue(dojo.date.compare(new Date(1993,04,24), independenceDate, "date") === 0);
+ saveCompleteCallback();
+ }
+ function failed(error, request){
+ deferred.errback(error);
+ saveFailedCallback();
+ }
+ newStore.fetchItemByIdentity({identity:"eg", onItem:gotItem, onError:failed});
+ };
+
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onItem(item){
+ function onComplete() {
+ deferred.callback(true);
+ }
+ store.setValue(item, "independence", new Date(1993,04,24));
+ store.save({onComplete:onComplete, onError:onError});
+ }
+ store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_saveEverything_withCustomColorTypeSimple(){
+ // summary:
+ // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
+ // description:
+ // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
+
+ //Set up the store basics: What data it has, and what to do when save is called for saveEverything
+ //And how to map the 'Color' type in and out of the format.
+ //(Test of saving all to a some location...)
+ var dataset = {
+ identifier:'name',
+ items: [
+ { name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+ { name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+ ]
+ };
+
+ var customTypeMap = {'Color': dojo.Color };
+
+ var store = new dojo.data.ItemFileWriteStore({
+ data:dataset,
+ typeMap: customTypeMap
+ });
+
+ store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+ //Now load the new data into a datastore and validate that it stored the Color right.
+ var dataset = dojo.fromJson(newFileContentString);
+ var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
+
+ function gotItem(item){
+ var hairColor = newStore.getValue(item,"hairColor");
+ doh.assertTrue(hairColor instanceof dojo.Color);
+ doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
+ saveCompleteCallback();
+ }
+ function failed(error, request){
+ deferred.errback(error);
+ saveFailedCallback();
+ }
+ newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
+ };
+
+ //Add a new item with a color type, then save it.
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onComplete() {
+ deferred.callback(true);
+ }
+
+ var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
+ store.save({onComplete:onComplete, onError:onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_saveEverything_withCustomColorTypeGeneral(){
+ // summary:
+ // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
+ // description:
+ // Simple test of the save API with a non-atomic type (dojo.Color) that has a type mapping.
+
+ //Set up the store basics: What data it has, and what to do when save is called for saveEverything
+ //And how to map the 'Color' type in and out of the format.
+ //(Test of saving all to a some location...)
+ var dataset = {
+ identifier:'name',
+ items: [
+ { name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+ { name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+ ]
+ };
+
+ var customTypeMap = {'Color': {
+ type: dojo.Color,
+ deserialize: function(value){
+ return new dojo.Color(value);
+ },
+ serialize: function(obj){
+ return obj.toString();
+ }
+ }
+ }
+ var store = new dojo.data.ItemFileWriteStore({
+ data:dataset,
+ typeMap: customTypeMap
+ });
+ store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+ //Now load the new data into a datastore and validate that it stored the Color right.
+ var dataset = dojo.fromJson(newFileContentString);
+ var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
+
+ function gotItem(item){
+ var hairColor = newStore.getValue(item,"hairColor");
+ doh.assertTrue(hairColor instanceof dojo.Color);
+ doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
+ saveCompleteCallback();
+ }
+ function failed(error, request){
+ deferred.errback(error);
+ saveFailedCallback();
+ }
+ newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
+ };
+
+ //Add a new item with a color type, then save it.
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onComplete() {
+ deferred.callback(true);
+ }
+
+ var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
+ store.save({onComplete:onComplete, onError:onError});
+ return deferred; //Object
+ },
+ function testWriteAPI_newItem_revert(){
+ // summary:
+ // Test for bug #5357. Ensure that the revert properly nulls the identity position
+ // for a new item after revert.
+ var args = {data: {
+ label:"name",
+ items:[
+ {name:'Ecuador', capital:'Quito'},
+ {name:'Egypt', capital:'Cairo'},
+ {name:'El Salvador', capital:'San Salvador'},
+ {name:'Equatorial Guinea', capital:'Malabo'},
+ {name:'Eritrea', capital:'Asmara'},
+ {name:'Estonia', capital:'Tallinn'},
+ {name:'Ethiopia', capital:'Addis Ababa'}
+ ]
+ } };
+ var store = new dojo.data.ItemFileWriteStore(args);
+
+ var newCountry = store.newItem({name: "Utopia", capitol: "Perfect"});
+
+ //DO NOT ACCESS THIS WAY. THESE ARE INTERNAL VARIABLES. DOING THIS FOR TEST PURPOSES.
+ var itemEntryNum = newCountry[store._itemNumPropName];
+ doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === newCountry);
+ store.revert();
+ doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === null);
+ },
+ function testNotificationAPI_onSet(){
+ // summary:
+ // Simple test of the onSet API
+ // description:
+ // Simple test of the onSet API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onItem(fetchedItem){
+ var egypt = fetchedItem;
+ var connectHandle = null;
+ function setValueHandler(item, attribute, oldValue, newValue){
+ doh.assertTrue(store.isItem(item));
+ doh.assertTrue(item == egypt);
+ doh.assertTrue(attribute == "capital");
+ doh.assertTrue(oldValue == "Cairo");
+ doh.assertTrue(newValue == "New Cairo");
+ deferred.callback(true);
+ dojo.disconnect(connectHandle);
+ }
+ connectHandle = dojo.connect(store, "onSet", setValueHandler);
+ store.setValue(egypt, "capital", "New Cairo");
+ }
+ store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+ },
+ function testNotificationAPI_onNew(){
+ // summary:
+ // Simple test of the onNew API
+ // description:
+ // Simple test of the onNew API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ var connectHandle = null;
+ function newItemHandler(item){
+ doh.assertTrue(store.isItem(item));
+ doh.assertTrue(store.getValue(item, "name") == "Canada");
+ deferred.callback(true);
+ dojo.disconnect(connectHandle);
+ }
+ connectHandle = dojo.connect(store, "onNew", newItemHandler);
+ var canada = store.newItem({name:"Canada", abbr:"ca", capital:"Ottawa"});
+ },
+ function testNotificationAPI_onDelete(){
+ // summary:
+ // Simple test of the onDelete API
+ // description:
+ // Simple test of the onDelete API
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var deferred = new doh.Deferred();
+ function onError(error){
+ deferred.errback(error);
+ }
+ function onItem(fetchedItem){
+ var egypt = fetchedItem;
+ var connectHandle = null;
+ function deleteItemHandler(item){
+ doh.assertTrue(store.isItem(item) == false);
+ doh.assertTrue(item == egypt);
+ deferred.callback(true);
+ dojo.disconnect(connectHandle);
+ }
+ connectHandle = dojo.connect(store, "onDelete", deleteItemHandler);
+ store.deleteItem(egypt);
+ }
+ store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+ },
+ function testReadAPI_functionConformanceToo(){
+ // summary:
+ // Simple test read API conformance. Checks to see all declared functions are actual functions on the instances.
+ // description:
+ // Simple test read API conformance. Checks to see all declared functions are actual functions on the instances.
+ var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ var readApi = new dojo.data.api.Read();
+ var passed = true;
+
+ for(var functionName in readApi){
+ var member = readApi[functionName];
+ //Check that all the 'Read' defined functions exist on the test store.
+ if(typeof member === "function"){
+ var testStoreMember = testStore[functionName];
+ if(!(typeof testStoreMember === "function")){
+ passed = false;
+ break;
+ }
+ }
+ }
+ doh.assertTrue(passed);
+ },
+ function testWriteAPI_functionConformance(){
+ // summary:
+ // Simple test write API conformance. Checks to see all declared functions are actual functions on the instances.
+ // description:
+ // Simple test write API conformance. Checks to see all declared functions are actual functions on the instances.
+ var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ var writeApi = new dojo.data.api.Write();
+ var passed = true;
+
+ for(var functionName in writeApi){
+ var member = writeApi[functionName];
+ //Check that all the 'Write' defined functions exist on the test store.
+ if(typeof member === "function"){
+ var testStoreMember = testStore[functionName];
+ if(!(typeof testStoreMember === "function")){
+ passed = false;
+ break;
+ }
+ }
+ }
+ doh.assertTrue(passed);
+ },
+ function testNotificationAPI_functionConformance(){
+ // summary:
+ // Simple test Notification API conformance. Checks to see all declared functions are actual functions on the instances.
+ // description:
+ // Simple test Notification API conformance. Checks to see all declared functions are actual functions on the instances.
+ var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ var api = new dojo.data.api.Notification();
+ var passed = true;
+
+ for(var functionName in api){
+ var member = api[functionName];
+ //Check that all the 'Write' defined functions exist on the test store.
+ if(typeof member === "function"){
+ var testStoreMember = testStore[functionName];
+ if(!(typeof testStoreMember === "function")){
+ passed = false;
+ break;
+ }
+ }
+ }
+ doh.assertTrue(passed);
+ },
+ function testIdentityAPI_noIdentifierSpecified(){
+ // summary:
+ // Test for bug #3873. Given a datafile that does not specify an
+ // identifier, make sure ItemFileWriteStore auto-creates identities
+ // that are unique even after calls to deleteItem() and newItem()
+ var args = {data: {
+ label:"name",
+ items:[
+ {name:'Ecuador', capital:'Quito'},
+ {name:'Egypt', capital:'Cairo'},
+ {name:'El Salvador', capital:'San Salvador'},
+ {name:'Equatorial Guinea', capital:'Malabo'},
+ {name:'Eritrea', capital:'Asmara'},
+ {name:'Estonia', capital:'Tallinn'},
+ {name:'Ethiopia', capital:'Addis Ababa'}
+ ]
+ } };
+ var store = new dojo.data.ItemFileWriteStore(args);
+ var deferred = new doh.Deferred();
+
+ var onError = function(error, request){
+ deferred.errback(error);
+ }
+ var onComplete = function(items, request){
+ doh.assertEqual(7, items.length);
+
+ var lastItem = items[(items.length - 1)];
+ var idOfLastItem = store.getIdentity(lastItem);
+ store.deleteItem(lastItem);
+ store.newItem({name:'Canada', capital:'Ottawa'});
+
+ var onCompleteAgain = function(itemsAgain, requestAgain){
+ doh.assertEqual(7, itemsAgain.length);
+ var identitiesInUse = {};
+ for(var i = 0; i < itemsAgain.length; ++i){
+ var item = itemsAgain[i];
+ var id = store.getIdentity(item);
+ if(identitiesInUse.hasOwnProperty(id)){
+ // there should not already be an entry for this id
+ doh.assertTrue(false);
+ }else{
+ // we want to add the entry now
+ identitiesInUse[id] = item;
+ }
+ }
+ deferred.callback(true);
+ }
+ store.fetch({onComplete:onCompleteAgain, onError:onError});
+ }
+
+ store.fetch({onComplete:onComplete, onError:onError});
+ return deferred;
+ },
+ function testIdentityAPI_noIdentifierSpecified_revert(){
+ // summary:
+ // Test for bug #4691 Given a datafile that does not specify an
+ // identifier, make sure ItemFileWriteStore auto-creates identities
+ // that are unique even after calls to deleteItem() and newItem()
+ var args = {data: {
+ label:"name",
+ items:[
+ {name:'Ecuador', capital:'Quito'},
+ {name:'Egypt', capital:'Cairo'},
+ {name:'El Salvador', capital:'San Salvador'},
+ {name:'Equatorial Guinea', capital:'Malabo'},
+ {name:'Eritrea', capital:'Asmara'},
+ {name:'Estonia', capital:'Tallinn'},
+ {name:'Ethiopia', capital:'Addis Ababa'}
+ ]
+ } };
+ var store = new dojo.data.ItemFileWriteStore(args);
+ var deferred = new doh.Deferred();
+
+ var onError = function(error, request){
+ deferred.errback(error);
+ }
+ var onComplete = function(items, request){
+ doh.assertEqual(7, items.length);
+
+ var lastItem = items[(items.length - 1)];
+ var idOfLastItem = store.getIdentity(lastItem);
+ store.deleteItem(lastItem);
+ store.newItem({name:'Canada', capital:'Ottawa'});
+
+ var onCompleteAgain = function(itemsAgain, requestAgain){
+ doh.assertEqual(7, itemsAgain.length);
+ var identitiesInUse = {};
+ for(var i = 0; i < itemsAgain.length; ++i){
+ var item = itemsAgain[i];
+ var id = store.getIdentity(item);
+ if(identitiesInUse.hasOwnProperty(id)){
+ // there should not already be an entry for this id
+ doh.assertTrue(false);
+ }else{
+ // we want to add the entry now
+ identitiesInUse[id] = item;
+ }
+ }
+ //Last test, revert everything and check item sizes.
+ store.revert();
+
+ //Now call fetch again and verify store state.
+ var revertComplete = function(itemsReverted, request){
+ doh.assertEqual(7, itemsReverted.length);
+ deferred.callback(true);
+ }
+ store.fetch({onComplete:revertComplete, onError:onError});
+ }
+ store.fetch({onComplete:onCompleteAgain, onError:onError});
+ }
+ store.fetch({onComplete:onComplete, onError:onError});
+ return deferred;
+ },
+ function testReferenceIntegrity_checkReferences(){
+ // summary:
+ // Simple test to verify the references were properly resolved.
+ // description:
+ // Simple test to verify the references were properly resolved.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ function onComplete(items, request){
+
+ var item10 = null;
+ var item1 = null;
+ var item3 = null;
+ var item5 = null;
+
+ for (var i = 0; i < items.length; i++) {
+ var ident = store.getIdentity(items[i]);
+ if (ident === 10) {
+ item10 = items[i];
+ }else if (ident === 1) {
+ item1 = items[i];
+ }else if (ident === 3) {
+ item3 = items[i];
+ }else if (ident === 5) {
+ item5 = items[i];
+ }
+ }
+ var friends = store.getValues(item10, "friends");
+ doh.assertTrue(friends !== null);
+ doh.assertTrue(friends !== undefined);
+
+ doh.assertTrue(store.isItem(item10));
+ doh.assertTrue(store.isItem(item1));
+ doh.assertTrue(store.isItem(item3));
+ doh.assertTrue(store.isItem(item5));
+ var found = 0;
+ try{
+ for (var i = 0; i < friends.length; i++) {
+ if (i === 0) {
+ doh.assertTrue(store.isItem(friends[i]));
+ doh.assertEqual(friends[i], item1);
+ doh.assertEqual(store.getIdentity(friends[i]), 1);
+ found++;
+ }else if (i === 1) {
+ doh.assertTrue(store.isItem(friends[i]));
+ doh.assertEqual(friends[i], item3);
+ doh.assertEqual(store.getIdentity(friends[i]), 3);
+ found++;
+ }else if (i === 2) {
+ doh.assertTrue(store.isItem(friends[i]));
+ doh.assertEqual(friends[i], item5);
+ doh.assertEqual(store.getIdentity(friends[i]), 5);
+ found++;
+ }
+ }
+ }catch(e){
+ doh.errback(e);
+ }
+ doh.assertEqual(3, found);
+ deferred.callback(true);
+ }
+ store.fetch({onError: onError, onComplete: onComplete});
+ return deferred;
+ },
+ function testReferenceIntegrity_deleteReferencedItem(){
+ // summary:
+ // Simple test to verify the references were properly deleted.
+ // description:
+ // Simple test to verify the references were properly deleted.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ function onItem(item, request){
+ try{
+ console.log("Before delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
+ store.deleteItem(item);
+ console.log("After delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
+ function verifyRefDelete(items, request){
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var curItem = items[i];
+ var attributes = store.getAttributes(curItem);
+ for(var j = 0; j < attributes.length; j++){
+ var values = store.getValues(curItem, attributes[j]);
+ var badRef = false;
+ for(var k = 0; k < values.length; k++){
+ var value = values[k];
+ try{
+ var id = store.getIdentity(value);
+ if(id == 10){
+ badRef = true;
+ break;
+ }
+ }catch(e){/*Not an item, even a dead one, just eat it.*/}
+ }
+ if(badRef){
+ deferred.errback(new Error("Found a reference remaining to a deleted item. Failure."));
+ passed = false;
+ break;
+ }
+ }
+ }
+ if(passed){
+ deferred.callback(true);
+ }
+ }
+ store.fetch({onComplete: verifyRefDelete, onError: onError});
+ }catch(error){
+ deferred.errback(error);
+ }
+ }
+ store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+ return deferred;
+ },
+ function testReferenceIntegrity_deleteReferencedItemThenRevert(){
+ // summary:
+ // Simple test to verify the references were properly deleted.
+ // description:
+ // Simple test to verify the references were properly deleted.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ function onItem(item, request){
+ try{
+ //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
+ //THIS IS FOR TESTING INTERNAL STATE!
+ console.log("Map before delete:");
+ store._dumpReferenceMap();
+ var beforeDelete = dojo.toJson(item[store._reverseRefMap]);
+ store.deleteItem(item);
+ console.log("Map after delete:");
+ store._dumpReferenceMap();
+ var afterDelete = dojo.toJson(item[store._reverseRefMap]);
+ store.revert();
+ console.log("Map after revert:");
+ store._dumpReferenceMap();
+ var afterRevert = dojo.toJson(item[store._reverseRefMap]);
+ doh.assertTrue(afterRevert === beforeDelete);
+ }catch(e){
+ deferred.errback(e);
+ passed = false;
+ }
+ if(passed){
+ deferred.callback(true);
+ }
+ }
+ store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+ return deferred;
+ },
+ function testReferenceIntegrity_deleteMultipleItemsWithReferencesAndRevert(){
+ // summary:
+ // Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
+ // Created for tracker bug: #5743
+ // description:
+ // Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
+ // Created for tracker bug: #5743
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_references"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ doh.assertTrue(false);
+ }
+ function onItem(item, request){
+ //Save off the located item, then locate another one (peer to Egypt)
+ doh.assertTrue(store.isItem(item));
+ var egypt = item;
+
+ function onItem2(item, request){
+ doh.assertTrue(store.isItem(item));
+ var nairobi = item;
+
+ //Delete them
+ store.deleteItem(egypt);
+ store.deleteItem(nairobi);
+ try{
+ //Revert, then do a fetch. If the internals have been damaged, this will generally
+ //cause onError to fire instead of onComplete.
+ store.revert();
+ function onComplete(items, request){
+ deferred.callback(true);
+ }
+ store.fetch({query: {name: "*"}, start: 0, count: 20, onComplete: onComplete, onError: onError});
+ }catch(e){
+ deferred.errback(e)
+ }
+ }
+ store.fetchItemByIdentity({identity: "Nairobi", onError: onError, onItem: onItem2});
+ }
+ store.fetchItemByIdentity({identity: "Egypt", onError: onError, onItem: onItem});
+ return deferred;
+ },
+ function testReferenceIntegrity_removeReferenceFromAttribute(){
+ // summary:
+ // Simple test to verify the reference removal updates the internal map.
+ // description:
+ // Simple test to verify the reference removal updates the internal map.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ doh.assertTrue(false);
+ }
+ function onItem(item, request){
+ try{
+ store.setValues(item, "friends", [null]);
+
+ function onItem2(item10, request){
+ //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
+ //THIS IS FOR TESTING INTERNAL STATE!
+ var refMap = item10[store._reverseRefMap];
+ store._dumpReferenceMap();
+
+ console.log("MAP for Item 10 is: " + dojo.toJson(refMap));
+
+ //Assert there is no reference to item 10 in item 11's attribute 'friends'.
+ doh.assertTrue(!refMap["11"]["friends"]);
+ store.setValues(item, "siblings", [0, 1, 2]);
+ //Assert there are no more references to 10 in 11. Ergo, "11" should be a 'undefined' attribute for the map of items referencing '10'..
+ doh.assertTrue(!refMap["11"]);
+ deferred.callback(true);
+ }
+ store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem2});
+
+ }catch(e){
+ console.debug(e);
+ deferred.errback(e);
+ doh.assertTrue(false);
+ }
+ }
+ store.fetchItemByIdentity({identity: 11, onError: onError, onItem: onItem});
+ return deferred;
+ },
+ function testReferenceIntegrity_deleteReferencedItemNonParent(){
+ // summary:
+ // Simple test to verify the references to a non-parent item was properly deleted.
+ // description:
+ // Simple test to verify the references to a non-parent item was properly deleted.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ }
+ function onItem(item, request){
+ try{
+ console.log("Reference state for item 16 is: " + dojo.toJson(item[store._reverseRefMap]));
+ store.deleteItem(item);
+ function verifyRefDelete(items, request){
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var curItem = items[i];
+ var attributes = store.getAttributes(curItem);
+ for(var j = 0; j < attributes.length; j++){
+ var values = store.getValues(curItem, attributes[j]);
+ var badRef = false;
+ for(var k = 0; k < values.length; k++){
+ var value = values[k];
+ try{
+ var id = store.getIdentity(value);
+ if(id == 16){
+ badRef = true;
+ break;
+ }
+ }catch(e){/*Not an item, even a dead one, just eat it.*/}
+ }
+ if(badRef){
+ deferred.errback(new Error("Found a reference remaining to a deleted item. Failure."));
+ passed = false;
+ break;
+ }
+ }
+ }
+ if(passed){
+ deferred.callback(true);
+ }
+ }
+ store.fetch({onComplete: verifyRefDelete, onError: onError});
+ }catch(error){
+ deferred.errback(error);
+ }
+ }
+ store.fetchItemByIdentity({identity: 16, onError: onError, onItem: onItem});
+ return deferred;
+ },
+ function testReferenceIntegrity_addReferenceToAttribute(){
+ // summary:
+ // Simple test to verify the reference additions can happen.
+ // description:
+ // Simple test to verify the reference additions can happen.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ doh.assertTrue(false);
+ }
+ function onComplete(items, request){
+
+ doh.assertTrue(items.length > 2);
+
+ var item1 = items[0];
+ var item2 = items[1];
+
+ //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
+ //THIS IS FOR TESTING INTERNAL STATE!
+ console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
+ console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
+
+ store.setValue(item1, "siblings", item2);
+
+ //Emit the current map state for inspection.
+ console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
+ console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
+
+ doh.assertTrue(item2[store._reverseRefMap] != null);
+
+ //Assert there is a recorded reference to item 2 in item 1's attribute 'sibling'.
+ doh.assertTrue(item2[store._reverseRefMap][store.getIdentity(item1)]["siblings"]);
+
+ deferred.callback(true);
+ }
+ store.fetch({onError: onError, onComplete: onComplete});
+ return deferred;
+ },
+ function testReferenceIntegrity_newItemWithParentReference(){
+ // summary:
+ // Simple test to verify that newItems with a parent properly record the parent's reference in the map.
+ // description:
+ // Simple test to verify that newItems with a parent properly record the parent's reference in the map.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ doh.assertTrue(false);
+ }
+ function onItem(item, request){
+ try{
+ //Create a new item and set its parent to item 10's uncle attribute.
+ var newItem = store.newItem({id: 17, name: "Item 17"}, {parent: item, attribute: "uncles"});
+
+ //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
+ //THIS IS FOR TESTING INTERNAL STATE!
+ //Look up the references to 17, as item 10 has one now on attribute 'uncles'
+ var refs = newItem[store._reverseRefMap];
+
+ //Assert there is a reference from 10 to item 17, on attribute uncle
+ doh.assertTrue(refs["10"]["uncles"]);
+
+ console.log("State of map of item 17 after newItem: " + dojo.toJson(refs));
+ }catch(e){
+ console.debug(e);
+ deferred.errback(e);
+ doh.assertTrue(false);
+ passed = false;
+ }
+ if(passed){
+ deferred.callback(true);
+ }
+ }
+ store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+ return deferred;
+ },
+ function testReferenceIntegrity_newItemWithReferenceToExistingItem(){
+ // summary:
+ // Simple test to verify that a new item with references to existing items properly record the references in the map.
+ // description:
+ // Simple test to verify that a new item with references to existing items properly record the references in the map.
+
+ var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+ var deferred = new doh.Deferred();
+ var passed = true;
+ function onError(error, request){
+ deferred.errback(error);
+ doh.assertTrue(false);
+ }
+ function onItem(item, request){
+ try{
+ //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
+ //THIS IS FOR TESTING INTERNAL STATE!
+ console.log("State of reference map to item 10 before newItem: " + dojo.toJson(item[store._reverseRefMap]));
+
+ //Create a new item and set its parent to item 10's uncle attribute.
+ var newItem = store.newItem({id: 17, name: "Item 17", friends: [item]});
+
+ //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
+ //THIS IS FOR TESTING INTERNAL STATE!
+ //Look up the references to 10, as item 17 has one on friends now.
+ var refs = item[store._reverseRefMap];
+
+ //Assert there is a reference from 15 to item 10, on attribute friends
+ doh.assertTrue(refs["17"]["friends"]);
+
+ console.log("State of reference map to item 10 after newItem: " + dojo.toJson(refs));
+ }catch(e){
+ console.debug(e);
+ deferred.errback(e);
+ doh.assertTrue(false);
+ passed = false;
+ }
+ if(passed){
+ deferred.callback(true);
+ }
+ }
+ store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+ return deferred;
+ },
+ function testReferenceIntegrity_disableReferenceIntegrity(){
+ // summary:
+ // Simple test to verify reference integrity can be disabled.
+ // description:
+ // Simple test to verify reference integrity can be disabled.
+
+ var params = tests.data.ItemFileWriteStore.getTestData("reference_integrity");
+ params.referenceIntegrity = false;
+ var store = new dojo.data.ItemFileWriteStore(params);
+
+ var deferred = new doh.Deferred();
+ function onError(error, request){
+ deferred.errback(error);
+ doh.assertTrue(false);
+ }
+ function onItem(item, request){
+ //DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!
+ //THIS IS FOR TESTING INTERNAL STATE!
+ if(item[store._reverseRefMap] === undefined){
+ deferred.callback(true);
+ }else{
+ deferred.errback(new Error("Disabling of reference integrity failed."));
+ }
+ }
+ store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+ return deferred;
+ }
+ ]
+);
+
+
+
+}
diff --git a/includes/js/dojo/tests/data/countries.json b/includes/js/dojo/tests/data/countries.json
new file mode 100644
index 0000000..71631da
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries.json
@@ -0,0 +1,11 @@
+{ identifier: 'abbr',
+ label: 'name',
+ items: [
+ { abbr:'ec', name:'Ecuador', capital:'Quito' },
+ { abbr:'eg', name:'Egypt', capital:'Cairo' },
+ { abbr:'sv', name:'El Salvador', capital:'San Salvador' },
+ { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+ { abbr:'er', name:'Eritrea', capital:'Asmara' },
+ { abbr:'ee', name:'Estonia', capital:'Tallinn' },
+ { abbr:'et', name:'Ethiopia', capital:'Addis Ababa' }
+]}
diff --git a/includes/js/dojo/tests/data/countries_commentFiltered.json b/includes/js/dojo/tests/data/countries_commentFiltered.json
new file mode 100644
index 0000000..319e429
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries_commentFiltered.json
@@ -0,0 +1,12 @@
+/*
+{ identifier: 'abbr',
+ items: [
+ { abbr:'ec', name:'Ecuador', capital:'Quito' },
+ { abbr:'eg', name:'Egypt', capital:'Cairo' },
+ { abbr:'sv', name:'El Salvador', capital:'San Salvador' },
+ { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+ { abbr:'er', name:'Eritrea', capital:'Asmara' },
+ { abbr:'ee', name:'Estonia', capital:'Tallinn' },
+ { abbr:'et', name:'Ethiopia', capital:'Addis Ababa' }
+]}
+*/
diff --git a/includes/js/dojo/tests/data/countries_idcollision.json b/includes/js/dojo/tests/data/countries_idcollision.json
new file mode 100644
index 0000000..a0c4a7b
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries_idcollision.json
@@ -0,0 +1,10 @@
+{ identifier: 'abbr',
+ items: [
+ { abbr:'ec', name:'Ecuador', capital:'Quito' },
+ { abbr:'sv', name:'El Salvador', capital:'San Salvador' },
+ { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+ { abbr:'er', name:'Eritrea', capital:'Asmara' },
+ { abbr:'ec', name:'Egypt', capital:'Cairo' },
+ { abbr:'ee', name:'Estonia', capital:'Tallinn' },
+ { abbr:'et', name:'Ethiopia', capital:'Addis Ababa' }
+]}
diff --git a/includes/js/dojo/tests/data/countries_references.json b/includes/js/dojo/tests/data/countries_references.json
new file mode 100644
index 0000000..136f3c2
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries_references.json
@@ -0,0 +1,44 @@
+{ 'identifier': 'name',
+ 'label': 'name',
+ 'items': [
+ { 'name':'Africa', 'type':'continent',
+ 'children':[{'_reference':'Egypt'}, {'_reference':'Kenya'}, {'_reference':'Sudan'}] },
+ { 'name':'Egypt', 'type':'country' },
+ { 'name':'Kenya', 'type':'country',
+ 'children':[{'_reference':'Nairobi'}, {'_reference':'Mombasa'}] },
+ { 'name':'Nairobi', 'type':'city' },
+ { 'name':'Mombasa', 'type':'city' },
+ { 'name':'Sudan', 'type':'country',
+ 'children':{'_reference':'Khartoum'} },
+ { 'name':'Khartoum', 'type':'city' },
+ { 'name':'Asia', 'type':'continent',
+ 'children':[{'_reference':'China'}, {'_reference':'India'}, {'_reference':'Russia'}, {'_reference':'Mongolia'}] },
+ { 'name':'China', 'type':'country' },
+ { 'name':'India', 'type':'country' },
+ { 'name':'Russia', 'type':'country' },
+ { 'name':'Mongolia', 'type':'country' },
+ { 'name':'Australia', 'type':'continent', 'population':'21 million',
+ 'children':{'_reference':'Commonwealth of Australia'}},
+ { 'name':'Commonwealth of Australia', 'type':'country', 'population':'21 million'},
+ { 'name':'Europe', 'type':'continent',
+ 'children':[{'_reference':'Germany'}, {'_reference':'France'}, {'_reference':'Spain'}, {'_reference':'Italy'}] },
+ { 'name':'Germany', 'type':'country' },
+ { 'name':'France', 'type':'country' },
+ { 'name':'Spain', 'type':'country' },
+ { 'name':'Italy', 'type':'country' },
+ { 'name':'North America', 'type':'continent',
+ 'children':[{'_reference':'Mexico'}, {'_reference':'Canada'}, {'_reference':'United States of America'}] },
+ { 'name':'Mexico', 'type':'country', 'population':'108 million', area:'1,972,550 sq km',
+ 'children':[{'_reference':'Mexico City'}, {'_reference':'Guadalajara'}] },
+ { 'name':'Mexico City', 'type':'city', 'population':'19 million', 'timezone':'-6 UTC'},
+ { 'name':'Guadalajara', 'type':'city', 'population':'4 million', 'timezone':'-6 UTC' },
+ { 'name':'Canada', 'type':'country', 'population':'33 million', area:'9,984,670 sq km',
+ 'children':[{'_reference':'Ottawa'}, {'_reference':'Toronto'}] },
+ { 'name':'Ottawa', 'type':'city', 'population':'0.9 million', 'timezone':'-5 UTC'},
+ { 'name':'Toronto', 'type':'city', 'population':'2.5 million', 'timezone':'-5 UTC' },
+ { 'name':'United States of America', 'type':'country' },
+ { 'name':'South America', 'type':'continent',
+ 'children':[{'_reference':'Brazil'}, {'_reference':'Argentina'}] },
+ { 'name':'Brazil', 'type':'country', 'population':'186 million' },
+ { 'name':'Argentina', 'type':'country', 'population':'40 million' }
+]}
diff --git a/includes/js/dojo/tests/data/countries_withBoolean.json b/includes/js/dojo/tests/data/countries_withBoolean.json
new file mode 100644
index 0000000..783d8a8
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries_withBoolean.json
@@ -0,0 +1,11 @@
+{ identifier: 'abbr',
+ items: [
+ { abbr:'ec', name:'Ecuador', capital:'Quito', real:true},
+ { abbr:'eg', name:'Egypt', capital:'Cairo', real:true},
+ { abbr:'sv', name:'El Salvador', capital:'San Salvador', real:true},
+ { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', real:true},
+ { abbr:'er', name:'Eritrea', capital:'Asmara', real:true},
+ { abbr:'ee', name:'Estonia', capital:'Tallinn', real:true},
+ { abbr:'et', name:'Ethiopia', capital:'Addis Ababa', real:true},
+ { abbr:'ut', name:'Utopia', capital:'Paradise', real:false}
+]}
diff --git a/includes/js/dojo/tests/data/countries_withDates.json b/includes/js/dojo/tests/data/countries_withDates.json
new file mode 100644
index 0000000..fdd2153
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries_withDates.json
@@ -0,0 +1,21 @@
+{ identifier: 'abbr',
+ label: 'name',
+ items: [
+ { abbr:'ec', name:'Ecuador', capital:'Quito' },
+ { abbr:'eg', name:'Egypt', capital:'Cairo' },
+ { abbr:'sv', name:'El Salvador', capital:'San Salvador' },
+ { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+ { abbr:'er',
+ name:'Eritrea',
+ capital:'Asmara',
+ independence:{_type:'Date', _value:"1993-05-24T00:00:00Z"} // May 24, 1993 in ISO-8601 standard
+ },
+ { abbr:'ee',
+ name:'Estonia',
+ capital:'Tallinn',
+ independence:{_type:'Date', _value:"1991-08-20T00:00:00Z"} // August 20, 1991 in ISO-8601 standard
+ },
+ { abbr:'et',
+ name:'Ethiopia',
+ capital:'Addis Ababa' }
+]}
diff --git a/includes/js/dojo/tests/data/countries_withNull.json b/includes/js/dojo/tests/data/countries_withNull.json
new file mode 100644
index 0000000..a0a7a3f
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries_withNull.json
@@ -0,0 +1,10 @@
+{ identifier: 'abbr',
+ items: [
+ { abbr:'ec', name:null, capital:'Quito' },
+ { abbr:'eg', name:null, capital:'Cairo' },
+ { abbr:'sv', name:'El Salvador', capital:'San Salvador' },
+ { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+ { abbr:'er', name:'Eritrea', capital:'Asmara' },
+ { abbr:'ee', name:null, capital:'Tallinn' },
+ { abbr:'et', name:'Ethiopia', capital:'Addis Ababa' }
+]}
diff --git a/includes/js/dojo/tests/data/countries_withoutid.json b/includes/js/dojo/tests/data/countries_withoutid.json
new file mode 100644
index 0000000..8db3046
--- /dev/null
+++ b/includes/js/dojo/tests/data/countries_withoutid.json
@@ -0,0 +1,10 @@
+{ label: 'name',
+ items: [
+ { abbr:'ec', name:'Ecuador', capital:'Quito' },
+ { abbr:'eg', name:'Egypt', capital:'Cairo' },
+ { abbr:'sv', name:'El Salvador', capital:'San Salvador' },
+ { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+ { abbr:'er', name:'Eritrea', capital:'Asmara' },
+ { abbr:'ee', name:'Estonia', capital:'Tallinn' },
+ { abbr:'et', name:'Ethiopia', capital:'Addis Ababa' }
+]}
diff --git a/includes/js/dojo/tests/data/data_multitype.json b/includes/js/dojo/tests/data/data_multitype.json
new file mode 100644
index 0000000..449995a
--- /dev/null
+++ b/includes/js/dojo/tests/data/data_multitype.json
@@ -0,0 +1,18 @@
+{
+ "identifier": "count",
+ "label": "count",
+ "items": [
+ { "count": 1, "value": "true" },
+ { "count": 2, "value": true },
+ { "count": 3, "value": "false"},
+ { "count": 4, "value": false },
+ { "count": 5, "value": true },
+ { "count": 6, "value": true },
+ { "count": 7, "value": "true" },
+ { "count": 8, "value": "true" },
+ { "count": 9, "value": "false"},
+ { "count": 10, "value": false },
+ { "count": 11, "value": [false, false]},
+ { "count": "12", "value": [false, "true"]}
+ ]
+}
diff --git a/includes/js/dojo/tests/data/geography_hierarchy_large.json b/includes/js/dojo/tests/data/geography_hierarchy_large.json
new file mode 100644
index 0000000..71fd29b
--- /dev/null
+++ b/includes/js/dojo/tests/data/geography_hierarchy_large.json
@@ -0,0 +1,44 @@
+{ identifier: 'name',
+ items: [
+ { name:'Africa', type:'continent', children:[
+ { name:'Egypt', type:'country' },
+ { name:'Kenya', type:'country', children:[
+ { name:'Nairobi', type:'city' },
+ { name:'Mombasa', type:'city' } ]
+ },
+ { name:'Sudan', type:'country', children:
+ { name:'Khartoum', type:'city' }
+ } ]
+ },
+ { name:'Asia', type:'continent', children:[
+ { name:'China', type:'country' },
+ { name:'India', type:'country' },
+ { name:'Russia', type:'country' },
+ { name:'Mongolia', type:'country' } ]
+ },
+ { name:'Australia', type:'continent', population:'21 million', children:
+ { name:'Commonwealth of Australia', type:'country', population:'21 million'}
+ },
+ { name:'Europe', type:'continent', children:[
+ { name:'Germany', type:'country' },
+ { name:'France', type:'country' },
+ { name:'Spain', type:'country' },
+ { name:'Italy', type:'country' } ]
+ },
+ { name:'North America', type:'continent', children:[
+ { name:'Mexico', type:'country', population:'108 million', area:'1,972,550 sq km', children:[
+ { name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+ { name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' } ]
+ },
+ { name:'Canada', type:'country', population:'33 million', area:'9,984,670 sq km', children:[
+ { name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+ { name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' }]
+ },
+ { name:'United States of America', type:'country' } ]
+ },
+ { name:'South America', type:'continent', children:[
+ { name:'Brazil', type:'country', population:'186 million' },
+ { name:'Argentina', type:'country', population:'40 million' } ]
+ } ]
+}
+
diff --git a/includes/js/dojo/tests/data/geography_hierarchy_small.json b/includes/js/dojo/tests/data/geography_hierarchy_small.json
new file mode 100644
index 0000000..989e5f7
--- /dev/null
+++ b/includes/js/dojo/tests/data/geography_hierarchy_small.json
@@ -0,0 +1,19 @@
+{ items:[
+ { name:'Africa', countries:[
+ { name:'Egypt', capital:'Cairo' },
+ { name:'Kenya', capital:'Nairobi' },
+ { name:'Sudan', capital:'Khartoum' }]},
+ { name:'Australia', capital:'Canberra' },
+ { name:'North America', countries:[
+ { name:'Canada', population:'33 million', cities:[
+ { name:'Toronto', population:'2.5 million' },
+ { name:'Alberta', population:'1 million' }
+ ]},
+ { name: 'United States of America', capital: 'Washington DC', states:[
+ { name: 'Missouri'},
+ { name: 'Arkansas'}
+ ]}
+ ]}
+ ]
+}
+
diff --git a/includes/js/dojo/tests/data/readOnlyItemFileTestTemplates.js b/includes/js/dojo/tests/data/readOnlyItemFileTestTemplates.js
new file mode 100644
index 0000000..7e194b4
--- /dev/null
+++ b/includes/js/dojo/tests/data/readOnlyItemFileTestTemplates.js
@@ -0,0 +1,2260 @@
+if(!dojo._hasResource["tests.data.readOnlyItemFileTestTemplates"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.data.readOnlyItemFileTestTemplates"] = true;
+dojo.provide("tests.data.readOnlyItemFileTestTemplates");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+dojo.require("dojo.date");
+dojo.require("dojo.date.stamp");
+
+
+tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore = function(/* String */ datastoreClassName){
+ // summary:
+ // Given the name of a datastore class to use, this function creates
+ // a set of unit tests for that datastore, and registers the new test
+ // group with the doh test framework. The new unit tests are based
+ // on a set of "template" unit tests.
+ var datastoreClass = dojo.getObject(datastoreClassName);
+ var testTemplates = tests.data.readOnlyItemFileTestTemplates.testTemplates;
+ var testsForDatastore = [];
+ var makeNewTestFunction = function(template){
+ return function(t){return template.runTest(datastoreClass, t);};
+ };
+ for(var i = 0; i < testTemplates.length; ++i) {
+ var testTemplate = testTemplates[i];
+ var test = {};
+ test.name = testTemplate.name;
+ test.runTest = makeNewTestFunction(testTemplate);
+ testsForDatastore.push(test);
+ }
+ var testGroupName = "tests.data.readOnlyItemFileTestTemplates, with datastore " + datastoreClassName;
+ doh.register(testGroupName, testsForDatastore);
+};
+
+
+//-----------------------------------------------------
+// testFile data-sets
+tests.data.readOnlyItemFileTestTemplates.getTestData = function(name){
+ var data = null;
+ if(name === "countries"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/countries.json").toString() };
+ }else{
+ data = {data: {
+ identifier:"abbr",
+ label:"name",
+ items:[
+ {abbr:"ec", name:"Ecuador", capital:"Quito"},
+ {abbr:'eg', name:'Egypt', capital:'Cairo'},
+ {abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+ {abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+ {abbr:'er', name:'Eritrea', capital:'Asmara'},
+ {abbr:'ee', name:'Estonia', capital:'Tallinn'},
+ {abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+ ]
+ } };
+ }
+ }else if(name === "countries_withNull"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/countries_withNull.json").toString() };
+ }else{
+ data = {data: {
+ identifier:"abbr",
+ items:[
+ {abbr:"ec", name:null, capital:"Quito"},
+ {abbr:'eg', name:null, capital:'Cairo'},
+ {abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+ {abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+ {abbr:'er', name:'Eritrea', capital:'Asmara'},
+ {abbr:'ee', name:null, capital:'Tallinn'},
+ {abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+ ]
+ } };
+ }
+ }else if(name === "countries_withoutid"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/countries_withoutid.json").toString() };
+ }else{
+ data = {data: {
+ label: "name",
+ items:[
+ {abbr:"ec", name:null, capital:"Quito"},
+ {abbr:'eg', name:null, capital:'Cairo'},
+ {abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+ {abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+ {abbr:'er', name:'Eritrea', capital:'Asmara'},
+ {abbr:'ee', name:null, capital:'Tallinn'},
+ {abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+ ]
+ } };
+ }
+ }else if (name === "countries_withBoolean"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/countries_withBoolean.json").toString() };
+ }else{
+ data = {data: {
+ identifier:"abbr",
+ items:[
+ {abbr:"ec", name:"Ecuador", capital:"Quito", real:true},
+ {abbr:'eg', name:'Egypt', capital:'Cairo', real:true},
+ {abbr:'sv', name:'El Salvador', capital:'San Salvador', real:true},
+ {abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', real:true},
+ {abbr:'er', name:'Eritrea', capital:'Asmara', real:true},
+ {abbr:'ee', name:'Estonia', capital:'Tallinn', real:true},
+ {abbr:'et', name:'Ethiopia', capital:'Addis Ababa', real:true},
+ {abbr:'ut', name:'Utopia', capital:'Paradise', real:false}
+ ]
+ } };
+ }
+ }else if (name === "countries_withDates"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/countries_withDates.json").toString() };
+ }else{
+ data = {data: {
+ identifier:"abbr",
+ items:[
+ {abbr:"ec", name:"Ecuador", capital:"Quito"},
+ {abbr:'eg', name:'Egypt', capital:'Cairo'},
+ {abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+ {abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+ {abbr:'er', name:'Eritrea', capital:'Asmara', independence:{_type:'Date', _value:"1993-05-24T00:00:00Z"}}, // May 24, 1993,
+ {abbr:'ee', name:'Estonia', capital:'Tallinn', independence:{_type:'Date', _value:"1991-08-20T00:00:00Z"}}, // August 20, 1991
+ {abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+ ]
+ } };
+ }
+ }else if (name === "geography_hierarchy_small"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/geography_hierarchy_small.json").toString() };
+ }else{
+ data = {data: {
+ items:[
+ { name:'Africa', countries:[
+ { name:'Egypt', capital:'Cairo' },
+ { name:'Kenya', capital:'Nairobi' },
+ { name:'Sudan', capital:'Khartoum' }]},
+ { name:'Australia', capital:'Canberra' },
+ { name:'North America', countries:[
+ { name:'Canada', population:'33 million', cities:[
+ { name:'Toronto', population:'2.5 million' },
+ { name:'Alberta', population:'1 million' }
+ ]},
+ { name: 'United States of America', capital: 'Washington DC', states:[
+ { name: 'Missouri'},
+ { name: 'Arkansas'}
+ ]}
+ ]}
+ ]
+ }};
+ }
+ }else if (name === "data_multitype"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/data_multitype.json").toString() };
+ }else{
+ data = {data: {
+ "identifier": "count",
+ "label": "count",
+ items: [
+ { count: 1, value: "true" },
+ { count: 2, value: true },
+ { count: 3, value: "false"},
+ { count: 4, value: false },
+ { count: 5, value: true },
+ { count: 6, value: true },
+ { count: 7, value: "true" },
+ { count: 8, value: "true" },
+ { count: 9, value: "false"},
+ { count: 10, value: false },
+ { count: 11, value: [false, false]},
+ { count: "12", value: [false, "true"]}
+ ]
+ }
+ };
+ }
+ }else if (name === "countries_references"){
+ if(dojo.isBrowser){
+ data = {url: dojo.moduleUrl("tests", "data/countries_references.json").toString() };
+ }else{
+ data = {data: { identifier: 'name',
+ label: 'name',
+ items: [
+ { name:'Africa', type:'continent',
+ children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
+ { name:'Egypt', type:'country' },
+ { name:'Kenya', type:'country',
+ children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+ { name:'Nairobi', type:'city' },
+ { name:'Mombasa', type:'city' },
+ { name:'Sudan', type:'country',
+ children:{_reference:'Khartoum'} },
+ { name:'Khartoum', type:'city' },
+ { name:'Asia', type:'continent',
+ children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
+ { name:'China', type:'country' },
+ { name:'India', type:'country' },
+ { name:'Russia', type:'country' },
+ { name:'Mongolia', type:'country' },
+ { name:'Australia', type:'continent', population:'21 million',
+ children:{_reference:'Commonwealth of Australia'}},
+ { name:'Commonwealth of Australia', type:'country', population:'21 million'},
+ { name:'Europe', type:'continent',
+ children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
+ { name:'Germany', type:'country' },
+ { name:'France', type:'country' },
+ { name:'Spain', type:'country' },
+ { name:'Italy', type:'country' },
+ { name:'North America', type:'continent',
+ children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
+ { name:'Mexico', type:'country', population:'108 million', area:'1,972,550 sq km',
+ children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+ { name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+ { name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+ { name:'Canada', type:'country', population:'33 million', area:'9,984,670 sq km',
+ children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+ { name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+ { name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+ { name:'United States of America', type:'country' },
+ { name:'South America', type:'continent',
+ children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
+ { name:'Brazil', type:'country', population:'186 million' },
+ { name:'Argentina', type:'country', population:'40 million' }
+ ]
+ }
+ };
+ }
+ }
+ return data;
+};
+
+//-----------------------------------------------------
+// testTemplates
+tests.data.readOnlyItemFileTestTemplates.testTemplates = [
+ {
+ name: "Identity API: fetchItemByIdentity()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the fetchItemByIdentity function of the store.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ if(item !== null){
+ var name = store.getValue(item,"name");
+ t.assertEqual(name, "El Salvador");
+ }
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: fetchItemByIdentity() notFound",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the fetchItemByIdentity function of the store.
+ // description:
+ // Simple test of the fetchItemByIdentity function of the store.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item === null);
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv_not", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: getIdentityAttributes()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getIdentityAttributes function.
+ // description:
+ // Simple test of the getIdentityAttributes function.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null)
+ var identifiers = store.getIdentityAttributes(item);
+ t.assertTrue(dojo.isArray(identifiers));
+ t.assertEqual(1, identifiers.length);
+ t.assertEqual("abbr", identifiers[0]);
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: fetchItemByIdentity() commentFilteredJson",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the fetchItemByIdentity function of the store.
+ // description:
+ // Simple test of the fetchItemByIdentity function of the store.
+ // This tests loading a comment-filtered json file so that people using secure
+ // data with this store can bypass the JavaSceipt hijack noted in Fortify's
+ // paper.
+
+ if(dojo.isBrowser){
+ var store = new datastore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var name = store.getValue(item,"name");
+ t.assertEqual(name, "El Salvador");
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ }
+ },
+ {
+ name: "Identity API: fetchItemByIdentity() nullValue",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the fetchItemByIdentity function of the store, checling a null value.
+ // description:
+ // Simple test of the fetchItemByIdentity function of the store, checking a null value.
+ // This tests handling attributes in json that were defined as null properly.
+ // Introduced because of tracker: #3153
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withNull"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var name = store.getValue(item,"name");
+ t.assertEqual(name, null);
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "ec", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: fetchItemByIdentity() booleanValue",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+ // description:
+ // Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withBoolean"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var name = store.getValue(item,"name");
+ t.assertEqual(name, "Utopia");
+ var real = store.getValue(item,"real");
+ t.assertEqual(real, false);
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "ut", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: fetchItemByIdentity() withoutSpecifiedIdInData",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+ // description:
+ // Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withoutid"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var name = store.getValue(item,"name");
+ t.assertEqual(name, "El Salvador");
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "2", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: getIdentity()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getIdentity function of the store.
+ // description:
+ // Simple test of the getIdentity function of the store.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ t.assertTrue(store.getIdentity(item) === "sv");
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: getIdentity() withoutSpecifiedId",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the #4691 bug
+ // description:
+ // Simple test of the #4691 bug
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withoutid"));
+
+ var d = new doh.Deferred();
+ function onItem(item, request){
+ t.assertTrue(item !== null);
+ t.assertTrue(store.getIdentity(item) === 2);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query:{abbr: "sv"}, onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: fetch() all",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch on ItemFileReadStore.
+ // description:
+ // Simple test of a basic fetch on ItemFileReadStore.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function completedAll(items, request){
+ t.is(7, items.length);
+ d.callback(true);
+ }
+ function error(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+
+ //Get everything...
+ store.fetch({ onComplete: completedAll, onError: error});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() one",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch on ItemFileReadStore of a single item.
+ // description:
+ // Simple test of a basic fetch on ItemFileReadStore of a single item.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(items.length, 1);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query: {abbr: "ec"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() shallow",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch on ItemFileReadStore of only toplevel items
+ // description:
+ // Simple test of a basic fetch on ItemFileReadStore of only toplevel items.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(items.length, 2);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ //Find all items starting with A, only toplevel (root) items.
+ store.fetch({ query: {name: "A*"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() Multiple",
+ runTest: function(datastore, t){
+ // summary:
+ // Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+ // description:
+ // Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+
+ var d = new doh.Deferred();
+ var done = [false, false];
+
+ function onCompleteOne(items, request){
+ done[0] = true;
+ t.assertEqual(items.length, 2);
+ if(done[0] && done[1]){
+ d.callback(true);
+ }
+ }
+ function onCompleteTwo(items, request){
+ done[1] = true;
+ if(done[0] && done[1]){
+ d.callback(true);
+ }
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ //Find all items starting with A, only toplevel (root) items.
+ store.fetch({ query: {name: "A*"},
+ onComplete: onCompleteOne,
+ onError: onError
+ });
+
+ //Find all items starting with A, only toplevel (root) items.
+ store.fetch({ query: {name: "N*"},
+ onComplete: onCompleteTwo,
+ onError: onError
+ });
+
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() MultipleMixedFetch",
+ runTest: function(datastore, t){
+ // summary:
+ // Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+ // description:
+ // Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+ // Tests an item fetch and an identity fetch.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ var done = [false, false];
+
+ function onComplete(items, request){
+ done[0] = true;
+ t.assertEqual(items.length, 1);
+ if(done[0] && done[1]){
+ d.callback(true);
+ }
+ }
+ function onItem(item){
+ done[1] = true;
+ t.assertTrue(item !== null);
+ var name = store.getValue(item,"name");
+ t.assertEqual(name, "El Salvador");
+
+ if(done[0] && done[1]){
+ d.callback(true);
+ }
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+
+ //Find all items starting with A, only toplevel (root) items.
+ store.fetch({ query: {name: "El*"},
+ onComplete: onComplete,
+ onError: onError
+ });
+
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() deep",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch on ItemFileReadStore of all items (including children (nested))
+ // description:
+ // Simple test of a basic fetch on ItemFileReadStore of all items (including children (nested))
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(items.length, 4);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ //Find all items starting with A, including child (nested) items.
+ store.fetch({ query: {name: "A*"},
+ onComplete: onComplete,
+ onError: onError,
+ queryOptions: {deep:true}
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() one_commentFilteredJson",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch on ItemFileReadStore of a single item.
+ // description:
+ // Simple test of a basic fetch on ItemFileReadStore of a single item.
+ // This tests loading a comment-filtered json file so that people using secure
+ // data with this store can bypass the JavaSceipt hijack noted in Fortify's
+ // paper.
+ if(dojo.isBrowser){
+ var store = new datastore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(items.length, 1);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query: {abbr: "ec"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ }
+ },
+ {
+ name: "Read API: fetch() withNull",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch on ItemFileReadStore of a single item where some attributes are null.
+ // description:
+ // Simple test of a basic fetch on ItemFileReadStore of a single item where some attributes are null.
+ // Introduced because of tracker: #3153
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withNull"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(4, items.length);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query: {name: "E*"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() all_streaming",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch on ItemFileReadStore.
+ // description:
+ // Simple test of a basic fetch on ItemFileReadStore.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ count = 0;
+
+ function onBegin(size, requestObj){
+ t.assertEqual(size, 7);
+ }
+ function onItem(item, requestObj){
+ t.assertTrue(store.isItem(item));
+ count++;
+ }
+ function onComplete(items, request){
+ t.assertEqual(count, 7);
+ t.assertTrue(items === null);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+
+ //Get everything...
+ store.fetch({ onBegin: onBegin,
+ onItem: onItem,
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() paging",
+ runTest: function(datastore, t){
+ // summary:
+ // Test of multiple fetches on a single result. Paging, if you will.
+ // description:
+ // Test of multiple fetches on a single result. Paging, if you will.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function dumpFirstFetch(items, request){
+ t.assertEqual(items.length, 5);
+ request.start = 3;
+ request.count = 1;
+ request.onComplete = dumpSecondFetch;
+ store.fetch(request);
+ }
+
+ function dumpSecondFetch(items, request){
+ t.assertEqual(items.length, 1);
+ request.start = 0;
+ request.count = 5;
+ request.onComplete = dumpThirdFetch;
+ store.fetch(request);
+ }
+
+ function dumpThirdFetch(items, request){
+ t.assertEqual(items.length, 5);
+ request.start = 2;
+ request.count = 20;
+ request.onComplete = dumpFourthFetch;
+ store.fetch(request);
+ }
+
+ function dumpFourthFetch(items, request){
+ t.assertEqual(items.length, 5);
+ request.start = 9;
+ request.count = 100;
+ request.onComplete = dumpFifthFetch;
+ store.fetch(request);
+ }
+
+ function dumpFifthFetch(items, request){
+ t.assertEqual(items.length, 0);
+ request.start = 2;
+ request.count = 20;
+ request.onComplete = dumpSixthFetch;
+ store.fetch(request);
+ }
+
+ function dumpSixthFetch(items, request){
+ t.assertEqual(items.length, 5);
+ d.callback(true);
+ }
+
+ function completed(items, request){
+ t.assertEqual(items.length, 7);
+ request.start = 1;
+ request.count = 5;
+ request.onComplete = dumpFirstFetch;
+ store.fetch(request);
+ }
+
+ function error(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({onComplete: completed, onError: error});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() with MultiType Match",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch againct an attribute that has different types for the value across items
+ // description:
+ // Simple test of a basic fetch againct an attribute that has different types for the value across items
+ // Introduced because of tracker: #4931
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("data_multitype"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(4, items.length);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query: {count: "1*"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() with MultiType, MultiValue Match",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of a basic fetch againct an attribute that has different types for the value across items
+ // description:
+ // Simple test of a basic fetch againct an attribute that has different types for the value across items
+ // Introduced because of tracker: #4931
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("data_multitype"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(7, items.length);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query: {value: "true"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: getLabel()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getLabel function against a store set that has a label defined.
+ // description:
+ // Simple test of the getLabel function against a store set that has a label defined.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(items.length, 1);
+ var label = store.getLabel(items[0]);
+ t.assertTrue(label !== null);
+ t.assertEqual("Ecuador", label);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query: {abbr: "ec"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: getLabelAttributes()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getLabelAttributes function against a store set that has a label defined.
+ // description:
+ // Simple test of the getLabelAttributes function against a store set that has a label defined.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(items.length, 1);
+ var labelList = store.getLabelAttributes(items[0]);
+ t.assertTrue(dojo.isArray(labelList));
+ t.assertEqual("name", labelList[0]);
+ d.callback(true);
+ }
+ function onError(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({ query: {abbr: "ec"},
+ onComplete: onComplete,
+ onError: onError
+ });
+ return d;
+ }
+ },
+ {
+ name: "Read API: getValue()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getValue function of the store.
+ // description:
+ // Simple test of the getValue function of the store.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var name = store.getValue(item,"name");
+ t.assertTrue(name === "El Salvador");
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: getValues()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getValues function of the store.
+ // description:
+ // Simple test of the getValues function of the store.
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var names = store.getValues(item,"name");
+ t.assertTrue(dojo.isArray(names));
+ t.assertEqual(names.length, 1);
+ t.assertEqual(names[0], "El Salvador");
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: isItem()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the isItem function of the store
+ // description:
+ // Simple test of the isItem function of the store
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ t.assertTrue(store.isItem(item));
+ t.assertTrue(!store.isItem({}));
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: isItem() multistore",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the isItem function of the store
+ // to verify two different store instances do not accept
+ // items from each other.
+ // description:
+ // Simple test of the isItem function of the store
+ // to verify two different store instances do not accept
+ // items from each other.
+
+ // Two different instances, even if they read from the same URL
+ // should not accept items between each other!
+ var store1 = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ var store2 = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem1(item1){
+ t.assertTrue(item1 !== null);
+
+ function onItem2(item2){
+ t.assertTrue(item1 !== null);
+ t.assertTrue(item2 !== null);
+ t.assertTrue(store1.isItem(item1));
+ t.assertTrue(store2.isItem(item2));
+ t.assertTrue(!store1.isItem(item2));
+ t.assertTrue(!store2.isItem(item1));
+ d.callback(true);
+ }
+ store2.fetchItemByIdentity({identity: "sv", onItem: onItem2, onError: onError});
+
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store1.fetchItemByIdentity({identity: "sv", onItem: onItem1, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: hasAttribute()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the hasAttribute function of the store
+ // description:
+ // Simple test of the hasAttribute function of the store
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ t.assertTrue(store.hasAttribute(item, "abbr"));
+ t.assertTrue(!store.hasAttribute(item, "abbr_not"));
+
+ //Test that null attributes throw an exception
+ var passed = false;
+ try{
+ store.hasAttribute(item, null);
+ }catch (e){
+ passed = true;
+ }
+ t.assertTrue(passed);
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: containsValue()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the containsValue function of the store
+ // description:
+ // Simple test of the containsValue function of the store
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ t.assertTrue(store.containsValue(item, "abbr", "sv"));
+ t.assertTrue(!store.containsValue(item, "abbr", "sv1"));
+ t.assertTrue(!store.containsValue(item, "abbr", null));
+
+ //Test that null attributes throw an exception
+ var passed = false;
+ try{
+ store.containsValue(item, null, "foo");
+ }catch (e){
+ passed = true;
+ }
+ t.assertTrue(passed);
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: getAttributes()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getAttributes function of the store
+ // description:
+ // Simple test of the getAttributes function of the store
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ t.assertTrue(store.isItem(item));
+
+ var attributes = store.getAttributes(item);
+ t.assertEqual(attributes.length, 3);
+ for(var i = 0; i < attributes.length; i++){
+ t.assertTrue((attributes[i] === "name" || attributes[i] === "abbr" || attributes[i] === "capital"));
+ }
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: getFeatures()",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the getFeatures function of the store
+ // description:
+ // Simple test of the getFeatures function of the store
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var features = store.getFeatures();
+ t.assertTrue(features["dojo.data.api.Read"] != null);
+ t.assertTrue(features["dojo.data.api.Identity"] != null);
+ }
+ },
+ {
+ name: "Read API: fetch() patternMatch0",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test pattern matching of everything starting with lowercase e
+ // description:
+ // Function to test pattern matching of everything starting with lowercase e
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+ var d = new doh.Deferred();
+ function completed(items, request) {
+ t.assertEqual(items.length, 5);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "abbr");
+ if(!(value === "ec" || value === "eg" || value === "er" || value === "ee" || value === "et")){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected abbreviation found, match failure."));
+ }
+ }
+ function error(error, request) {
+ t.assertTrue(false);
+ d.errback(error);
+ }
+ store.fetch({query: {abbr: "e*"}, onComplete: completed, onError: error});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() patternMatch1",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test pattern matching of everything with $ in it.
+ // description:
+ // Function to test pattern matching of everything with $ in it.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 1, value:"foo*bar"},
+ {uniqueId: 2, value:"bar*foo"},
+ {uniqueId: 3, value:"boomBam"},
+ {uniqueId: 4, value:"bit$Bite"},
+ {uniqueId: 5, value:"ouagadogou"},
+ {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+ {uniqueId: 7, value:"squawl"},
+ {uniqueId: 8, value:"seaweed"},
+ {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ t.assertEqual(items.length, 2);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(value === "bit$Bite" || value === "jfq4@#!$!@Rf14r14i5u")){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected pattern matched. Filter failure."));
+ }
+ }
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+ store.fetch({query: {value: "*$*"}, onComplete: completed, onError: error});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() patternMatch2",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test exact pattern match
+ // description:
+ // Function to test exact pattern match
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 1, value:"foo*bar"},
+ {uniqueId: 2, value:"bar*foo"},
+ {uniqueId: 3, value:"boomBam"},
+ {uniqueId: 4, value:"bit$Bite"},
+ {uniqueId: 5, value:"ouagadogou"},
+ {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+ {uniqueId: 7, value:"squawl"},
+ {uniqueId: 8, value:"seaweed"},
+ {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ t.assertEqual(items.length, 1);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(value === "bar*foo")){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected abbreviation found, match failure."));
+ }
+ }
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+ store.fetch({query: {value: "bar\*foo"}, onComplete: completed, onError: error});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() patternMatch_caseSensitive",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test pattern matching of a pattern case-sensitively
+ // description:
+ // Function to test pattern matching of a pattern case-sensitively
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 1, value:"foo*bar"},
+ {uniqueId: 2, value:"bar*foo"},
+ {uniqueId: 3, value:"BAR*foo"},
+ {uniqueId: 4, value:"BARBananafoo"}
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ t.assertEqual(1, items.length);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(value === "bar*foo")){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected pattern matched. Filter failure."));
+ }
+ }
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+ store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: false} , onComplete: completed, onError: error});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() patternMatch_caseInsensitive",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test pattern matching of a pattern case-insensitively
+ // description:
+ // Function to test pattern matching of a pattern case-insensitively
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 1, value:"foo*bar"},
+ {uniqueId: 2, value:"bar*foo"},
+ {uniqueId: 3, value:"BAR*foo"},
+ {uniqueId: 4, value:"BARBananafoo"}
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ t.assertEqual(items.length, 2);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(value === "BAR*foo" || value === "bar*foo")){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected pattern matched. Filter failure."));
+ }
+ }
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+ store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: true}, onComplete: completed, onError: error});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortNumeric",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting numerically.
+ // description:
+ // Function to test sorting numerically.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+ {uniqueId: 1, value:"ba|r*foo"},
+ {uniqueId: 2, value:"boomBam"},
+ {uniqueId: 3, value:"bit$Bite"},
+ {uniqueId: 4, value:"ouagadogou"},
+ {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+ {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+ {uniqueId: 7, value:"squawl"},
+ {uniqueId: 9, value:"seaweed"},
+ {uniqueId: 10, value:"zulu"},
+ {uniqueId: 8, value:"seaweed"}
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ t.assertEqual(items.length, 11);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(store.getValue(items[i], "uniqueId") === i)){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "uniqueId"}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortNumericDescending",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting numerically.
+ // description:
+ // Function to test sorting numerically.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+ {uniqueId: 1, value:"ba|r*foo"},
+ {uniqueId: 2, value:"boomBam"},
+ {uniqueId: 3, value:"bit$Bite"},
+ {uniqueId: 4, value:"ouagadogou"},
+ {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+ {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+ {uniqueId: 7, value:"squawl"},
+ {uniqueId: 9, value:"seaweed"},
+ {uniqueId: 10, value:"zulu"},
+ {uniqueId: 8, value:"seaweed"}
+ ]
+ }
+ });
+ var d = new doh.Deferred();
+ function completed(items, request){
+ t.assertEqual(items.length, 11);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!((items.length - (store.getValue(items[i], "uniqueId") + 1)) === i)){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "uniqueId", descending: true}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortNumericWithCount",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting numerically in descending order, returning only a specified number of them.
+ // description:
+ // Function to test sorting numerically in descending order, returning only a specified number of them.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+ {uniqueId: 1, value:"ba|r*foo"},
+ {uniqueId: 2, value:"boomBam"},
+ {uniqueId: 3, value:"bit$Bite"},
+ {uniqueId: 4, value:"ouagadogou"},
+ {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+ {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+ {uniqueId: 7, value:"squawl"},
+ {uniqueId: 9, value:"seaweed"},
+ {uniqueId: 10, value:"zulu"},
+ {uniqueId: 8, value:"seaweed"}
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ t.assertEqual(items.length, 5);
+ var itemId = 10;
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(store.getValue(items[i], "uniqueId") === itemId)){
+ passed=false;
+ break;
+ }
+ itemId--; // Decrement the item id. We are descending sorted, so it should go 10, 9, 8, etc.
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "uniqueId", descending: true}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes, count: 5});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortAlphabetic",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting alphabetic ordering.
+ // description:
+ // Function to test sorting alphabetic ordering.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value:"abc"},
+ {uniqueId: 1, value:"bca"},
+ {uniqueId: 2, value:"abcd"},
+ {uniqueId: 3, value:"abcdefg"},
+ {uniqueId: 4, value:"lmnop"},
+ {uniqueId: 5, value:"foghorn"},
+ {uniqueId: 6, value:"qberty"},
+ {uniqueId: 7, value:"qwerty"},
+ {uniqueId: 8, value:""},
+ {uniqueId: 9, value:"seaweed"},
+ {uniqueId: 10, value:"123abc"}
+
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ //Output should be in this order...
+ var orderedArray = [ "",
+ "123abc",
+ "abc",
+ "abcd",
+ "abcdefg",
+ "bca",
+ "foghorn",
+ "lmnop",
+ "qberty",
+ "qwerty",
+ "seaweed"
+ ];
+ t.assertEqual(items.length, 11);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(store.getValue(items[i], "value") === orderedArray[i])){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request) {
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "value"}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortAlphabeticDescending",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting alphabetic ordering in descending mode.
+ // description:
+ // Function to test sorting alphabetic ordering in descending mode.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value:"abc"},
+ {uniqueId: 1, value:"bca"},
+ {uniqueId: 2, value:"abcd"},
+ {uniqueId: 3, value:"abcdefg"},
+ {uniqueId: 4, value:"lmnop"},
+ {uniqueId: 5, value:"foghorn"},
+ {uniqueId: 6, value:"qberty"},
+ {uniqueId: 7, value:"qwerty"},
+ {uniqueId: 8, value:""},
+ {uniqueId: 9, value:"seaweed"},
+ {uniqueId: 10, value:"123abc"}
+
+ ]
+ }
+ });
+ var d = new doh.Deferred();
+ function completed(items, request){
+ //Output should be in this order...
+ var orderedArray = [ "",
+ "123abc",
+ "abc",
+ "abcd",
+ "abcdefg",
+ "bca",
+ "foghorn",
+ "lmnop",
+ "qberty",
+ "qwerty",
+ "seaweed"
+ ];
+ orderedArray = orderedArray.reverse();
+ t.assertEqual(items.length, 11);
+
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(store.getValue(items[i], "value") === orderedArray[i])){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request) {
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "value", descending: true}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortDate",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting date.
+ // description:
+ // Function to test sorting date.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value: new Date(0)},
+ {uniqueId: 1, value: new Date(100)},
+ {uniqueId: 2, value:new Date(1000)},
+ {uniqueId: 3, value:new Date(2000)},
+ {uniqueId: 4, value:new Date(3000)},
+ {uniqueId: 5, value:new Date(4000)},
+ {uniqueId: 6, value:new Date(5000)},
+ {uniqueId: 7, value:new Date(6000)},
+ {uniqueId: 8, value:new Date(7000)},
+ {uniqueId: 9, value:new Date(8000)},
+ {uniqueId: 10, value:new Date(9000)}
+
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items,request){
+ var orderedArray = [0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+ t.assertEqual(items.length, 11);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "value"}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortDateDescending",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting date in descending order.
+ // description:
+ // Function to test sorting date in descending order.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value: new Date(0)},
+ {uniqueId: 1, value: new Date(100)},
+ {uniqueId: 2, value:new Date(1000)},
+ {uniqueId: 3, value:new Date(2000)},
+ {uniqueId: 4, value:new Date(3000)},
+ {uniqueId: 5, value:new Date(4000)},
+ {uniqueId: 6, value:new Date(5000)},
+ {uniqueId: 7, value:new Date(6000)},
+ {uniqueId: 8, value:new Date(7000)},
+ {uniqueId: 9, value:new Date(8000)},
+ {uniqueId: 10, value:new Date(9000)}
+
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items,request){
+ var orderedArray = [0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+ orderedArray = orderedArray.reverse();
+ t.assertEqual(items.length, 11);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "value", descending: true}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortMultiple",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting on multiple attributes.
+ // description:
+ // Function to test sorting on multiple attributes.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 1, value:"fo|o*b.ar"},
+ {uniqueId: 2, value:"ba|r*foo"},
+ {uniqueId: 3, value:"boomBam"},
+ {uniqueId: 4, value:"bit$Bite"},
+ {uniqueId: 5, value:"ouagadogou"},
+ {uniqueId: 6, value:"jfq4@#!$!@|f1.$4r14i5u"},
+ {uniqueId: 7, value:"BaB{aMa|SaRa***F}oo"},
+ {uniqueId: 8, value:"squawl"},
+ {uniqueId: 10, value:"seaweed"},
+ {uniqueId: 12, value:"seaweed"},
+ {uniqueId: 11, value:"zulu"},
+ {uniqueId: 9, value:"seaweed"}
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ var orderedArray0 = [7,2,4,3,1,6,5,12,10,9,8,11];
+ var orderedArray1 = [ "BaB{aMa|SaRa***F}oo",
+ "ba|r*foo",
+ "bit$Bite",
+ "boomBam",
+ "fo|o*b.ar",
+ "jfq4@#!$!@|f1.$4r14i5u",
+ "ouagadogou",
+ "seaweed",
+ "seaweed",
+ "seaweed",
+ "squawl",
+ "zulu"
+ ];
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!( (store.getValue(items[i], "uniqueId") === orderedArray0[i])&&
+ (store.getValue(items[i], "value") === orderedArray1[i]))
+ ){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request){
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{ attribute: "value"}, { attribute: "uniqueId", descending: true}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortMultipleSpecialComparator",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting on multiple attributes with a custom comparator.
+ // description:
+ // Function to test sorting on multiple attributes with a custom comparator.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 1, status:"CLOSED"},
+ {uniqueId: 2, status:"OPEN"},
+ {uniqueId: 3, status:"PENDING"},
+ {uniqueId: 4, status:"BLOCKED"},
+ {uniqueId: 5, status:"CLOSED"},
+ {uniqueId: 6, status:"OPEN"},
+ {uniqueId: 7, status:"PENDING"},
+ {uniqueId: 8, status:"PENDING"},
+ {uniqueId: 10, status:"BLOCKED"},
+ {uniqueId: 12, status:"BLOCKED"},
+ {uniqueId: 11, status:"OPEN"},
+ {uniqueId: 9, status:"CLOSED"}
+ ]
+ }
+ });
+
+
+ store.comparatorMap = {};
+ store.comparatorMap["status"] = function(a,b) {
+ var ret = 0;
+ // We want to map these by what the priority of these items are, not by alphabetical.
+ // So, custom comparator.
+ var enumMap = { OPEN: 3, BLOCKED: 2, PENDING: 1, CLOSED: 0};
+ if (enumMap[a] > enumMap[b]) {
+ ret = 1;
+ }
+ if (enumMap[a] < enumMap[b]) {
+ ret = -1;
+ }
+ return ret;
+ };
+
+ var sortAttributes = [{attribute: "status", descending: true}, { attribute: "uniqueId", descending: true}];
+
+ var d = new doh.Deferred();
+ function completed(items, findResult){
+ var orderedArray = [11,6,2,12,10,4,8,7,3,9,5,1];
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ var value = store.getValue(items[i], "value");
+ if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(errData, request){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: fetch() sortAlphabeticWithUndefined",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test sorting alphabetic ordering.
+ // description:
+ // Function to test sorting alphabetic ordering.
+
+ var store = new datastore({data: { identifier: "uniqueId",
+ items: [ {uniqueId: 0, value:"abc"},
+ {uniqueId: 1, value:"bca"},
+ {uniqueId: 2, value:"abcd"},
+ {uniqueId: 3, value:"abcdefg"},
+ {uniqueId: 4, value:"lmnop"},
+ {uniqueId: 5, value:"foghorn"},
+ {uniqueId: 6, value:"qberty"},
+ {uniqueId: 7, value:"qwerty"},
+ {uniqueId: 8 }, //Deliberate undefined value
+ {uniqueId: 9, value:"seaweed"},
+ {uniqueId: 10, value:"123abc"}
+
+ ]
+ }
+ });
+
+ var d = new doh.Deferred();
+ function completed(items, request){
+ //Output should be in this order...
+ var orderedArray = [10,0,2,3,1,5,4,6,7,9,8];
+ t.assertEqual(items.length, 11);
+ var passed = true;
+ for(var i = 0; i < items.length; i++){
+ if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+ passed=false;
+ break;
+ }
+ }
+ t.assertTrue(passed);
+ if (passed){
+ d.callback(true);
+ }else{
+ d.errback(new Error("Unexpected sorting order found, sort failure."));
+ }
+ }
+
+ function error(error, request) {
+ t.assertTrue(false);
+ d.errback(error);
+ }
+
+ var sortAttributes = [{attribute: "value"}];
+ store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+ return d;
+ }
+ },
+ {
+ name: "Read API: errorCondition_idCollision_inMemory",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the errors thrown when there is an id collision in the data.
+ // Added because of tracker: #2546
+ // description:
+ // Simple test of the errors thrown when there is an id collision in the data.
+ // Added because of tracker: #2546
+
+ var store = new datastore({ data: { identifier: "uniqueId",
+ items: [{uniqueId: 12345, value:"foo"},
+ {uniqueId: 123456, value:"bar"},
+ {uniqueId: 12345, value:"boom"},
+ {uniqueId: 123457, value:"bit"}
+ ]
+ }
+ });
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ //This is bad if this fires, this case should fail and not call onComplete.
+ t.assertTrue(false);
+ d.callback(false);
+ }
+
+ function reportError(errData, request){
+ //This is good if this fires, it is expected.
+ t.assertTrue(true);
+ d.callback(true);
+ }
+ store.fetch({onComplete: onComplete, onError: reportError});
+ return d;
+ }
+ },
+ {
+ name: "Read API: errorCondition_idCollision_xhr",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test of the errors thrown when there is an id collision in the data.
+ // Added because of tracker: #2546
+ // description:
+ // Simple test of the errors thrown when there is an id collision in the data.
+ // Added because of tracker: #2546
+
+ if(dojo.isBrowser){
+ var store = new datastore({url: dojo.moduleUrl("tests", "data/countries_idcollision.json").toString() });
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ //This is bad if this fires, this case should fail and not call onComplete.
+ t.assertTrue(false);
+ d.callback(false);
+ }
+
+ function reportError(errData, request){
+ //This is good if this fires, it is expected.
+ t.assertTrue(true);
+ d.callback(true);
+ }
+ store.fetch({onComplete: onComplete, onError: reportError});
+ return d;
+ }
+ }
+ },
+ {
+ name: "Read API: Date_datatype",
+ runTest: function(datastore, t){
+ //var store = new datastore(tests.data.readOnlyItemFileTestTemplates.testFile["countries_withDates"]);
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withDates"));
+
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var independenceDate = store.getValue(item, "independence");
+ t.assertTrue(independenceDate instanceof Date);
+ //Check to see if the value was deserialized properly. Since the store stores in UTC/GMT, it
+ //should also be compared in the UTC/GMT mode
+ t.assertTrue(dojo.date.stamp.toISOString(independenceDate, {zulu:true}) === "1993-05-24T00:00:00Z");
+ d.callback(true);
+ }
+ function onError(errData){
+ t.assertTrue(false);
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity:"er", onItem:onItem, onError:onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: custom_datatype_Color_SimpleMapping",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test using literal values with custom datatypes
+ var dataset = {
+ identifier:'name',
+ items: [
+ { name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+ { name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+ ]
+ };
+ var store = new datastore({
+ data:dataset,
+ typeMap:{'Color': dojo.Color}
+ });
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var beaker = item;
+ var hairColor = store.getValue(beaker, "hairColor");
+ t.assertTrue(hairColor instanceof dojo.Color);
+ t.assertTrue(hairColor.toHex() == "#ff0000");
+ d.callback(true);
+ }
+ function onError(errData){
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: custom_datatype_Color_GeneralMapping",
+ runTest: function(datastore, t){
+ // summary:
+ // Function to test using literal values with custom datatypes
+ var dataset = {
+ identifier:'name',
+ items: [
+ { name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+ { name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+ ]
+ };
+ var store = new datastore({
+ data:dataset,
+ typeMap:{'Color': {
+ type: dojo.Color,
+ deserialize: function(value){
+ return new dojo.Color(value);
+ }
+ }
+ }
+ });
+ var d = new doh.Deferred();
+ function onItem(item){
+ t.assertTrue(item !== null);
+ var beaker = item;
+ var hairColor = store.getValue(beaker, "hairColor");
+ t.assertTrue(hairColor instanceof dojo.Color);
+ t.assertTrue(hairColor.toHex() == "#ff0000");
+ d.callback(true);
+ }
+ function onError(errData){
+ d.errback(errData);
+ }
+ store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: hierarchical_data",
+ runTest: function(datastore, t){
+ //var store = new datastore(tests.data.readOnlyItemFileTestTemplates.testFile["geography_hierarchy_small"]);
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ t.assertEqual(items.length, 1);
+ var northAmerica = items[0];
+ var canada = store.getValue(northAmerica, "countries");
+ var toronto = store.getValue(canada, "cities");
+ t.assertEqual(store.getValue(canada, "name"), "Canada");
+ t.assertEqual(store.getValue(toronto, "name"), "Toronto");
+ d.callback(true);
+ }
+ function onError(errData){
+ d.errback(errData);
+ }
+ store.fetch({
+ query: {name: "North America"},
+ onComplete: onComplete,
+ onError: onError
+ });
+
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: no_identifier_specified",
+ runTest: function(datastore, t){
+ var arrayOfItems = [
+ {name:"Kermit", color:"green"},
+ {name:"Miss Piggy", likes:"Kermit"},
+ {name:"Beaker", hairColor:"red"}
+ ];
+ var store = new datastore({data:{items:arrayOfItems}});
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ var features = store.getFeatures();
+ var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+ t.assertTrue(hasIdentityFeature);
+ for(var i = 0; i < items.length; ++i){
+ var item = items[i];
+ var identifier = store.getIdentityAttributes(item);
+ t.assertTrue(identifier === null);
+ var identity = store.getIdentity(item);
+ t.assertTrue(typeof identity == "number");
+ }
+ d.callback(true);
+ }
+ function reportError(errData, request){
+ d.errback(true);
+ }
+ store.fetch({onComplete: onComplete, onError: reportError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Identity API: hierarchical_data",
+ runTest: function(datastore, t){
+ var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+ var d = new doh.Deferred();
+ function onComplete(items, request){
+ var features = store.getFeatures();
+ var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+ t.assertTrue(hasIdentityFeature);
+ for(var i = 0; i < items.length; ++i){
+ var item = items[i];
+ var identifier = store.getIdentityAttributes(item);
+ t.assertTrue(identifier === null);
+ var identity = store.getIdentity(item);
+ t.assertTrue(typeof identity == "number");
+ }
+ d.callback(true);
+ }
+ function reportError(errData, request){
+ d.errback(true);
+ }
+ store.fetch({onComplete: onComplete, onError: reportError});
+ return d; // Deferred
+ }
+ },
+ {
+ name: "Read API: functionConformance",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test read API conformance. Checks to see all declared functions are actual functions on the instances.
+ // description:
+ // Simple test read API conformance. Checks to see all declared functions are actual functions on the instances.
+ var testStore = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ var readApi = new dojo.data.api.Read();
+ var passed = true;
+
+ for(i in readApi){
+ if(i.toString().charAt(0) !== '_')
+ {
+ var member = readApi[i];
+ //Check that all the 'Read' defined functions exist on the test store.
+ if(typeof member === "function"){
+ var testStoreMember = testStore[i];
+ if(!(typeof testStoreMember === "function")){
+ passed = false;
+ break;
+ }
+ }
+ }
+ }
+ t.assertTrue(passed);
+ }
+ },
+ {
+ name: "Identity API: functionConformance",
+ runTest: function(datastore, t){
+ // summary:
+ // Simple test identity API conformance. Checks to see all declared functions are actual functions on the instances.
+ // description:
+ // Simple test identity API conformance. Checks to see all declared functions are actual functions on the instances.
+ var testStore = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+ var identityApi = new dojo.data.api.Identity();
+ var passed = true;
+
+ for(i in identityApi){
+
+ if(i.toString().charAt(0) !== '_')
+ {
+ var member = identityApi[i];
+ //Check that all the 'Read' defined functions exist on the test store.
+ if(typeof member === "function"){
+ var testStoreMember = testStore[i];
+ if(!(typeof testStoreMember === "function")){
+ passed = false;
+ break;
+ }
+ }
+ }
+ }
+ t.assertTrue(passed);
+ }
+ }
+];
+
+
+}
diff --git a/includes/js/dojo/tests/data/reference_integrity.json b/includes/js/dojo/tests/data/reference_integrity.json
new file mode 100644
index 0000000..bdc6767
--- /dev/null
+++ b/includes/js/dojo/tests/data/reference_integrity.json
@@ -0,0 +1,27 @@
+/*
+{
+ "identifier": "id",
+ "label": "name",
+ "items":[
+ {"id": 1, "name": "Item 1"},
+ {"id": 2, "name": "Item 2"},
+ {"id": 3, "name": "Item 3"},
+ {"id": 4, "name": "Item 4"},
+ {"id": 5, "name": "Item 5"},
+ {"id": 6, "name": "Item 6"},
+ {"id": 7, "name": "Item 7"},
+ {"id": 8, "name": "Item 8"},
+ {"id": 9, "name": "Item 9"},
+ {"id": 10, "name": "Item 10", "friends": [{"_reference": 1},{"_reference": 3},{"_reference": 5}]},
+ {"id": 11, "name": "Item 11", "friends": [{"_reference": 10}], "siblings": [{"_reference": 10}]},
+ {"id": 12, "name": "Item 12", "friends": [{"_reference": 3},{"_reference": 7}], "enemies": [{"_reference": 10}]},
+ {"id": 13, "name": "Item 13", "friends": [{"_reference": 10}]},
+ {"id": 14, "name": "Item 14", "friends": [{"_reference": 11}]},
+ {"id": 15, "name": "item 15", "friends": [{"id": 16, "name": "Item 16"}]}
+ ]
+}
+*/
+
+
+
+
diff --git a/includes/js/dojo/tests/data/runTests.html b/includes/js/dojo/tests/data/runTests.html
new file mode 100644
index 0000000..ee3d473
--- /dev/null
+++ b/includes/js/dojo/tests/data/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <title>dojo.data D.O.H. Unit Test Runner</title>
+ <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=tests.data"></HEAD>
+ <BODY>
+ Redirecting to D.O.H runner.
+ </BODY>
+</HTML>
diff --git a/includes/js/dojo/tests/data/utils.js b/includes/js/dojo/tests/data/utils.js
new file mode 100644
index 0000000..8b26037
--- /dev/null
+++ b/includes/js/dojo/tests/data/utils.js
@@ -0,0 +1,203 @@
+if(!dojo._hasResource["tests.data.utils"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.data.utils"] = true;
+dojo.provide("tests.data.utils");
+dojo.require("dojo.data.util.filter");
+dojo.require("dojo.data.util.sorter");
+
+tests.register("tests.data.utils",
+ [
+ function testWildcardFilter_1(t){
+ var pattern = "ca*";
+ var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testWildcardFilter_2(t){
+ var pattern = "*ca";
+ var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testWildcardFilter_3(t){
+ var pattern = "*ca*";
+ var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testWildcardFilter_4(t){
+ //Try and match <anything>c<anything>a*b
+ var pattern = "*c*a\\*b*";
+ var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+ t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testWildcardFilter_5(t){
+ var pattern = "*c*a\\\\*b";
+ var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+ t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testWildcardFilter_caseInsensitive(t){
+ var pattern = "ca*";
+ var values = ["CA", "california", "Macca", "Macca*b", "Macca\\b"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+ t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+ },
+ function testSingleChar_1(t){
+ var pattern = "bob?le";
+ var values = ["bobble", "boble", "foo", "bobBle", "bar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testSingleChar_2(t){
+ var pattern = "?ob?le";
+ var values = ["bobble", "cob1le", "foo", "bobBle", "bar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testBracketChar(t){
+ //Make sure we don't treat this as regexp
+ var pattern = "*[*]*";
+ var values = ["bo[b]ble", "cob1le", "foo", "[bobBle]", "b[]ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testBraceChar(t){
+ //Make sure we don't treat this as regexp
+ var pattern = "*{*}*";
+ var values = ["bo{b}ble", "cob1le", "foo", "{bobBle}", "b{}ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testParenChar(t){
+ //Make sure we don't treat this as regexp
+ var pattern = "*(*)*";
+ var values = ["bo(b)ble", "cob1le", "foo", "{bobBle}", "b()ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testPlusChar(t){
+ //Make sure we don't treat this as regexp, so match anything with a + in it.
+ var pattern = "*+*";
+ var values = ["bo+ble", "cob1le", "foo", "{bobBle}", "b{}ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testPeriodChar(t){
+ //Make sure we don't treat this as regexp, so match anything with a period
+ var pattern = "*.*";
+ var values = ["bo.ble", "cob1le", "foo", "{bobBle}", "b{}ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testBarChar(t){
+ //Make sure we don't treat this as regexp, so match anything with a pipe bar
+ var pattern = "*|*";
+ var values = ["bo.ble", "cob|le", "foo", "{bobBle}", "b{}ar"];
+
+ t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testDollarSignChar(t){
+ //Make sure we don't treat this as regexp, so match anything with a $ in it
+ var pattern = "*$*";
+ var values = ["bo$ble", "cob$le", "foo", "{bobBle}", "b{}ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testCarrotChar(t){
+ //Make sure we don't treat this as regexp, so match anything with a ^ in it
+ var pattern = "*^*";
+ var values = ["bo$ble", "cob$le", "f^oo", "{bobBle}", "b{}ar"];
+
+ t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertTrue(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testEscapeChar(t){
+ //Make sure we escape properly, so match this single word.
+ var pattern = "bob\*ble";
+ var values = ["bob*ble", "cob$le", "f^oo", "{bobBle}", "b{}ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ },
+ function testAbsoluteMatch(t){
+ var pattern = "bobble";
+ var values = ["bobble", "cob$le", "f^oo", "{bobBle}", "b{}ar"];
+
+ t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+ }
+ ]
+);
+
+
+}
diff --git a/includes/js/dojo/tests/date.js b/includes/js/dojo/tests/date.js
new file mode 100644
index 0000000..57df0fd
--- /dev/null
+++ b/includes/js/dojo/tests/date.js
@@ -0,0 +1,716 @@
+if(!dojo._hasResource["tests.date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.date"] = true;
+dojo.provide("tests.date");
+
+dojo.require("dojo.date");
+
+tests.register("tests.date.util",
+ [
+
+/* Informational Functions
+ **************************/
+
+function test_date_getDaysInMonth(t){
+ // months other than February
+ t.is(31, dojo.date.getDaysInMonth(new Date(2006,0,1)));
+ t.is(31, dojo.date.getDaysInMonth(new Date(2006,2,1)));
+ t.is(30, dojo.date.getDaysInMonth(new Date(2006,3,1)));
+ t.is(31, dojo.date.getDaysInMonth(new Date(2006,4,1)));
+ t.is(30, dojo.date.getDaysInMonth(new Date(2006,5,1)));
+ t.is(31, dojo.date.getDaysInMonth(new Date(2006,6,1)));
+ t.is(31, dojo.date.getDaysInMonth(new Date(2006,7,1)));
+ t.is(30, dojo.date.getDaysInMonth(new Date(2006,8,1)));
+ t.is(31, dojo.date.getDaysInMonth(new Date(2006,9,1)));
+ t.is(30, dojo.date.getDaysInMonth(new Date(2006,10,1)));
+ t.is(31, dojo.date.getDaysInMonth(new Date(2006,11,1)));
+
+ // Februarys
+ t.is(28, dojo.date.getDaysInMonth(new Date(2006,1,1)));
+ t.is(29, dojo.date.getDaysInMonth(new Date(2004,1,1)));
+ t.is(29, dojo.date.getDaysInMonth(new Date(2000,1,1)));
+ t.is(28, dojo.date.getDaysInMonth(new Date(1900,1,1)));
+ t.is(28, dojo.date.getDaysInMonth(new Date(1800,1,1)));
+ t.is(28, dojo.date.getDaysInMonth(new Date(1700,1,1)));
+ t.is(29, dojo.date.getDaysInMonth(new Date(1600,1,1)));
+},
+
+function test_date_isLeapYear(t){
+ t.f(dojo.date.isLeapYear(new Date(2006,0,1)));
+ t.t(dojo.date.isLeapYear(new Date(2004,0,1)));
+ t.t(dojo.date.isLeapYear(new Date(2000,0,1)));
+ t.f(dojo.date.isLeapYear(new Date(1900,0,1)));
+ t.f(dojo.date.isLeapYear(new Date(1800,0,1)));
+ t.f(dojo.date.isLeapYear(new Date(1700,0,1)));
+ t.t(dojo.date.isLeapYear(new Date(1600,0,1)));
+},
+
+// The getTimezone function pulls from either the date's toString or
+// toLocaleString method -- it's really just a string-processing
+// function (assuming the Date obj passed in supporting both toString
+// and toLocaleString) and as such can be tested for multiple browsers
+// by manually settting up fake Date objects with the actual strings
+// produced by various browser/OS combinations.
+// FIXME: the function and tests are not localized.
+function test_date_getTimezoneName(t){
+
+ // Create a fake Date object with toString and toLocaleString
+ // results manually set to simulate tests for multiple browsers
+ function FakeDate(str, strLocale){
+ this.str = str || '';
+ this.strLocale = strLocale || '';
+ this.toString = function() {
+ return this.str;
+ };
+ this.toLocaleString = function(){
+ return this.strLocale;
+ };
+ }
+ var dt = new FakeDate();
+
+ // FF 1.5 Ubuntu Linux (Breezy)
+ dt.str = 'Sun Sep 17 2006 22:25:51 GMT-0500 (CDT)';
+ dt.strLocale = 'Sun 17 Sep 2006 10:25:51 PM CDT';
+ t.is('CDT', dojo.date.getTimezoneName(dt));
+
+ // Safari 2.0 Mac OS X 10.4
+ dt.str = 'Sun Sep 17 2006 22:55:01 GMT-0500';
+ dt.strLocale = 'September 17, 2006 10:55:01 PM CDT';
+ t.is('CDT', dojo.date.getTimezoneName(dt));
+
+ // FF 1.5 Mac OS X 10.4
+ dt.str = 'Sun Sep 17 2006 22:57:18 GMT-0500 (CDT)';
+ dt.strLocale = 'Sun Sep 17 22:57:18 2006';
+ t.is('CDT', dojo.date.getTimezoneName(dt));
+
+ // Opera 9 Mac OS X 10.4 -- no TZ data expect empty string return
+ dt.str = 'Sun, 17 Sep 2006 22:58:06 GMT-0500';
+ dt.strLocale = 'Sunday September 17, 22:58:06 GMT-0500 2006';
+ t.is('', dojo.date.getTimezoneName(dt));
+
+ // IE 6 Windows XP
+ dt.str = 'Mon Sep 18 11:21:07 CDT 2006';
+ dt.strLocale = 'Monday, September 18, 2006 11:21:07 AM';
+ t.is('CDT', dojo.date.getTimezoneName(dt));
+
+ // Opera 9 Ubuntu Linux (Breezy) -- no TZ data expect empty string return
+ dt.str = 'Mon, 18 Sep 2006 13:30:32 GMT-0500';
+ dt.strLocale = 'Monday September 18, 13:30:32 GMT-0500 2006';
+ t.is('', dojo.date.getTimezoneName(dt));
+
+ // IE 5.5 Windows 2000
+ dt.str = 'Mon Sep 18 13:49:22 CDT 2006';
+ dt.strLocale = 'Monday, September 18, 2006 1:49:22 PM';
+ t.is('CDT', dojo.date.getTimezoneName(dt));
+}
+ ]
+);
+
+tests.register("tests.date.math",
+ [
+function test_date_compare(t){
+ var d1=new Date();
+ d1.setHours(0);
+ var d2=new Date();
+ d2.setFullYear(2005);
+ d2.setHours(12);
+ t.is(0, dojo.date.compare(d1, d1));
+ t.is(1, dojo.date.compare(d1, d2, "date"));
+ t.is(-1, dojo.date.compare(d2, d1, "date"));
+ t.is(-1, dojo.date.compare(d1, d2, "time"));
+ t.is(1, dojo.date.compare(d1, d2, "datetime"));
+},
+function test_date_add(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+
+ interv = "year";
+ dtA = new Date(2005, 11, 27);
+ dtB = new Date(2006, 11, 27);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2005, 11, 27);
+ dtB = new Date(2004, 11, 27);
+ t.is(dtB, dojo.date.add(dtA, interv, -1));
+
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2001, 1, 28);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2005, 1, 28);
+ t.is(dtB, dojo.date.add(dtA, interv, 5));
+
+ dtA = new Date(1900, 11, 31);
+ dtB = new Date(1930, 11, 31);
+ t.is(dtB, dojo.date.add(dtA, interv, 30));
+
+ dtA = new Date(1995, 11, 31);
+ dtB = new Date(2030, 11, 31);
+ t.is(dtB, dojo.date.add(dtA, interv, 35));
+
+ interv = "quarter";
+ dtA = new Date(2000, 0, 1);
+ dtB = new Date(2000, 3, 1);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2000, 7, 29);
+ t.is(dtB, dojo.date.add(dtA, interv, 2));
+
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2001, 1, 28);
+ t.is(dtB, dojo.date.add(dtA, interv, 4));
+
+ interv = "month";
+ dtA = new Date(2000, 0, 1);
+ dtB = new Date(2000, 1, 1);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2000, 0, 31);
+ dtB = new Date(2000, 1, 29);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2001, 1, 28);
+ t.is(dtB, dojo.date.add(dtA, interv, 12));
+
+ interv = "week";
+ dtA = new Date(2000, 0, 1);
+ dtB = new Date(2000, 0, 8);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ interv = "day";
+ dtA = new Date(2000, 0, 1);
+ dtB = new Date(2000, 0, 2);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2001, 0, 1);
+ dtB = new Date(2002, 0, 1);
+ t.is(dtB, dojo.date.add(dtA, interv, 365));
+
+ dtA = new Date(2000, 0, 1);
+ dtB = new Date(2001, 0, 1);
+ t.is(dtB, dojo.date.add(dtA, interv, 366));
+
+ dtA = new Date(2000, 1, 28);
+ dtB = new Date(2000, 1, 29);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2001, 1, 28);
+ dtB = new Date(2001, 2, 1);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2000, 2, 1);
+ dtB = new Date(2000, 1, 29);
+ t.is(dtB, dojo.date.add(dtA, interv, -1));
+
+ dtA = new Date(2001, 2, 1);
+ dtB = new Date(2001, 1, 28);
+ t.is(dtB, dojo.date.add(dtA, interv, -1));
+
+ dtA = new Date(2000, 0, 1);
+ dtB = new Date(1999, 11, 31);
+ t.is(dtB, dojo.date.add(dtA, interv, -1));
+
+ interv = "weekday";
+ // Sat, Jan 1
+ dtA = new Date(2000, 0, 1);
+ // Should be Mon, Jan 3
+ dtB = new Date(2000, 0, 3);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ // Sun, Jan 2
+ dtA = new Date(2000, 0, 2);
+ // Should be Mon, Jan 3
+ dtB = new Date(2000, 0, 3);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ // Sun, Jan 2
+ dtA = new Date(2000, 0, 2);
+ // Should be Fri, Jan 7
+ dtB = new Date(2000, 0, 7);
+ t.is(dtB, dojo.date.add(dtA, interv, 5));
+
+ // Sun, Jan 2
+ dtA = new Date(2000, 0, 2);
+ // Should be Mon, Jan 10
+ dtB = new Date(2000, 0, 10);
+ t.is(dtB, dojo.date.add(dtA, interv, 6));
+
+ // Mon, Jan 3
+ dtA = new Date(2000, 0, 3);
+ // Should be Mon, Jan 17
+ dtB = new Date(2000, 0, 17);
+ t.is(dtB, dojo.date.add(dtA, interv, 10));
+
+ // Sat, Jan 8
+ dtA = new Date(2000, 0, 8);
+ // Should be Mon, Jan 3
+ dtB = new Date(2000, 0, 3);
+ t.is(dtB, dojo.date.add(dtA, interv, -5));
+
+ // Sun, Jan 9
+ dtA = new Date(2000, 0, 9);
+ // Should be Wed, Jan 5
+ dtB = new Date(2000, 0, 5);
+ t.is(dtB, dojo.date.add(dtA, interv, -3));
+
+ // Sun, Jan 23
+ dtA = new Date(2000, 0, 23);
+ // Should be Fri, Jan 7
+ dtB = new Date(2000, 0, 7);
+ t.is(dtB, dojo.date.add(dtA, interv, -11));
+
+ interv = "hour";
+ dtA = new Date(2000, 0, 1, 11);
+ dtB = new Date(2000, 0, 1, 12);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2001, 9, 28, 0);
+ dtB = new Date(dtA.getTime() + (60 * 60 * 1000));
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2001, 9, 28, 23);
+ dtB = new Date(2001, 9, 29, 0);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2001, 11, 31, 23);
+ dtB = new Date(2002, 0, 1, 0);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ interv = "minute";
+ dtA = new Date(2000, 11, 31, 23, 59);
+ dtB = new Date(2001, 0, 1, 0, 0);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2000, 11, 27, 12, 2);
+ dtB = new Date(2000, 11, 27, 13, 2);
+ t.is(dtB, dojo.date.add(dtA, interv, 60));
+
+ interv = "second";
+ dtA = new Date(2000, 11, 31, 23, 59, 59);
+ dtB = new Date(2001, 0, 1, 0, 0, 0);
+ t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+ dtA = new Date(2000, 11, 27, 8, 10, 59);
+ dtB = new Date(2000, 11, 27, 8, 11, 59);
+ t.is(dtB, dojo.date.add(dtA, interv, 60));
+
+ // Test environment JS Date doesn't support millisec?
+ //interv = "millisecond";
+ //
+ //dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
+ //dtB = new Date(2001, 0, 1, 0, 0, 0, 0);
+ //t.is(dtB, dojo.date.add(dtA, interv, 1));
+ //
+ //dtA = new Date(2000, 11, 27, 8, 10, 53, 2);
+ //dtB = new Date(2000, 11, 27, 8, 10, 54, 2);
+ //t.is(dtB, dojo.date.add(dtA, interv, 1000));
+},
+function test_date_diff(t){
+ var dtA = null; // First date to compare
+ var dtB = null; // Second date to compare
+ var interv = ''; // Interval to compare on (e.g., year, month)
+
+ interv = "year";
+ dtA = new Date(2005, 11, 27);
+ dtB = new Date(2006, 11, 27);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 11, 31);
+ dtB = new Date(2001, 0, 1);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "quarter";
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2001, 2, 1);
+ t.is(4, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 11, 1);
+ dtB = new Date(2001, 0, 1);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "month";
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2001, 2, 1);
+ t.is(13, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 11, 1);
+ dtB = new Date(2001, 0, 1);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "week";
+ dtA = new Date(2000, 1, 1);
+ dtB = new Date(2000, 1, 8);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 1, 28);
+ dtB = new Date(2000, 2, 6);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 2, 6);
+ dtB = new Date(2000, 1, 28);
+ t.is(-1, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "day";
+ dtA = new Date(2000, 1, 29);
+ dtB = new Date(2000, 2, 1);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 11, 31);
+ dtB = new Date(2001, 0, 1);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ // DST leap -- check for rounding err
+ // This is dependent on US calendar, but
+ // shouldn't break in other locales
+ dtA = new Date(2005, 3, 3);
+ dtB = new Date(2005, 3, 4);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "weekday";
+ dtA = new Date(2006, 7, 3);
+ dtB = new Date(2006, 7, 11);
+ t.is(6, dojo.date.difference(dtA, dtB, interv));
+
+ // Positive diffs
+ dtA = new Date(2006, 7, 4);
+ dtB = new Date(2006, 7, 11);
+ t.is(5, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 5);
+ dtB = new Date(2006, 7, 11);
+ t.is(5, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 6);
+ dtB = new Date(2006, 7, 11);
+ t.is(5, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 7);
+ dtB = new Date(2006, 7, 11);
+ t.is(4, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 7);
+ dtB = new Date(2006, 7, 13);
+ t.is(4, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 7);
+ dtB = new Date(2006, 7, 14);
+ t.is(5, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 7);
+ dtB = new Date(2006, 7, 15);
+ t.is(6, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 7);
+ dtB = new Date(2006, 7, 28);
+ t.is(15, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 2, 2);
+ dtB = new Date(2006, 2, 28);
+ t.is(18, dojo.date.difference(dtA, dtB, interv));
+
+ // Negative diffs
+ dtA = new Date(2006, 7, 11);
+ dtB = new Date(2006, 7, 4);
+ t.is(-5, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 11);
+ dtB = new Date(2006, 7, 5);
+ t.is(-4, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 11);
+ dtB = new Date(2006, 7, 6);
+ t.is(-4, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 11);
+ dtB = new Date(2006, 7, 7);
+ t.is(-4, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 13);
+ dtB = new Date(2006, 7, 7);
+ t.is(-5, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 14);
+ dtB = new Date(2006, 7, 7);
+ t.is(-5, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 15);
+ dtB = new Date(2006, 7, 7);
+ t.is(-6, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 7, 28);
+ dtB = new Date(2006, 7, 7);
+ t.is(-15, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2006, 2, 28);
+ dtB = new Date(2006, 2, 2);
+ t.is(-18, dojo.date.difference(dtA, dtB, interv));
+
+ // Two days on the same weekend -- no weekday diff
+ dtA = new Date(2006, 7, 5);
+ dtB = new Date(2006, 7, 6);
+ t.is(0, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "hour";
+ dtA = new Date(2000, 11, 31, 23);
+ dtB = new Date(2001, 0, 1, 0);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 11, 31, 12);
+ dtB = new Date(2001, 0, 1, 0);
+ t.is(12, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "minute";
+ dtA = new Date(2000, 11, 31, 23, 59);
+ dtB = new Date(2001, 0, 1, 0, 0);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 1, 28, 23, 59);
+ dtB = new Date(2000, 1, 29, 0, 0);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "second";
+ dtA = new Date(2000, 11, 31, 23, 59, 59);
+ dtB = new Date(2001, 0, 1, 0, 0, 0);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ interv = "millisecond";
+ dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
+ dtB = new Date(2001, 0, 1, 0, 0, 0, 0);
+ t.is(1, dojo.date.difference(dtA, dtB, interv));
+
+ dtA = new Date(2000, 11, 31, 23, 59, 59, 0);
+ dtB = new Date(2001, 0, 1, 0, 0, 0, 0);
+ t.is(1000, dojo.date.difference(dtA, dtB, interv));
+},
+function test_date_add_diff_year(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+
+ interv = "year";
+ dtA = new Date(2005, 11, 27);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2005, 11, 27);
+ dtB = dojo.date.add(dtA, interv, -1);
+ t.is(dojo.date.difference(dtA, dtB, interv), -1);
+
+ dtA = new Date(2000, 1, 29);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2000, 1, 29);
+ dtB = dojo.date.add(dtA, interv, 5);
+ t.is(dojo.date.difference(dtA, dtB, interv), 5);
+
+ dtA = new Date(1900, 11, 31);
+ dtB = dojo.date.add(dtA, interv, 30);
+ t.is(dojo.date.difference(dtA, dtB, interv), 30);
+
+ dtA = new Date(1995, 11, 31);
+ dtB = dojo.date.add(dtA, interv, 35);
+ t.is(dojo.date.difference(dtA, dtB, interv), 35);
+},
+function test_date_add_diff_quarter(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ interv = "quarter";
+ dtA = new Date(2000, 0, 1);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2000, 1, 29);
+ dtB = dojo.date.add(dtA, interv, 2);
+ t.is(dojo.date.difference(dtA, dtB, interv), 2);
+
+ dtA = new Date(2000, 1, 29);
+ dtB = dojo.date.add(dtA, interv, 4);
+ t.is(dojo.date.difference(dtA, dtB, interv), 4);
+},
+function test_date_add_diff_month(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ interv = "month";
+ dtA = new Date(2000, 0, 1);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2000, 0, 31);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2000, 1, 29);
+ dtB = dojo.date.add(dtA, interv, 12);
+ t.is(dojo.date.difference(dtA, dtB, interv), 12);
+},
+function test_date_add_diff_week(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ interv = "week";
+ dtA = new Date(2000, 0, 1);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+},
+function test_date_add_diff_day(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ interv = "day";
+ dtA = new Date(2000, 0, 1);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2001, 0, 1);
+ dtB = dojo.date.add(dtA, interv, 365);
+ t.is(dojo.date.difference(dtA, dtB, interv), 365);
+
+ dtA = new Date(2000, 0, 1);
+ dtB = dojo.date.add(dtA, interv, 366);
+ t.is(dojo.date.difference(dtA, dtB, interv), 366);
+
+ dtA = new Date(2000, 1, 28);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2001, 1, 28);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2000, 2, 1);
+ dtB = dojo.date.add(dtA, interv, -1);
+ t.is(dojo.date.difference(dtA, dtB, interv), -1);
+
+ dtA = new Date(2001, 2, 1);
+ dtB = dojo.date.add(dtA, interv, -1);
+ t.is(dojo.date.difference(dtA, dtB, interv), -1);
+
+ dtA = new Date(2000, 0, 1);
+ dtB = dojo.date.add(dtA, interv, -1);
+ t.is(dojo.date.difference(dtA, dtB, interv), -1);
+},
+function test_date_add_diff_weekday(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ interv = "weekday";
+ // Sat, Jan 1
+ dtA = new Date(2000, 0, 1);
+ // Should be Mon, Jan 3
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ // Sun, Jan 2
+ dtA = new Date(2000, 0, 2);
+ // Should be Mon, Jan 3
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ // Sun, Jan 2
+ dtA = new Date(2000, 0, 2);
+ // Should be Fri, Jan 7
+ dtB = dojo.date.add(dtA, interv, 5);
+ t.is(dojo.date.difference(dtA, dtB, interv), 5);
+
+ // Sun, Jan 2
+ dtA = new Date(2000, 0, 2);
+ // Should be Mon, Jan 10
+ dtB = dojo.date.add(dtA, interv, 6);
+ t.is(dojo.date.difference(dtA, dtB, interv), 6);
+
+ // Mon, Jan 3
+ dtA = new Date(2000, 0, 3);
+ // Should be Mon, Jan 17
+ dtB = dojo.date.add(dtA, interv, 10);
+ t.is(dojo.date.difference(dtA, dtB, interv), 10);
+
+ // Sat, Jan 8
+ dtA = new Date(2000, 0, 8);
+ // Should be Mon, Jan 3
+ dtB = dojo.date.add(dtA, interv, -5);
+ t.is(dojo.date.difference(dtA, dtB, interv), -5);
+
+ // Sun, Jan 9
+ dtA = new Date(2000, 0, 9);
+ // Should be Wed, Jan 5
+ dtB = dojo.date.add(dtA, interv, -3);
+ t.is(dojo.date.difference(dtA, dtB, interv), -3);
+
+ // Sun, Jan 23
+ dtA = new Date(2000, 0, 23);
+ // Should be Fri, Jan 7
+ dtB = dojo.date.add(dtA, interv, -11);
+ t.is(dojo.date.difference(dtA, dtB, interv), -11);
+},
+function test_date_add_diff_hour(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ interv = "hour";
+ dtA = new Date(2000, 0, 1, 11);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2001, 9, 28, 0);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2001, 9, 28, 23);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2001, 11, 31, 23);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+},
+function test_date_add_diff_minute(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ interv = "minute";
+ dtA = new Date(2000, 11, 31, 23, 59);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2000, 11, 27, 12, 2);
+ dtB = dojo.date.add(dtA, interv, 60);
+ t.is(dojo.date.difference(dtA, dtB, interv), 60);
+},
+function test_date_add_diff_second(t){
+ var interv = ''; // Interval (e.g., year, month)
+ var dtA = null; // Date to increment
+ var dtB = null; // Expected result date
+ console.debug("second");
+ interv = "second";
+ dtA = new Date(2000, 11, 31, 23, 59, 59);
+ dtB = dojo.date.add(dtA, interv, 1);
+ t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+ dtA = new Date(2000, 11, 27, 8, 10, 59);
+ dtB = dojo.date.add(dtA, interv, 60);
+ t.is(dojo.date.difference(dtA, dtB, interv), 60);
+
+ // Test environment JS Date doesn't support millisec?
+ //interv = "millisecond";
+ //
+ //dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
+ //dtB = dojo.date.add(dtA, interv, 1);
+ //t.is(dojo.date.difference(dtA, dtB, interv), 1);
+ //
+ //dtA = new Date(2000, 11, 27, 8, 10, 53, 2);
+ //dtB = dojo.date.add(dtA, interv, 1000);
+ //t.is(dojo.date.difference(dtA, dtB, interv), 1000);
+}
+ ]
+);
+
+dojo.require("tests.date.locale");
+dojo.require("tests.date.stamp");
+
+}
diff --git a/includes/js/dojo/tests/date/locale.js b/includes/js/dojo/tests/date/locale.js
new file mode 100644
index 0000000..77512a0
--- /dev/null
+++ b/includes/js/dojo/tests/date/locale.js
@@ -0,0 +1,398 @@
+if(!dojo._hasResource["tests.date.locale"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.date.locale"] = true;
+dojo.provide("tests.date.locale");
+
+dojo.require("dojo.date.locale");
+
+tests.register("tests.date.locale",
+ [
+ {
+ // Test formatting and parsing of dates in various locales pre-built in dojo.cldr
+ // NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+ // load resources here for specific locales:
+
+ name: "date.locale",
+ setUp: function(){
+ var partLocaleList = ["en-us", "fr-fr", "es", "de-at", "ja-jp", "zh-cn"];
+
+ dojo.forEach(partLocaleList, function(locale){
+ dojo.requireLocalization("dojo.cldr", "gregorian", locale, "zh-cn,zh,en-ca,ko-kr,pt,pt-br,it-it,ROOT,en-gb,de,ja,en,en-au,fr,es,ko,zh-tw,it,es-es");
+ });
+ },
+ runTest: function(t){
+ },
+ tearDown: function(){
+ //Clean up bundles that should not exist if
+ //the test is re-run.
+ delete dojo.cldr.nls.gregorian;
+ }
+ },
+ {
+ name: "isWeekend",
+ runTest: function(t){
+ var thursday = new Date(2006, 8, 21);
+ var friday = new Date(2006, 8, 22);
+ var saturday = new Date(2006, 8, 23);
+ var sunday = new Date(2006, 8, 24);
+ var monday = new Date(2006, 8, 25);
+ t.f(dojo.date.locale.isWeekend(thursday, 'en-us'));
+ t.t(dojo.date.locale.isWeekend(saturday, 'en-us'));
+ t.t(dojo.date.locale.isWeekend(sunday, 'en-us'));
+ t.f(dojo.date.locale.isWeekend(monday, 'en-us'));
+// t.f(dojo.date.locale.isWeekend(saturday, 'en-in'));
+// t.t(dojo.date.locale.isWeekend(sunday, 'en-in'));
+// t.f(dojo.date.locale.isWeekend(monday, 'en-in'));
+// t.t(dojo.date.locale.isWeekend(friday, 'he-il'));
+// t.f(dojo.date.locale.isWeekend(sunday, 'he-il'));
+ }
+ },
+ {
+ name: "format",
+ runTest: function(t){
+
+ var date = new Date(2006, 7, 11, 0, 55, 12, 345);
+
+ t.is("Friday, August 11, 2006", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'en-us'}));
+ t.is("vendredi 11 ao\xFBt 2006", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'fr-fr'}));
+ t.is("Freitag, 11. August 2006", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'de-at'}));
+ t.is("2006\u5E748\u670811\u65E5\u91D1\u66DC\u65E5", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'ja-jp'}));
+
+ t.is("8/11/06", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'en-us'}));
+ t.is("11/08/06", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'fr-fr'}));
+ t.is("11.08.06", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'de-at'}));
+ t.is("06/08/11", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'ja-jp'}));
+
+ t.is("12:55 AM", dojo.date.locale.format(date, {formatLength:'short',selector:'time', locale:'en-us'}));
+ t.is("12:55:12", dojo.date.locale.format(date, {timePattern:'h:m:s',selector:'time'}));
+ t.is("12:55:12.35", dojo.date.locale.format(date, {timePattern:'h:m:s.SS',selector:'time'}));
+ t.is("24:55:12.35", dojo.date.locale.format(date, {timePattern:'k:m:s.SS',selector:'time'}));
+ t.is("0:55:12.35", dojo.date.locale.format(date, {timePattern:'H:m:s.SS',selector:'time'}));
+ t.is("0:55:12.35", dojo.date.locale.format(date, {timePattern:'K:m:s.SS',selector:'time'}));
+
+ t.is("11082006", dojo.date.locale.format(date, {datePattern:"ddMMyyyy", selector:"date"}));
+
+ // compare without timezone
+ t.is("\u4e0a\u534812\u65f655\u520612\u79d2", dojo.date.locale.format(date, {formatLength:'full',selector:'time', locale:'zh-cn'}).split(' ')[0]);
+ }
+ },
+ {
+ name: "parse_dates",
+ runTest: function(t){
+
+ var aug_11_2006 = new Date(2006, 7, 11, 0);
+
+ //en: 'short' fmt: M/d/yy
+ // Tolerate either 8 or 08 for month part.
+ t.is( aug_11_2006, dojo.date.locale.parse("08/11/06", {formatLength:'short', selector:'date', locale:'en'}));
+ t.is( aug_11_2006, dojo.date.locale.parse("8/11/06", {formatLength:'short', selector:'date', locale:'en'}));
+ // Tolerate yyyy input in yy part...
+ t.is( aug_11_2006, dojo.date.locale.parse("8/11/2006", {formatLength:'short', selector:'date', locale:'en'}));
+ // ...but not in strict mode
+ t.f( Boolean(dojo.date.locale.parse("8/11/2006", {formatLength:'short', selector:'date', locale:'en', strict:true})));
+
+ //en: 'medium' fmt: MMM d, yyyy
+ // Tolerate either 8 or 08 for month part.
+ t.is( aug_11_2006, dojo.date.locale.parse("Aug 11, 2006", {formatLength:'medium', selector:'date', locale:'en'}));
+ t.is( aug_11_2006, dojo.date.locale.parse("Aug 11, 2006", {formatLength:'medium', selector:'date', locale:'en'}));
+ // Tolerate abbreviating period in month part...
+ t.is( aug_11_2006, dojo.date.locale.parse("Aug. 11, 2006", {formatLength:'medium', selector:'date', locale:'en'}));
+ // ...but not in strict mode
+ t.f( Boolean(dojo.date.locale.parse("Aug. 11, 2006", {formatLength:'medium', selector:'date', locale:'en', strict:true})));
+
+ // Note: 06 for year part will be translated literally as the year 6 C.E.
+ var aug_11_06CE = new Date(2006, 7, 11, 0);
+ aug_11_06CE.setFullYear(6); //literally the year 6 C.E.
+ t.is( aug_11_06CE, dojo.date.locale.parse("Aug 11, 06", {selector:'date', datePattern:'MMM dd, yyyy', strict:true}));
+
+ //en: 'long' fmt: MMMM d, yyyy
+ t.is( aug_11_2006, dojo.date.locale.parse("August 11, 2006", {formatLength:'long', selector:'date', locale:'en'}));
+
+ //en: 'full' fmt: EEEE, MMMM d, yyyy
+ t.is( aug_11_2006, dojo.date.locale.parse("Friday, August 11, 2006", {formatLength:'full', selector:'date', locale:'en'}));
+ //TODO: wrong day-of-week should fail
+ //t.f( Boolean(dojo.date.locale.parse("Thursday, August 11, 2006", {formatLength:'full', selector:'date', locale:'en'})));
+ //TODO: Whitespace tolerance
+ // t.is( aug_11_2006, dojo.date.locale.parse(" August 11, 2006", {formatLength:'long', selector:'date', locale:'en'}));
+ // t.is( aug_11_2006, dojo.date.locale.parse("August 11, 2006", {formatLength:'long', selector:'date', locale:'en'}));
+ // t.is( aug_11_2006, dojo.date.locale.parse("August 11 , 2006", {formatLength:'long', selector:'date', locale:'en'}));
+ // t.is( aug_11_2006, dojo.date.locale.parse("August 11, 2006", {formatLength:'long', selector:'date', locale:'en'}));
+ // t.is( aug_11_2006, dojo.date.locale.parse("August 11, 2006 ", {formatLength:'long', selector:'date', locale:'en'}));
+
+ //Simple Validation Tests
+ //catch "month" > 12 (note: month/day reversals are common when user expectation isn't met wrt european versus US formats)
+ t.f( Boolean(dojo.date.locale.parse("15/1/2005", {formatLength:'short', selector:'date', locale:'en'})));
+ //day of month typo rolls over to the next month
+ t.f( Boolean(dojo.date.locale.parse("Aug 32, 2006", {formatLength:'medium', selector:'date', locale:'en'})));
+
+ //German (de)
+ t.is( aug_11_2006, dojo.date.locale.parse("11.08.06", {formatLength:'short', selector:'date', locale:'de'}));
+ t.f( Boolean(dojo.date.locale.parse("11.8/06", {formatLength:'short', selector:'date', locale:'de'})));
+ t.f( Boolean(dojo.date.locale.parse("11.8x06", {formatLength:'short', selector:'date', locale:'de'})));
+ t.f( Boolean(dojo.date.locale.parse("11.13.06", {formatLength:'short', selector:'date', locale:'de'})));
+ t.f( Boolean(dojo.date.locale.parse("11.0.06", {formatLength:'short', selector:'date', locale:'de'})));
+ t.f( Boolean(dojo.date.locale.parse("32.08.06", {formatLength:'short', selector:'date', locale:'de'})));
+
+ //Spanish (es)
+ //es: 'short' fmt: d/MM/yy
+ t.is( aug_11_2006, dojo.date.locale.parse("11/08/06", {formatLength:'short', selector:'date', locale:'es'}));
+ t.is( aug_11_2006, dojo.date.locale.parse("11/8/06", {formatLength:'short', selector:'date', locale:'es'}));
+ // Tolerate yyyy input in yy part...
+ t.is( aug_11_2006, dojo.date.locale.parse("11/8/2006", {formatLength:'short', selector:'date', locale:'es'}));
+ // ...but not in strict mode
+ t.f( Boolean(dojo.date.locale.parse("11/8/2006", {formatLength:'short', selector:'date', locale:'es', strict:true})));
+ //es: 'medium' fmt: dd-MMM-yy (not anymore as of CLDR 1.5.1)
+// t.is( aug_11_2006, dojo.date.locale.parse("11-ago-06", {formatLength:'medium', selector:'date', locale:'es'}));
+// t.is( aug_11_2006, dojo.date.locale.parse("11-ago-2006", {formatLength:'medium', selector:'date', locale:'es'}));
+ // Tolerate abbreviating period in month part...
+// t.is( aug_11_2006, dojo.date.locale.parse("11-ago.-2006", {formatLength:'medium', selector:'date', locale:'es'}));
+ // ...but not in strict mode
+// t.f( Boolean(dojo.date.locale.parse("11-ago.-2006", {formatLength:'medium', selector:'date', locale:'es', strict:true})));
+ //es: 'long' fmt: d' de 'MMMM' de 'yyyy
+ t.is( aug_11_2006, dojo.date.locale.parse("11 de agosto de 2006", {formatLength:'long', selector:'date', locale:'es'}));
+ //case-insensitive month...
+ t.is( aug_11_2006, dojo.date.locale.parse("11 de Agosto de 2006", {formatLength:'long', selector:'date', locale:'es'}));
+ //...but not in strict mode
+ t.f( Boolean(dojo.date.locale.parse("11 de Agosto de 2006", {formatLength:'long', selector:'date', locale:'es', strict:true})));
+ //es 'full' fmt: EEEE d' de 'MMMM' de 'yyyy
+ t.is( aug_11_2006, dojo.date.locale.parse("viernes 11 de agosto de 2006", {formatLength:'full', selector:'date', locale:'es'}));
+ //case-insensitive day-of-week...
+ t.is( aug_11_2006, dojo.date.locale.parse("Viernes 11 de agosto de 2006", {formatLength:'full', selector:'date', locale:'es'}));
+ //...but not in strict mode
+ t.f( Boolean(dojo.date.locale.parse("Viernes 11 de agosto de 2006", {formatLength:'full', selector:'date', locale:'es', strict:true})));
+
+ //Japanese (ja)
+ //note: to avoid garbling from non-utf8-aware editors that may touch this file, using the \uNNNN format
+ //for expressing double-byte chars.
+ //toshi (year): \u5e74
+ //getsu (month): \u6708
+ //nichi (day): \u65e5
+ //kinyoubi (Friday): \u91d1\u66dc\u65e5
+ //zenkaku space: \u3000
+
+ //ja: 'short' fmt: yy/MM/dd (note: the "short" fmt isn't actually defined in the CLDR data...)
+ t.is( aug_11_2006, dojo.date.locale.parse("06/08/11", {formatLength:'short', selector:'date', locale:'ja'}));
+ t.is( aug_11_2006, dojo.date.locale.parse("06/8/11", {formatLength:'short', selector:'date', locale:'ja'}));
+ // Tolerate yyyy input in yy part...
+ t.is( aug_11_2006, dojo.date.locale.parse("2006/8/11", {formatLength:'short', selector:'date', locale:'ja'}));
+ // ...but not in strict mode
+ t.f( Boolean(dojo.date.locale.parse("2006/8/11", {formatLength:'short', selector:'date', locale:'ja', strict:true})));
+ //ja: 'medium' fmt: yyyy/MM/dd
+ t.is( aug_11_2006, dojo.date.locale.parse("2006/08/11", {formatLength:'medium', selector:'date', locale:'ja'}));
+ t.is( aug_11_2006, dojo.date.locale.parse("2006/8/11", {formatLength:'medium', selector:'date', locale:'ja'}));
+ //ja: 'long' fmt: yyyy'\u5e74'\u6708'd'\u65e5'
+ t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e748\u670811\u65e5", {formatLength:'long', selector:'date', locale:'ja'}));
+ //ja 'full' fmt: yyyy'\u5e74'M'\u6708'd'\u65e5'EEEE
+ t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e748\u670811\u65e5\u91d1\u66dc\u65e5", {formatLength:'full', selector:'date', locale:'ja'}));
+
+ //TODO: Whitespace tolerance
+ //tolerate ascii space
+ // t.is( aug_11_2006, dojo.date.locale.parse(" 2006\u5e748\u670811\u65e5\u91d1\u66dc\u65e5 ", {formatLength:'full', selector:'date', locale:'ja'}));
+ // t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e74 8\u670811\u65e5 \u91d1\u66dc\u65e5", {formatLength:'full', selector:'date', locale:'ja'}));
+ //tolerate zenkaku space
+ // t.is( aug_11_2006, dojo.date.locale.parse("\u30002006\u5e748\u670811\u65e5\u91d1\u66dc\u65e5\u3000", {formatLength:'full', selector:'date', locale:'ja'}));
+ // t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e74\u30008\u670811\u65e5\u3000\u91d1\u66dc\u65e5", {formatLength:'full', selector:'date', locale:'ja'}));
+
+ var apr_11_2006 = new Date(2006, 3, 11, 0);
+ //Roundtrip
+ var options={formatLength:'medium',selector:'date', locale:'fr-fr'};
+ t.is(0, dojo.date.compare(apr_11_2006, dojo.date.locale.parse(dojo.date.locale.format(apr_11_2006, options), options)));
+
+ //Tolerance for abbreviations
+ t.is(0, dojo.date.compare(apr_11_2006, dojo.date.locale.parse("11 avr 06", options)));
+ }
+ },
+ {
+ name: "parse_dates_neg",
+ runTest: function(t){
+ t.f(Boolean(dojo.date.locale.parse("2/29/2007", {formatLength: 'short', selector: 'date', locale: 'en'})));
+ t.f(Boolean(dojo.date.locale.parse("4/31/2007", {formatLength: 'short', selector: 'date', locale: 'en'})));
+ t.f(Boolean(dojo.date.locale.parse("Decemb 30, 2007", {formatLength: 'long', selector: 'date', locale: 'en'})));
+ }
+ },
+ {
+ name: "parse_datetimes",
+ runTest: function(t){
+
+ var aug_11_2006_12_30_am = new Date(2006, 7, 11, 0, 30);
+ var aug_11_2006_12_30_pm = new Date(2006, 7, 11, 12, 30);
+
+ //en: 'short' datetime fmt: M/d/yy h:mm a
+ //note: this is concatenation of dateFormat-short and timeFormat-short,
+ //cldr provisionally defines datetime fmts as well, but we're not using them at the moment
+ t.is( aug_11_2006_12_30_pm, dojo.date.locale.parse("08/11/06 12:30 PM", {formatLength:'short', locale:'en'}));
+ //case-insensitive
+ t.is( aug_11_2006_12_30_pm, dojo.date.locale.parse("08/11/06 12:30 pm", {formatLength:'short', locale:'en'}));
+ //...but not in strict mode
+ t.f( Boolean(dojo.date.locale.parse("08/11/06 12:30 pm", {formatLength:'short', locale:'en', strict:true})));
+
+ t.is( aug_11_2006_12_30_am, dojo.date.locale.parse("08/11/06 12:30 AM", {formatLength:'short', locale:'en'}));
+
+ t.is( new Date(2006, 7, 11), dojo.date.locale.parse("11082006", {datePattern:"ddMMyyyy", selector:"date"}));
+
+ }
+ },
+ {
+ name: "parse_times",
+ runTest: function(t){
+
+ var time = new Date(2006, 7, 11, 12, 30);
+ var tformat = {selector:'time', strict:true, timePattern:"h:mm a", locale:'en'};
+
+ t.is(time.getHours(), dojo.date.locale.parse("12:30 PM", tformat).getHours());
+ t.is(time.getMinutes(), dojo.date.locale.parse("12:30 PM", tformat).getMinutes());
+ }
+ },
+ {
+ name: "day_of_year",
+ runTest: function(t){
+
+// t.is(23, dojo.date.setDayOfYear(new Date(2006,0,1), 23).getDate());
+ t.is(1, dojo.date.locale._getDayOfYear(new Date(2006,0,1)));
+ t.is(32, dojo.date.locale._getDayOfYear(new Date(2006,1,1)));
+ t.is(72, dojo.date.locale._getDayOfYear(new Date(2007,2,13,0,13)));
+ t.is(72, dojo.date.locale._getDayOfYear(new Date(2007,2,13,1,13)));
+ }
+ },
+ {
+ name: "week_of_year",
+ runTest: function(t){
+ t.is(0, dojo.date.locale._getWeekOfYear(new Date(2000,0,1)));
+ t.is(1, dojo.date.locale._getWeekOfYear(new Date(2000,0,2)));
+ t.is(0, dojo.date.locale._getWeekOfYear(new Date(2000,0,2), 1));
+ t.is(0, dojo.date.locale._getWeekOfYear(new Date(2007,0,1)));
+ t.is(1, dojo.date.locale._getWeekOfYear(new Date(2007,0,1), 1));
+ t.is(27, dojo.date.locale._getWeekOfYear(new Date(2007,6,14)));
+ t.is(28, dojo.date.locale._getWeekOfYear(new Date(2007,6,14), 1));
+ }
+ }
+ ]
+);
+
+/*
+// workaround deprecated methods. Should decide whether we should convert the tests or add a helper method (in dojo.date?) to do this.
+
+dojo_validate_isValidTime = function(str, props){
+ props = props || {};
+ if(!props.format){props.format="h:mm:ss";}
+ if(!props.am){props.am="a.m.";}
+ if(!props.pm){props.pm="p.m.";}
+ var result = false;
+ if(/[hk]/.test(props.format) && props.format.indexOf('a') == -1){
+ result = dojo.date.locale.parse(str, {selector: 'time', timePattern: props.format + " a"});
+ }
+ return Boolean(result || dojo.date.locale.parse(str, {selector: 'time', timePattern: props.format}));
+}
+
+dojo_validate_is12HourTime = function(str){
+ return dojo_validate_isValidTime(str, {format: 'h:mm:ss'}) || dojo_validate_isValidTime(str, {format: 'h:mm'});
+}
+
+dojo_validate_is24HourTime = function(str){
+ return dojo_validate_isValidTime(str, {format: 'H:mm:ss'}) || dojo_validate_isValidTime(str, {format: 'H:mm'});
+}
+
+dojo_validate_isValidDate = function(str, fmt){
+ return Boolean(dojo.date.locale.parse(str, {selector: 'date', datePattern: fmt}));
+}
+
+function test_validate_datetime_isValidTime(){
+ jum.assertTrue("test1", dojo_validate_isValidTime('5:15:05 pm'));
+// FAILURE jum.assertTrue("test2", dojo_validate_isValidTime('5:15:05 p.m.', {pm: "P.M."} ));
+ jum.assertFalse("test3", dojo_validate_isValidTime('5:15:05 f.m.'));
+ jum.assertTrue("test4", dojo_validate_isValidTime('5:15 pm', {format: "h:mm a"} ) );
+ jum.assertFalse("test5", dojo_validate_isValidTime('5:15 fm', {}) );
+ jum.assertTrue("test6", dojo_validate_isValidTime('15:15:00', {format: "H:mm:ss"} ) );
+// FAILURE jum.assertFalse("test7", dojo_validate_isValidTime('15:15:00', {}) );
+ jum.assertTrue("test8", dojo_validate_isValidTime('17:01:30', {format: "H:mm:ss"} ) );
+ jum.assertFalse("test9", dojo_validate_isValidTime('17:1:30', {format: "H:mm:ss"} ) );
+// FAILURE jum.assertFalse("test10", dojo_validate_isValidTime('17:01:30', {format: "H:m:ss"} ) );
+ // Greek
+// FAILURE jum.assertTrue("test11", dojo_validate_isValidTime('5:01:30 \u0924\u0924', {am: "\u0928\u0924", pm: "\u0924\u0924"} ) );
+ // Italian
+ jum.assertTrue("test12", dojo_validate_isValidTime('17.01.30', {format: "H.mm.ss"} ) );
+ // Mexico
+// FAILURE jum.assertTrue("test13", dojo_validate_isValidTime('05:01:30 p.m.', {format: "hh:mm:ss a", am: "a.m.", pm: "p.m."} ) );
+}
+
+
+function test_validate_datetime_is12HourTime(){
+ jum.assertTrue("test1", dojo_validate_is12HourTime('5:15:05 pm'));
+// FAILURE jum.assertFalse("test2", dojo_validate_is12HourTime('05:15:05 pm'));
+ jum.assertFalse("test3", dojo_validate_is12HourTime('5:5:05 pm'));
+ jum.assertFalse("test4", dojo_validate_is12HourTime('5:15:5 pm'));
+// FAILURE jum.assertFalse("test5", dojo_validate_is12HourTime('13:15:05 pm'));
+ jum.assertFalse("test6", dojo_validate_is12HourTime('5:60:05 pm'));
+ jum.assertFalse("test7", dojo_validate_is12HourTime('5:15:60 pm'));
+ jum.assertTrue("test8", dojo_validate_is12HourTime('5:59:05 pm'));
+ jum.assertTrue("test9", dojo_validate_is12HourTime('5:15:59 pm'));
+// FAILURE jum.assertFalse("test10", dojo_validate_is12HourTime('5:15:05'));
+
+ // optional seconds
+ jum.assertTrue("test11", dojo_validate_is12HourTime('5:15 pm'));
+ jum.assertFalse("test12", dojo_validate_is12HourTime('5:15: pm'));
+}
+
+function test_validate_datetime_is24HourTime(){
+ jum.assertTrue("test1", dojo_validate_is24HourTime('00:03:59'));
+ jum.assertTrue("test2", dojo_validate_is24HourTime('22:03:59'));
+//FIXME: fix tests or code?
+// jum.assertFalse("test3", dojo_validate_is24HourTime('22:03:59 pm'));
+// jum.assertFalse("test4", dojo_validate_is24HourTime('2:03:59'));
+ jum.assertFalse("test5", dojo_validate_is24HourTime('0:3:59'));
+ jum.assertFalse("test6", dojo_validate_is24HourTime('00:03:5'));
+ jum.assertFalse("test7", dojo_validate_isValidTime('24:03:59', {format: 'kk:mm:ss'}));
+ jum.assertFalse("test8", dojo_validate_is24HourTime('02:60:59'));
+ jum.assertFalse("test9", dojo_validate_is24HourTime('02:03:60'));
+
+ // optional seconds
+ jum.assertTrue("test10", dojo_validate_is24HourTime('22:53'));
+ jum.assertFalse("test11", dojo_validate_is24HourTime('22:53:'));
+}
+
+function test_validate_datetime_isValidDate(){
+
+ // Month date year
+ jum.assertTrue("test1", dojo_validate_isValidDate("08/06/2005", "MM/dd/yyyy"));
+ jum.assertTrue("test2", dojo_validate_isValidDate("08.06.2005", "MM.dd.yyyy"));
+ jum.assertTrue("test3", dojo_validate_isValidDate("08-06-2005", "MM-dd-yyyy"));
+ jum.assertTrue("test4", dojo_validate_isValidDate("8/6/2005", "M/d/yyyy"));
+ jum.assertTrue("test5", dojo_validate_isValidDate("8/6", "M/d"));
+ jum.assertFalse("test6", dojo_validate_isValidDate("09/31/2005", "MM/dd/yyyy"));
+ jum.assertFalse("test7", dojo_validate_isValidDate("02/29/2005", "MM/dd/yyyy"));
+ jum.assertTrue("test8", dojo_validate_isValidDate("02/29/2004", "MM/dd/yyyy"));
+
+ // year month date
+ jum.assertTrue("test9", dojo_validate_isValidDate("2005-08-06", "yyyy-MM-dd"));
+ jum.assertTrue("test10", dojo_validate_isValidDate("20050806", "yyyyMMdd"));
+
+ // year month
+ jum.assertTrue("test11", dojo_validate_isValidDate("2005-08", "yyyy-MM"));
+ jum.assertTrue("test12", dojo_validate_isValidDate("200508", "yyyyMM"));
+
+ // year
+ jum.assertTrue("test13", dojo_validate_isValidDate("2005", "yyyy"));
+
+ // year week day
+//TODO: need to support 'w'?
+// jum.assertTrue("test14", dojo_validate_isValidDate("2005-W42-3", "yyyy-'W'ww-d"));
+// jum.assertTrue("test15", dojo_validate_isValidDate("2005W423", "yyyy'W'wwd"));
+// jum.assertFalse("test16", dojo_validate_isValidDate("2005-W42-8", "yyyy-'W'ww-d"));
+// jum.assertFalse("test17", dojo_validate_isValidDate("2005-W54-3", "yyyy-'W'ww-d"));
+
+ // year week
+// jum.assertTrue("test18", dojo_validate_isValidDate("2005-W42", "yyyy-'W'ww"));
+// jum.assertTrue("test19", dojo_validate_isValidDate("2005W42", "yyyy'W'ww"));
+
+ // year ordinal-day
+ jum.assertTrue("test20", dojo_validate_isValidDate("2005-292", "yyyy-DDD"));
+ jum.assertTrue("test21", dojo_validate_isValidDate("2005292", "yyyyDDD"));
+ jum.assertFalse("test22", dojo_validate_isValidDate("2005-366", "yyyy-DDD"));
+ jum.assertTrue("test23", dojo_validate_isValidDate("2004-366", "yyyy-DDD"));
+
+ // date month year
+ jum.assertTrue("test24", dojo_validate_isValidDate("19.10.2005", "dd.MM.yyyy"));
+ jum.assertTrue("test25", dojo_validate_isValidDate("19-10-2005", "d-M-yyyy"));
+}
+*/
+
+}
diff --git a/includes/js/dojo/tests/date/stamp.js b/includes/js/dojo/tests/date/stamp.js
new file mode 100644
index 0000000..88cf677
--- /dev/null
+++ b/includes/js/dojo/tests/date/stamp.js
@@ -0,0 +1,94 @@
+if(!dojo._hasResource["tests.date.stamp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.date.stamp"] = true;
+dojo.provide("tests.date.stamp");
+
+dojo.require("dojo.date.stamp");
+
+tests.register("tests.date.stamp",
+ [
+function test_date_iso(t){
+ var rfc = "2005-06-29T08:05:00-07:00";
+ var date = dojo.date.stamp.fromISOString(rfc);
+ t.is(2005,date.getFullYear());
+ t.is(5,date.getMonth());
+ t.is(29,date.getUTCDate());
+ t.is(15,date.getUTCHours());
+ t.is(5,date.getMinutes());
+ t.is(0,date.getSeconds());
+
+ rfc = "2004-02-29";
+ date = dojo.date.stamp.fromISOString(rfc);
+ t.is(2004,date.getFullYear());
+ t.is(1,date.getMonth());
+ t.is(29,date.getDate());
+
+ rfc = "2004-01";
+ date = dojo.date.stamp.fromISOString(rfc);
+ t.is(2004,date.getFullYear());
+ t.is(0,date.getMonth());
+ t.is(1,date.getDate());
+
+ // No TZ info means local time
+ rfc = "2004-02-29T01:23:45";
+ date = dojo.date.stamp.fromISOString(rfc);
+ t.is(2004,date.getFullYear());
+ t.is(1,date.getMonth());
+ t.is(29,date.getDate());
+ t.is(1,date.getHours());
+
+ date = new Date(2005,5,29,8,5,0);
+ rfc = dojo.date.stamp.toISOString(date);
+ //truncate for comparison
+ t.is("2005-06",rfc.substring(0,7));
+
+ date = new Date(101,0,2);
+ date.setFullYear(101);
+ rfc = dojo.date.stamp.toISOString(date);
+ //truncate for comparison
+ t.is("0101-01",rfc.substring(0,7));
+
+ rfc = "0101-01-01";
+ date = dojo.date.stamp.fromISOString(rfc);
+ t.is(101,date.getFullYear());
+ t.is(0,date.getMonth());
+ t.is(1,date.getDate());
+
+ date = dojo.date.stamp.fromISOString("T18:46:39");
+ t.is(18, date.getHours());
+ t.is(46, date.getMinutes());
+ t.is(39, date.getSeconds());
+},
+
+function test_date_iso_tz(t){
+
+ //23:59:59.9942 or 235959.9942
+// var date = dojo.date.stamp.fromISOString("T18:46:39.9942");
+// t.is(18, date.getHours());
+// t.is(46, date.getMinutes());
+// t.is(39, date.getSeconds());
+// t.is(994, date.getMilliseconds());
+
+ //1995-02-04 24:00 = 1995-02-05 00:00
+
+ //timezone tests
+ var offset = new Date().getTimezoneOffset()/60;
+ date = dojo.date.stamp.fromISOString("T18:46:39+07:00");
+ t.is(11, date.getUTCHours());
+
+ date = dojo.date.stamp.fromISOString("T18:46:39+00:00");
+ t.is(18, date.getUTCHours());
+
+ date = dojo.date.stamp.fromISOString("T18:46:39Z");
+ t.is(18, date.getUTCHours());
+
+ date = dojo.date.stamp.fromISOString("T16:46:39-07:00");
+ t.is(23, date.getUTCHours());
+
+ //+hh:mm, +hhmm, or +hh
+
+ //-hh:mm, -hhmm, or -hh
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/dnd/dndDefault.css b/includes/js/dojo/tests/dnd/dndDefault.css
new file mode 100644
index 0000000..eca2ef5
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/dndDefault.css
@@ -0,0 +1,52 @@
+
+.container {
+ border:3px solid #ccc;
+ padding: 1em 3em;
+ cursor: default;
+ radius:8pt;
+ background:#fff;
+ -moz-border-radius:8pt 8pt;
+}
+.dojoDndContainerOver {
+
+ border:3px solid #aaa;
+}
+.dojoDndItem {
+ padding:3px;
+}
+.dojoDndItemOver {
+ background: #ededed;
+ cursor:pointer;
+}
+.dojoDndItemSelected {
+ background: #ccf; color: #444;
+}
+.dojoDndItemAnchor {
+ background: #ccf; color: black;
+}
+.dojoDndItemOver .dojoDndItemSelected {
+ background: #ededed;
+}
+.dojoDndItemOver .dojoDndItemAnchor {
+ background: #ededed;
+}
+.dojoDndItemBefore {
+ border-top: 2px solid #369;
+}
+.dojoDndItemAfter {
+ border-bottom: 2px solid #369;
+}
+.dojoDndAvatar {
+ border:2px solid #ccc;
+ font-size: 75%;
+ -moz-border-radius:8pt 8pt;
+ radius:8pt;
+}
+
+.dojoDndAvatarHeader {
+ background: #aaa;
+}
+.dojoDndAvatarItem {
+ background: #fff;
+ border-bottom:1px solid #666;
+}
diff --git a/includes/js/dojo/tests/dnd/dndDefault.css.commented.css b/includes/js/dojo/tests/dnd/dndDefault.css.commented.css
new file mode 100644
index 0000000..cad410c
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/dndDefault.css.commented.css
@@ -0,0 +1,69 @@
+/*
+
+ there are basically all the classes you can set
+ for the various dojo.dnd states and elements in
+ their simplest form. hacking welcome.
+
+*/
+.container {
+ border:3px solid #ccc;
+ padding: 1em 3em;
+ cursor: default;
+ radius:8pt;
+ background:#fff;
+ -moz-border-radius:8pt 8pt;
+}
+
+.dojoDndContainerOver {
+ /* cursor:pointer; */
+ border:3px solid #aaa;
+}
+
+.dojoDndItem {
+ padding:3px;
+}
+
+.dojoDndItemOver {
+ background: #ededed;
+ cursor:pointer;
+}
+
+.dojoDndItemSelected {
+ background: #ccf; color: #444;
+}
+
+.dojoDndItemAnchor {
+ background: #ccf; color: black;
+}
+
+.dojoDndItemOver .dojoDndItemSelected {
+ background: #ededed;
+}
+
+.dojoDndItemOver .dojoDndItemAnchor {
+ background: #ededed;
+}
+
+.dojoDndItemBefore {
+ border-top: 2px solid #369;
+}
+
+.dojoDndItemAfter {
+ border-bottom: 2px solid #369;
+}
+
+.dojoDndAvatar {
+ border:2px solid #ccc;
+ font-size: 75%;
+ -moz-border-radius:8pt 8pt;
+ radius:8pt;
+}
+
+.dojoDndAvatarHeader {
+ background: #aaa;
+}
+
+.dojoDndAvatarItem {
+ background: #fff;
+ border-bottom:1px solid #666;
+}
diff --git a/includes/js/dojo/tests/dnd/flickr_viewer.html b/includes/js/dojo/tests/dnd/flickr_viewer.html
new file mode 100644
index 0000000..4ede297
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/flickr_viewer.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Sort Flickr images by tags</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "../../resources/dnd.css";
+ body {
+ padding: 1em;
+ }
+
+ /* application-specific settings */
+ #status {font-weight: bold;}
+ .container {padding: 5px; cursor: default; background: #f8f8ff;}
+ .wrap1 {float: left; width: 275px; height: 600px; overflow: auto; margin-right: 1em;}
+ .wrap1 div {min-height: 100px;}
+ .wrap2 {width: 350px; height: 170px; overflow: auto;}
+ .wrap2 div {min-height: 150px;}
+ .container .name {font-weight: bold; padding-right: 4px;}
+ .container .image {padding: 5px;}
+ body.dojoDndCopy, body.dojoDndMove {color: #888;}
+ .dojoDndCopy .container, .dojoDndMove .container {background: #ddf;}
+
+ /* container-specific settings */
+ .dojoDndContainer {border: 1px solid white; color: black;}
+ .dojoDndContainerOver {border: 1px solid black; color: black;}
+ .container.dojoDndTargetDisabled {background: #ccc; color: #888;}
+
+ /* item-specific settings */
+ .dojoDndItemOver {background: #feb;}
+ .dojoDndItemSelected {background: #ccf; color: #444;}
+ .dojoDndItemAnchor {background: #ccf; color: black;}
+ .dojoDndItemOver.dojoDndItemSelected {background: #ec8;}
+ .dojoDndItemOver.dojoDndItemAnchor {background: #ec8;}
+ .dojoDndItemBefore {border-top: 3px solid red;}
+ .dojoDndItemAfter {border-bottom: 3px solid red;}
+ .dojoDndHorizontal .dojoDndItemBefore {border-top: none;}
+ .dojoDndHorizontal .dojoDndItemAfter {border-bottom: none;}
+ .dojoDndHorizontal .dojoDndItemBefore img {border-left: 3px solid red;}
+ .dojoDndHorizontal .dojoDndItemAfter img {border-right: 3px solid red;}
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../dnd/common.js"></script>
+ <script type="text/javascript" src="../../dnd/autoscroll.js"></script>
+ <script type="text/javascript" src="../../dnd/Container.js"></script>
+ <script type="text/javascript" src="../../dnd/Selector.js"></script>
+ <script type="text/javascript" src="../../dnd/Source.js"></script>
+ <script type="text/javascript" src="../../dnd/Avatar.js"></script>
+ <script type="text/javascript" src="../../dnd/Manager.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojo.io.script");
+ dojo.require("dojo.dnd.Source");
+
+ // The main image container creator
+ var main_creator = function(item, hint){
+ var type = [];
+ if(item.tags.search(/cat/i) >= 0){ type.push("cat"); }
+ if(item.tags.search(/dog/i) >= 0){ type.push("dog"); }
+ var node;
+ if(hint == "avatar"){
+ node = dojo.doc.createElement("span");
+ node.innerHTML = "<img src='" + item.media.m.replace(/_m\./, "_s.") + "'/>";
+ }else{
+ var t = ["<table border='0' cellpadding='0' cellspacing='0' width='250'>"];
+ t.push("<tr><td colspan='2' class='image' align='center' width='250'><img src='" +
+ item.media.m + "'/></td></tr>");
+ t.push("<tr><td class='name' valign='top'>Title:</td><td class='value'><a href='" +
+ item.link + "' target='_blank'>" +
+ (item.title ? item.title : "<em>untitled</em>") + "</a></td></tr>");
+ t.push("<tr><td class='name' valign='top'>Author:</td><td class='value'>" +
+ item.author + "</td></tr>");
+ t.push("<tr><td class='name' valign='top'>Tags:</td><td class='value'>" +
+ item.tags + "</td></tr>");
+ t.push("</table>");
+ node = dojo.doc.createElement("div");
+ node.innerHTML = t.join("");
+ }
+ node.id = dojo.dnd.getUniqueId();
+ return {node: node, data: item, type: type};
+ };
+
+ // The band image container creator
+ var band_creator = function(item, hint){
+ var type = [];
+ if(item.tags.search(/cat/i) >= 0){ type.push("cat"); }
+ if(item.tags.search(/dog/i) >= 0){ type.push("dog"); }
+ var src = item.media.m.replace(/_m\./, "_s.");
+ var node = dojo.doc.createElement("span");
+ node.innerHTML = "<img src='" + src + "'/>";
+ node.id = dojo.dnd.getUniqueId();
+ return {node: node, data: item, type: type};
+ };
+
+ // Flickr's JSONP function
+ var jsonFlickrFeed = function(data){
+ if(!data.items || !data.items.length){
+ dojo.byId("status").innerHTML = "Flickr didn't return any images";
+ return;
+ }
+ dojo.byId("status").innerHTML = data.items.length + " images were retrieved";
+ // initialize sources
+ c1.selectAll().deleteSelectedNodes();
+ c2.selectAll().deleteSelectedNodes();
+ c3.selectAll().deleteSelectedNodes();
+ // populate the main source
+ c1.insertNodes(false, data.items);
+ };
+
+ var init = function(){
+ // replace the avatar string to make it more human readable
+ dojo.dnd.Avatar.prototype._generateText = function(){
+ return (this.manager.copy ? "copy" : "mov") +
+ "ing " + this.manager.nodes.length + " item" +
+ (this.manager.nodes.length != 1 ? "s" : "");
+ };
+ // ask Flickr for images
+ var td = dojo.io.script.get({
+ url: "http://api.flickr.com/services/feeds/photos_public.gne",
+ content: {tags: "cat,dog,cow", tagmode: "any", format: "json"},
+ handleAs: "text/javascript",
+ preventCache: true
+ });
+ td.addErrback(function(){
+ dojo.byId("status").innerHTML = "Flickr failed to return images";
+ });
+ };
+
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Sort Flickr images by tags</h1>
+ <p>This simple web application retrieves public images from Flickr that were tagged either as "cat", "dog", or "cow".
+ You can copy/move images in different containers according to their tags.</p>
+ <p>Following selection modes are supported by default:</p>
+ <ul>
+ <li>Simple click &mdash; selects a single element, all other elements will be unselected.</li>
+ <li>Ctrl+click &mdash; toggles a selection state of an element (use Meta key on Mac).</li>
+ <li>Shift+click &mdash; selects a range of element from the previous anchor to the current element.</li>
+ <li>Ctrl+Shift+click &mdash; adds a range of element from the previous anchor to the current element (use Meta key on Mac).</li>
+ </ul>
+ <p>Following drop modes are supported by default:</p>
+ <ul>
+ <li>Simple drop &mdash; moves elements to the valid target removing them from the source. It can be used to reorganize elements within a single source/target.</li>
+ <li>Ctrl+drop &mdash; copies elements to the valid target (use Meta key on Mac).</li>
+ </ul>
+ <p>Now scroll down and start dragging and dropping, rearrange images using DnD, copy and move them back!</p>
+ <p>Status: <span id="status">retrieving a list of Flickr images...</span></p>
+ <div class="wrap1">
+ <div dojoType="dojo.dnd.Source" jsId="c1" accept="cat, dog, cow" class="container">
+ <script type="dojo/method" event="creator" args="item, hint">return main_creator(item, hint);</script>
+ </div>
+ </div>
+ <p>Tag: cat</p>
+ <div class="wrap2">
+ <div dojoType="dojo.dnd.Source" jsId="c2" accept="cat" horizontal="true" class="container">
+ <script type="dojo/method" event="creator" args="item, hint">return band_creator(item, hint);</script>
+ </div>
+ </div>
+ <p>Tag: dog</p>
+ <div class="wrap2">
+ <div dojoType="dojo.dnd.Source" jsId="c3" accept="dog" horizontal="true" class="container">
+ <script type="dojo/method" event="creator" args="item, hint">return band_creator(item, hint);</script>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_box_constraints.html b/includes/js/dojo/tests/dnd/test_box_constraints.html
new file mode 100644
index 0000000..85a5033
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_box_constraints.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo box constraint test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 1em;
+ }
+
+ .moveable {
+ background: #FFFFBF;
+ border: 1px solid black;
+ width: 300px;
+ padding: 10px 20px;
+ cursor: pointer;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojo.dnd.move");
+ var m5, m6;
+ var init = function(){
+ m5 = new dojo.dnd.move.boxConstrainedMoveable("moveable5", {box: {l: 100, t: 100, w: 500, h: 500}});
+ m6 = new dojo.dnd.move.boxConstrainedMoveable("moveable6", {box: {l: 100, t: 100, w: 500, h: 500}, within: true});
+
+ // system-wide topics
+ dojo.subscribe("/dnd/move/start", function(node){
+ console.debug("Start move", node);
+ });
+ dojo.subscribe("/dnd/move/stop", function(node){
+ console.debug("Stop move", node);
+ });
+
+ // watching a particular moveable instance
+ dojo.connect(m5, "onDndMoveStart", function(mover){
+ console.debug("Start moving m5 with this mover:", mover);
+ });
+ dojo.connect(m5, "onDndMoveStop", function(mover){
+ console.debug("Stop moving m5 with this mover:", mover);
+ });
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo box constraint test</h1>
+ <p class="moveable" id="moveable5"><strong>Paragraph restricted to (100,100:500,500) box:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo justo, pellentesque sit amet, tristique sed, tempor eu, felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam scelerisque velit vel sem. Curabitur vulputate. Morbi pretium porta dui.</p>
+ <p class="moveable" id="moveable6"><strong>Paragraph restricted to (100,100:500,500) box, it cannot go outside of this box:</strong> In hac habitasse platea dictumst. Etiam rhoncus, leo quis hendrerit vestibulum, ipsum felis porta massa, vitae posuere nunc lorem ac enim. Nam neque turpis, aliquet quis, sollicitudin sit amet, dapibus sed, eros. Duis volutpat porttitor velit. Vivamus nibh metus, iaculis eget, malesuada eget, facilisis id, lorem. Sed turpis. Vestibulum aliquam mauris. Integer malesuada tellus vel neque. In hac habitasse platea dictumst. Aliquam at lectus. Maecenas nonummy cursus nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi imperdiet purus eu ipsum. Curabitur sapien felis, euismod eu, dapibus vel, tempor vitae, pede. Suspendisse blandit. Nulla imperdiet. Duis placerat nulla ultricies sem. In in mi nec ipsum molestie tempor. Sed scelerisque.</p>
+ <p class="moveable" dojoType="dojo.dnd.move.boxConstrainedMoveable" box="{l: 100, t: 100, w: 500, h: 500}"><strong>Marked up paragraph restricted to (100,100:500,500) box:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo justo, pellentesque sit amet, tristique sed, tempor eu, felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam scelerisque velit vel sem. Curabitur vulputate. Morbi pretium porta dui.
+ </p>
+ <p class="moveable" dojoType="dojo.dnd.Moveable"><strong>Marked up paragraph restricted to (100,100:500,500) box, it cannot go outside of this box:</strong> In hac habitasse platea dictumst. Etiam rhoncus, leo quis hendrerit vestibulum, ipsum felis porta massa, vitae posuere nunc lorem ac enim. Nam neque turpis, aliquet quis, sollicitudin sit amet, dapibus sed, eros. Duis volutpat porttitor velit. Vivamus nibh metus, iaculis eget, malesuada eget, facilisis id, lorem. Sed turpis. Vestibulum aliquam mauris. Integer malesuada tellus vel neque. In hac habitasse platea dictumst. Aliquam at lectus. Maecenas nonummy cursus nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi imperdiet purus eu ipsum. Curabitur sapien felis, euismod eu, dapibus vel, tempor vitae, pede. Suspendisse blandit. Nulla imperdiet. Duis placerat nulla ultricies sem. In in mi nec ipsum molestie tempor. Sed scelerisque.
+ <!-- this is the obsolete way to do it -->
+ <script type="dojo/method">this.mover = dojo.dnd.boxConstrainedMover({l: 100, t: 100, w: 500, h: 500}, true);</script>
+ </p>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_container.html b/includes/js/dojo/tests/dnd/test_container.html
new file mode 100644
index 0000000..352aa7a
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_container.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Dojo DnD container test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 20px;
+ }
+
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/Container.js"></script>
+ <script type="text/javascript">
+ // dojo.require("dojo.dnd.Container");
+ var c1, c2, c3, c4, c5;
+ var init = function(){
+ c1 = new dojo.dnd.Container(dojo.byId("container1"));
+ c2 = new dojo.dnd.Container(dojo.byId("container2"));
+ c3 = new dojo.dnd.Container(dojo.byId("container3"));
+ c4 = new dojo.dnd.Container(dojo.byId("container4"));
+ c5 = new dojo.dnd.Container(dojo.byId("container5"));
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo DnD container test</h1>
+ <p>Containers have a notion of a "current container", and one element can be "current".</p>
+ <p>see <a href="dndDefault.css">dndDefault.css</a> for example styling</p>
+ <h2>DIV container</h2>
+ <div id="container1" class="container">
+ <div class="dojoDndItem">Item 1</div>
+ <div class="dojoDndItem">Item 2</div>
+ <div class="dojoDndItem">Item 3</div>
+ </div>
+ <h2>UL container</h2>
+ <ul id="container2" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ul>
+ <h2>OL container</h2>
+ <ol id="container3" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ol>
+ <h2>TABLE container</h2>
+ <table id="container4" class="container" border="1px solid black">
+ <tr class="dojoDndItem">
+ <td>A</td>
+ <td>row 1</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>B</td>
+ <td>row 2</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>C</td>
+ <td>row 3</td>
+ </tr>
+ </table>
+ <h2>P container with SPAN elements</h2>
+ <p>Elements of this container are layed out horizontally.</p>
+ <p id="container5" class="container">
+ <span class="dojoDndItem">&nbsp;Item 1&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 2&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 3&nbsp;</span>
+ </p>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_container_markup.html b/includes/js/dojo/tests/dnd/test_container_markup.html
new file mode 100644
index 0000000..4bde544
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_container_markup.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Dojo DnD markup container test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 20px;
+ }
+
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../dnd/Container.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojo.dnd.Container");
+ </script>
+</head>
+<body>
+ <h1>Dojo DnD markup container test</h1>
+ <p>This example is functionally equivalent to <a href="test_container.html">test_container.html</a> example but is done using the Dojo markup.</p>
+ <p>Containers have a notion of a "current container", and one element can be "current".</p>
+ <p>See <a href="dndDefault.css">dndDefault.css</a> for example styling</p>
+ <h2>DIV container</h2>
+ <div dojoType="dojo.dnd.Container" jsId="c1" class="container">
+ <div class="dojoDndItem">Item 1</div>
+ <div class="dojoDndItem">Item 2</div>
+ <div class="dojoDndItem">Item 3</div>
+ </div>
+ <h2>UL container</h2>
+ <ul dojoType="dojo.dnd.Container" jsId="c2" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ul>
+ <h2>OL container</h2>
+ <ol dojoType="dojo.dnd.Container" jsId="c3" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ol>
+ <h2>TABLE container</h2>
+ <table dojoType="dojo.dnd.Container" jsId="c4" class="container" border="1px solid black">
+ <tr class="dojoDndItem">
+ <td>A</td>
+ <td>row 1</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>B</td>
+ <td>row 2</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>C</td>
+ <td>row 3</td>
+ </tr>
+ </table>
+ <h2>P container with SPAN elements</h2>
+ <p>Elements of this container are layed out horizontally.</p>
+ <p dojoType="dojo.dnd.Container" jsId="c5" class="container">
+ <span class="dojoDndItem">&nbsp;Item 1&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 2&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 3&nbsp;</span>
+ </p>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_custom_constraints.html b/includes/js/dojo/tests/dnd/test_custom_constraints.html
new file mode 100644
index 0000000..9140914
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_custom_constraints.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo custom constraint test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+
+ body {
+ padding: 1em;
+ }
+
+ .moveable {
+ background: #FFFFBF;
+ border: 1px solid black;
+ width: 300px;
+ padding: 10px 20px;
+ margin: 0px;
+ cursor: pointer;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.dnd.move");
+
+ var STEP = 50;
+
+ var init = function(){
+ // 1st way
+ var m1 = new dojo.dnd.Moveable("moveable1");
+ m1.onMove = function(mover, leftTop){
+ leftTop.l -= leftTop.l % STEP;
+ leftTop.t -= leftTop.t % STEP;
+ dojo.marginBox(mover.node, leftTop);
+ };
+ // 2nd way
+ var m2 = new dojo.dnd.Moveable("moveable2");
+ dojo.connect(m2, "onMoving", function(mover, leftTop){
+ leftTop.l -= leftTop.l % STEP;
+ leftTop.t -= leftTop.t % STEP;
+ });
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo custom constraint test</h1>
+ <p class="moveable" id="moveable1"><strong>This paragraph stops at 50x50 grid knots:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo justo, pellentesque sit amet, tristique sed, tempor eu, felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam scelerisque velit vel sem. Curabitur vulputate. Morbi pretium porta dui.</p>
+ <p class="moveable" id="moveable2"><strong>This paragraph stops at 50x50 grid knots:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo justo, pellentesque sit amet, tristique sed, tempor eu, felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam scelerisque velit vel sem. Curabitur vulputate. Morbi pretium porta dui.</p>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_dnd.html b/includes/js/dojo/tests/dnd/test_dnd.html
new file mode 100644
index 0000000..7e2a56a
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_dnd.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Dojo DnD test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "../../resources/dnd.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 1em;
+ background: #ededed;
+ }
+
+ .container {
+ width: 100px;
+ display: block;
+ }
+
+ .clear {
+ clear: both;
+ }
+ </style>
+
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+ <script type="text/javascript" src="../../dnd/Container.js"></script>
+ <script type="text/javascript" src="../../dnd/Selector.js"></script>
+ <script type="text/javascript" src="../../dnd/Source.js"></script>
+ <script type="text/javascript" src="../../dnd/Avatar.js"></script>
+ <script type="text/javascript" src="../../dnd/Manager.js"></script>
+
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojo.dnd.Source");
+
+ var c1;
+
+ function init(){
+ c1 = new dojo.dnd.Source("container1");
+ c1.insertNodes(false, [1, "A", [1, 2, 3],
+ function(x){ return x + x; },
+ {toString: function(){ return "CUSTOM!"; }},
+ null]);
+
+ // example subscribe to events
+ dojo.subscribe("/dnd/start", function(source){
+ console.debug("Starting the drop", source);
+ });
+ dojo.subscribe("/dnd/drop/before", function(source, nodes, copy, target){
+ if(target == c1){
+ console.debug(copy ? "Copying from" : "Moving from", source, "to", target, "before", target.before);
+ }
+ });
+ dojo.subscribe("/dnd/drop", function(source, nodes, copy, target){
+ if(target == c1){
+ console.debug(copy ? "Copying from" : "Moving from", source, "to", target, "before", target.before);
+ }
+ });
+ dojo.connect(c4, "onDndDrop", function(source, nodes, copy, target){
+ if(target == c4){
+ console.debug(copy ? "Copying from" : "Moving from", source);
+ }
+ });
+ };
+
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1 class="testTitle">Dojo DnD test</h1>
+
+ <p>Elements of both sources/targets were created dynamically.</p>
+ <p>Following selection modes are supported by default:</p>
+ <ul>
+ <li>Simple click &mdash; selects a single element, all other elements will be unselected.</li>
+ <li>Ctrl+click &mdash; toggles a selection state of an element (use Meta key on Mac).</li>
+ <li>Shift+click &mdash; selects a range of element from the previous anchor to the current element.</li>
+ <li>Ctrl+Shift+click &mdash; adds a range of element from the previous anchor to the current element (use Meta key on Mac).</li>
+ </ul>
+ <p>Following drop modes are supported by default:</p>
+ <ul>
+ <li>Simple drop &mdash; moves elements to the valid target removing them from the source. It can be used to reorganize elements within a single source/target.</li>
+ <li>Ctrl+drop &mdash; copies elements to the valid target (use Meta key on Mac).</li>
+ </ul>
+
+ <div id="dragLists">
+ <div style="float: left; margin: 5px;">
+ <h3>Source 1</h3>
+ <div id="container1" class="container"></div>
+ </div>
+ <div style="float: left; margin: 5px;">
+ <h3>Source 2</h3>
+ <div dojoType="dojo.dnd.Source" jsId="c2" class="container">
+ <div class="dojoDndItem">Item <strong>X</strong></div>
+ <div class="dojoDndItem">Item <strong>Y</strong></div>
+ <div class="dojoDndItem">Item <strong>Z</strong></div>
+ </div>
+ </div>
+ <div style="float: left; margin: 5px;">
+ <h3>Source 3</h3>
+ <div dojoType="dojo.dnd.Source" jsId="c3" class="container">
+ <script type="dojo/method" event="creator" args="item, hint">
+ // this is custom creator, which changes the avatar representation
+ var node = dojo.doc.createElement("div"), s = String(item);
+ node.id = dojo.dnd.getUniqueId();
+ node.className = "dojoDndItem";
+ node.innerHTML = (hint != "avatar" || s.indexOf("Item") < 0) ?
+ s : "<strong style='color: darkred'>Special</strong> " + s;
+ return {node: node, data: item, type: ["text"]};
+ </script>
+ <div class="dojoDndItem">Item <strong>Alpha</strong></div>
+ <div class="dojoDndItem">Item <strong>Beta</strong></div>
+ <div class="dojoDndItem">Item <strong>Gamma</strong></div>
+ <div class="dojoDndItem">Item <strong>Delta</strong></div>
+ </div>
+ </div>
+ <div style="float: left; margin: 5px;">
+ <h3>Pure Target 4</h3>
+ <div dojoType="dojo.dnd.Target" jsId="c4" class="container">
+ <div class="dojoDndItem">One item</div>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+
+ <p>HTML after</p>
+
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_dnd_handles.html b/includes/js/dojo/tests/dnd/test_dnd_handles.html
new file mode 100644
index 0000000..bcc58dc
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_dnd_handles.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Dojo DnD with handles test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "../../resources/dnd.css";
+ @import "dndDefault.css";
+
+ body { padding: 1em; background: #ededed; }
+
+ .container { width: 100px; display: block; }
+ .container.handles .dojoDndHandle { background: #fee; }
+ .clear { clear: both; }
+ </style>
+
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+ <script type="text/javascript" src="../../dnd/Container.js"></script>
+ <script type="text/javascript" src="../../dnd/Selector.js"></script>
+ <script type="text/javascript" src="../../dnd/Source.js"></script>
+ <script type="text/javascript" src="../../dnd/Avatar.js"></script>
+ <script type="text/javascript" src="../../dnd/Manager.js"></script>
+
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojo.dnd.Source");
+ </script>
+</head>
+<body>
+ <h1 class="testTitle">Dojo DnD with handles test</h1>
+
+ <p>Following selection modes are supported by default:</p>
+ <ul>
+ <li>Simple click &mdash; selects a single element, all other elements will be unselected.</li>
+ <li>Ctrl+click &mdash; toggles a selection state of an element (use Meta key on Mac).</li>
+ <li>Shift+click &mdash; selects a range of element from the previous anchor to the current element.</li>
+ <li>Ctrl+Shift+click &mdash; adds a range of element from the previous anchor to the current element (use Meta key on Mac).</li>
+ </ul>
+ <p>Following drop modes are supported by default:</p>
+ <ul>
+ <li>Simple drop &mdash; moves elements to the valid target removing them from the source. It can be used to reorganize elements within a single source/target.</li>
+ <li>Ctrl+drop &mdash; copies elements to the valid target (use Meta key on Mac).</li>
+ </ul>
+
+ <p>Source with handles. Items should be draggable by "Item".</p>
+ <div dojoType="dojo.dnd.Source" jsId="c1" withHandles="true" class="container handles">
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Alpha</strong></div>
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Beta</strong></div>
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Gamma</strong></div>
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Delta</strong></div>
+ </div>
+
+ <p>Source without handles.</p>
+ <div dojoType="dojo.dnd.Source" jsId="c2" class="container">
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Epsilon</strong></div>
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Zeta</strong></div>
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Eta</strong></div>
+ <div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Theta</strong></div>
+ </div>
+
+ <p>HTML after</p>
+
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_form.html b/includes/js/dojo/tests/dnd/test_form.html
new file mode 100644
index 0000000..cac46c0
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_form.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Dojo DnD form test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "../../resources/dnd.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 1em;
+ background:#ededed;
+ }
+
+ #container1,#container2 { width:300px; display:block; }
+ .clear { clear:both; }
+
+ </style>
+
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+ <script type="text/javascript" src="../../dnd/Container.js"></script>
+ <script type="text/javascript" src="../../dnd/Selector.js"></script>
+ <script type="text/javascript" src="../../dnd/Source.js"></script>
+ <script type="text/javascript" src="../../dnd/Avatar.js"></script>
+ <script type="text/javascript" src="../../dnd/Manager.js"></script>
+
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ //dojo.require("dojo.dnd.Source");
+ //dojo.require("dojo.dnd.Manager");
+
+ var c1, c2;
+
+ function init(){
+
+ c1 = new dojo.dnd.Source("container1");
+ c1.insertNodes(false, [1, 2, 3, 4, 5, 6, [1, 2, 3], function(x){ return x + x; }]);
+ c2 = new dojo.dnd.Target("container2", {accept: ["money"]});
+
+ // example subscribe to events
+ dojo.subscribe("/dnd/start",function(foo){
+ console.debug(foo);
+ });
+
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1 class="testTitle">Dojo DnD form test</h1>
+
+ <p>This is a test to confirm that the DnD container does not interfere with form elements.</p>
+
+ <div id="dragLists">
+
+ <div style="float:left; margin:5px; ">
+ <h3>Target 1</h3>
+ <p id="container1" class="container"></p>
+ </div>
+
+ <div style="float:left; margin:5px; ">
+ <h3>Target 2: form controls galore</h3>
+ <form id="container2" class="container" action="http://dojotoolkit.org">
+ Input text: <input type="text" /><br />
+ Input checkbox: <input type="checkbox" /><br />
+ Input radio: <input type="radio" /><br />
+ Input password: <input type="password" /><br />
+ Input file: <input type="file" /><br />
+ Input button: <input type="button" value="Button" /><br />
+ Input reset: <input type="reset" /><br />
+ Input submit: <input type="submit" /><br />
+ Input image: <input type="image" src="http://dojotoolkit.org/misc/feed.png" /><br />
+ Button: <button>Button</button><br />
+ Select: <select><option>Yes</option><option>No</option></select><br />
+ Textarea: <textarea cols="20" rows="3">Some text.</textarea>
+ </form>
+ </div>
+ <div class="clear"></div>
+ </div>
+
+ <p>&nbsp;</p>
+
+ <div dojoType="dojo.dnd.Source" class="container">
+ <div>Source with <strong>skipForm = false</strong> (by default)</div>
+ <div class="dojoDndItem">Item <strong>X</strong>: <input type="text" value="1" /></div>
+ <div class="dojoDndItem">Item <strong>Y</strong>: <input type="text" value="2" /></div>
+ <div class="dojoDndItem">Item <strong>Z</strong>: <input type="text" value="3" /></div>
+ </div>
+
+ <p>&nbsp;</p>
+
+ <div dojoType="dojo.dnd.Source" class="container" skipForm="true">
+ <div>Source with <strong>skipForm = true</strong></div>
+ <div class="dojoDndItem">Item <strong>A</strong>: <input type="text" value="a" /></div>
+ <div class="dojoDndItem">Item <strong>B</strong>: <input type="text" value="b" /></div>
+ <div class="dojoDndItem">Item <strong>C</strong>: <input type="text" value="c" /></div>
+ </div>
+
+ <p>HTML after</p>
+
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_moveable.html b/includes/js/dojo/tests/dnd/test_moveable.html
new file mode 100644
index 0000000..3f7e2e7
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_moveable.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo Moveable test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 1em;
+ color:#666;
+ background-color:#dedede;
+ }
+
+ #moveable1 {
+ background: #fff;
+ border: 1px solid black;
+ padding:8px;
+ }
+ #handle1 {
+ background: #333;
+ color: #fff;
+ font-weight: bold;
+ cursor: pointer;
+ border: 1px solid black;
+ }
+ #moveable2 {
+ position: absolute;
+ background: #fff;
+ width: 200px;
+ height: 200px;
+ left: 100px;
+ top: 100px;
+ padding: 10px 20px;
+ margin: 10px 20px;
+ border: 10px solid black;
+ cursor: pointer;
+ radius:8pt;
+ -moz-border-radius:8pt 8pt;
+ }
+ #moveable3 {
+ position: relative;
+ width: 150px;
+ height: 100px;
+ background: #ff8;
+ color: blue;
+ font-weight: bold;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/Mover.js"></script>
+ <script type="text/javascript" src="../../dnd/Moveable.js"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.dnd.move");
+ var m1, m2;
+ var init = function(){
+ m1 = new dojo.dnd.Moveable("moveable1", {handle: "handle1"});
+ m2 = new dojo.dnd.Moveable("moveable2");
+ m3 = new dojo.dnd.Moveable("moveable3");
+
+ dojo.subscribe("/dnd/move/start", function(mover){
+ console.debug("Start move", mover);
+ });
+ dojo.subscribe("/dnd/move/stop", function(mover){
+ console.debug("Stop move", mover);
+ });
+
+ dojo.connect(m1, "onMoveStart", function(mover){
+ console.debug("Start moving m1", mover);
+ });
+ dojo.connect(m1, "onMoveStop", function(mover){
+ console.debug("Stop moving m1", mover);
+ });
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo Moveable test</h1>
+ <h2>1st run</h2>
+ <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam gravida dapibus ante. Nam viverra ligula in neque. Nullam at metus. Aenean ipsum.</p>
+ <p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin sodales vehicula purus. Quisque bibendum mi ac mauris. Quisque tellus. Morbi sagittis. Integer euismod rhoncus augue. Ut accumsan. Curabitur quis tellus sit amet odio ultricies tristique. Etiam malesuada.</p>
+ <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, elementum non, aliquam sed, luctus eu, augue. Aliquam elementum leo nec enim. Donec ornare sagittis magna. Mauris ac tellus.</p>
+ <p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante. Aliquam erat volutpat. Morbi quis velit eu mi sollicitudin lacinia. Suspendisse potenti. Donec lectus.</p>
+ <p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa enim vel turpis. Sed orci neque, sagittis eu, mattis vitae, rutrum condimentum, leo. Fusce wisi odio, convallis at, condimentum vel, imperdiet id, mi. Mauris semper, magna pretium consectetuer sollicitudin, eros enim vehicula risus, eu ultrices turpis quam at wisi. Nam mollis.</p>
+ <table id="moveable1">
+ <tr><td id="handle1" colspan="2">You can drag the table using this handle.</td></tr>
+ <tr><td>1</td><td>Lorem ipsum dolor sit amet...</td></tr>
+ <tr><td>2</td><td>Mauris vulputate elit a risus...</td></tr>
+ <tr><td>3</td><td>Pellentesque habitant morbi tristique senectus...</td></tr>
+ <tr><td>4</td><td>Duis ac augue rhoncus neque...</td></tr>
+ <tr><td>5</td><td>Quisque egestas turpis. Sed id...</td></tr>
+ </table>
+ <h2>2nd run</h2>
+ <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam gravida dapibus ante. Nam viverra ligula in neque. Nullam at metus. Aenean ipsum.</p>
+ <p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin sodales vehicula purus. Quisque bibendum mi ac mauris. Quisque tellus. Morbi sagittis. Integer euismod rhoncus augue. Ut accumsan. Curabitur quis tellus sit amet odio ultricies tristique. Etiam malesuada.</p>
+ <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, elementum non, aliquam sed, luctus eu, augue. Aliquam elementum leo nec enim. Donec ornare sagittis magna. Mauris ac tellus.</p>
+ <p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante. Aliquam erat volutpat. Morbi quis velit eu mi sollicitudin lacinia. Suspendisse potenti. Donec lectus.</p>
+ <p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa enim vel turpis. Sed orci neque, sagittis eu, mattis vitae, rutrum condimentum, leo. Fusce wisi odio, convallis at, condimentum vel, imperdiet id, mi. Mauris semper, magna pretium consectetuer sollicitudin, eros enim vehicula risus, eu ultrices turpis quam at wisi. Nam mollis.</p>
+ <div id="moveable2">
+ <div>You can drag this whole object around.</div>
+ <div id="moveable3">You can move this paragraph. It is relatively positioned.</div>
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_moveable_markup.html b/includes/js/dojo/tests/dnd/test_moveable_markup.html
new file mode 100644
index 0000000..1f63d13
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_moveable_markup.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo Moveable markup test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 1em;
+ color:#666;
+ background-color:#dedede;
+ }
+
+ #moveable1 {
+ background: #fff;
+ border: 1px solid black;
+ padding:8px;
+ }
+ #handle1 {
+ background: #333;
+ color: #fff;
+ font-weight:bold;
+ cursor: pointer;
+ border: 1px solid black;
+ }
+ #moveable2 {
+ background: #fff;
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ left: 100px;
+ top: 100px;
+ padding: 10px 20px;
+ margin: 10px 20px;
+ border: 10px solid black;
+ cursor: pointer;
+ radius:8pt;
+ -moz-border-radius:8pt 8pt;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojo.dnd.move");
+
+ dojo.addOnLoad(function(){
+ dojo.subscribe("/dnd/move/start", function(node){
+ console.debug("Start move", node);
+ });
+
+ dojo.subscribe("/dnd/move/stop", function(node){
+ console.debug("Stop move", node);
+ });
+ });
+ </script>
+</head>
+<body>
+ <h1>Dojo Moveable markup test</h1>
+ <h2>1st run</h2>
+ <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam gravida dapibus ante. Nam viverra ligula in neque. Nullam at metus. Aenean ipsum.</p>
+ <p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin sodales vehicula purus. Quisque bibendum mi ac mauris. Quisque tellus. Morbi sagittis. Integer euismod rhoncus augue. Ut accumsan. Curabitur quis tellus sit amet odio ultricies tristique. Etiam malesuada.</p>
+ <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, elementum non, aliquam sed, luctus eu, augue. Aliquam elementum leo nec enim. Donec ornare sagittis magna. Mauris ac tellus.</p>
+ <p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante. Aliquam erat volutpat. Morbi quis velit eu mi sollicitudin lacinia. Suspendisse potenti. Donec lectus.</p>
+ <p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa enim vel turpis. Sed orci neque, sagittis eu, mattis vitae, rutrum condimentum, leo. Fusce wisi odio, convallis at, condimentum vel, imperdiet id, mi. Mauris semper, magna pretium consectetuer sollicitudin, eros enim vehicula risus, eu ultrices turpis quam at wisi. Nam mollis.</p>
+ <table id="moveable1" dojoType="dojo.dnd.Moveable" handle="handle1">
+ <tr><td id="handle1" colspan="2">You can drag the table using this handle.</td></tr>
+ <tr><td>1</td><td>Lorem ipsum dolor sit amet...</td></tr>
+ <tr><td>2</td><td>Mauris vulputate elit a risus...</td></tr>
+ <tr><td>3</td><td>Pellentesque habitant morbi tristique senectus...</td></tr>
+ <tr><td>4</td><td>Duis ac augue rhoncus neque...</td></tr>
+ <tr><td>5</td><td>Quisque egestas turpis. Sed id...</td></tr>
+ </table>
+ <h2>2nd run</h2>
+ <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam gravida dapibus ante. Nam viverra ligula in neque. Nullam at metus. Aenean ipsum.</p>
+ <p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin sodales vehicula purus. Quisque bibendum mi ac mauris. Quisque tellus. Morbi sagittis. Integer euismod rhoncus augue. Ut accumsan. Curabitur quis tellus sit amet odio ultricies tristique. Etiam malesuada.</p>
+ <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, elementum non, aliquam sed, luctus eu, augue. Aliquam elementum leo nec enim. Donec ornare sagittis magna. Mauris ac tellus.</p>
+ <p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante. Aliquam erat volutpat. Morbi quis velit eu mi sollicitudin lacinia. Suspendisse potenti. Donec lectus.</p>
+ <p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa enim vel turpis. Sed orci neque, sagittis eu, mattis vitae, rutrum condimentum, leo. Fusce wisi odio, convallis at, condimentum vel, imperdiet id, mi. Mauris semper, magna pretium consectetuer sollicitudin, eros enim vehicula risus, eu ultrices turpis quam at wisi. Nam mollis.</p>
+ <div id="moveable2" dojoType="dojo.dnd.Moveable">You can drag this whole paragraph around.</div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_params.html b/includes/js/dojo/tests/dnd/test_params.html
new file mode 100644
index 0000000..1be540c
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_params.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo DnD optional parameters test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+
+ body {
+ padding: 1em;
+ }
+
+ .moveable {
+ background: #FFFFBF;
+ border: 1px solid black;
+ width: 300px;
+ padding: 10px 20px;
+ cursor: pointer;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.dnd.move");
+ var m1, m2, m3, m4;
+ var init = function(){
+ m1 = new dojo.dnd.Moveable("moveable1");
+ m2 = new dojo.dnd.Moveable("moveable2", {delay: 10});
+ m3 = new dojo.dnd.Moveable("moveable3");
+ m4 = new dojo.dnd.Moveable("moveable4", {skip: true});
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo DnD optional parameters test</h1>
+ <p class="moveable" id="moveable1"><strong>Normal paragraph:</strong> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris augue augue, condimentum nec, viverra et, porttitor sit amet, ligula. Cras malesuada sollicitudin risus. Praesent tincidunt nunc ut enim. Aliquam sit amet libero ac lorem ornare vulputate. Nulla a mauris cursus erat rutrum condimentum. Vivamus sit amet pede in felis sodales adipiscing. Curabitur arcu turpis, pharetra ac, porttitor ac, ultrices nec, quam. Donec feugiat purus eu nulla. Aenean mattis tellus vel nulla. Pellentesque vitae quam. Vestibulum scelerisque, eros nec imperdiet interdum, sapien quam accumsan libero, at vestibulum risus purus ut quam. Nam mattis, lorem vel rhoncus pulvinar, augue nibh rhoncus felis, et elementum felis dolor vitae justo. Nullam felis augue, ultricies ac, laoreet sed, lobortis in, neque. Vivamus nunc quam, dictum at, egestas et, fringilla non, magna.</p>
+ <p class="moveable" id="moveable2"><strong>Delayed move by 10px:</strong> Quisque at urna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque ante sem, ullamcorper in, ornare vitae, placerat id, velit. Ut ut tortor vitae lectus dignissim fringilla. Praesent urna enim, laoreet in, lobortis eget, porttitor eget, lacus. Suspendisse et enim. Duis semper nulla a felis. Duis dolor odio, ultrices et, lobortis sed, posuere eu, dolor. Duis est. Nam laoreet. Sed vehicula augue aliquam tortor.</p>
+ <p class="moveable" id="moveable3"><strong>With form elements:</strong>
+ <a href="http://dojotoolkit.org">dojotoolkit</a><br />
+ <input type="button" value="Button" />
+ <input type="text" value="abc" />
+ <input type="checkbox" checked />
+ <input type="radio" />
+ <select>
+ <option value="1">one</option>
+ <option value="2">two</option>
+ </select>
+ </p>
+ <p class="moveable" id="moveable4"><strong>With form elements and skip setting:</strong>
+ <a href="http://dojotoolkit.org">dojotoolkit</a>
+ <input type="button" value="Button" />
+ <input type="text" value="abc" />
+ <input type="checkbox" checked />
+ <input type="radio" />
+ <select>
+ <option value="1">one</option>
+ <option value="2">two</option>
+ </select>
+ </p>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_parent_constraints.html b/includes/js/dojo/tests/dnd/test_parent_constraints.html
new file mode 100644
index 0000000..a814a06
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_parent_constraints.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo parent constraint test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+
+ body {
+ padding: 1em;
+ }
+
+ .moveable {
+ background: #FFFFBF;
+ border: 1px solid black;
+ width: 300px;
+ padding: 10px 20px;
+ cursor: pointer;
+ }
+
+ .parent {
+ background: #BFECFF;
+ border: 10px solid lightblue;
+ width: 500px;
+ height: 500px;
+ padding: 10px;
+ margin: 10px;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.dnd.move");
+ var m1, m2, m3, m4;
+ var init = function(){
+ m1 = new dojo.dnd.move.parentConstrainedMoveable("moveable1", {area: "margin", within: true});
+ m2 = new dojo.dnd.move.parentConstrainedMoveable("moveable2", {area: "border", within: true});
+ m3 = new dojo.dnd.move.parentConstrainedMoveable("moveable3", {area: "padding", within: true});
+ m4 = new dojo.dnd.move.parentConstrainedMoveable("moveable4", {area: "content", within: true});
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo parent constraint test</h1>
+ <div class="parent" id="parent">
+ <div><strong>This is the parent element.</strong> All children will be restricted with <strong>within = true</strong>.</div>
+ <div class="moveable" id="moveable1">I am restricted within my parent's margins.</div>
+ <div class="moveable" id="moveable2">I am restricted within my parent's border.</div>
+ <div class="moveable" id="moveable3">I am restricted within my parent's paddings.</div>
+ <div class="moveable" id="moveable4">I am restricted within my parent's content.</div>
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_parent_constraints_margins.html b/includes/js/dojo/tests/dnd/test_parent_constraints_margins.html
new file mode 100644
index 0000000..3ee455c
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_parent_constraints_margins.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo parent constraint test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+
+ body {
+ padding: 1em;
+ }
+
+ .moveable {
+ background: #FFFFBF;
+ border: 1px solid black;
+ width: 300px;
+ padding: 10px 20px;
+ cursor: pointer;
+ margin: 20px;
+ }
+
+ .parent {
+ background: #BFECFF;
+ border: 10px solid lightblue;
+ width: 500px;
+ height: 500px;
+ padding: 10px;
+ margin: 10px;
+ overflow: hidden;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.dnd.move");
+ var m7, m8;
+ var init = function(){
+ m7 = new dojo.dnd.move.parentConstrainedMoveable("moveable7", {area: "margin"});
+ m8 = new dojo.dnd.move.parentConstrainedMoveable("moveable8", {area: "margin", within: true});
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo parent constraint test</h1>
+ <div class="parent" id="parent">
+ <div><strong>This is the parent element.</strong></div>
+ <div class="moveable" id="moveable7"><strong>Paragraph restricted to its parent element:</strong> Sed hendrerit ornare justo. Maecenas ac urna. Maecenas in leo in tortor tincidunt pellentesque. Vivamus augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer eget ipsum vitae quam condimentum tempus. Phasellus augue tortor, pretium nec, bibendum eget, eleifend eget, quam. Nam sem mauris, volutpat eget, ultricies in, consequat nec, tortor. Nulla eleifend. Vivamus et purus ultricies turpis vehicula auctor.</div>
+ <div class="moveable" id="moveable8"><strong>Paragraph restricted to its parent element (cannot go outside):</strong> Nam nibh. Mauris neque sem, pharetra ac, gravida ac, ultricies eget, quam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Vivamus scelerisque molestie mi. Duis eget ligula nec justo interdum hendrerit. Curabitur tempor convallis enim. In quis lorem. Proin nonummy consectetuer ligula. Curabitur tempor adipiscing lorem. Maecenas vitae nunc. Aliquam et magna. In vestibulum justo eleifend ante. Nulla pede sem, tempus tincidunt, vehicula ut, tempor et, nisi. Nulla ut lorem. Aliquam erat volutpat. Proin sodales, elit ut molestie dignissim, quam neque vulputate felis, quis scelerisque magna arcu aliquet lacus. Vivamus blandit. Nam eu mi vel augue pharetra semper.</div>
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_selector.html b/includes/js/dojo/tests/dnd/test_selector.html
new file mode 100644
index 0000000..bebdca9
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_selector.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Dojo DnD selector test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body { padding: 20px; }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/common.js"></script>
+ <script type="text/javascript" src="../../dnd/Container.js"></script>
+ <script type="text/javascript" src="../../dnd/Selector.js"></script>
+ <script type="text/javascript">
+ //dojo.require("dojo.dnd.Selector");
+ var c1, c2, c3, c4, c5;
+ var init = function(){
+ c1 = new dojo.dnd.Selector(dojo.byId("container1"), {singular: true});
+ c2 = new dojo.dnd.Selector(dojo.byId("container2"));
+ c3 = new dojo.dnd.Selector(dojo.byId("container3"));
+ c4 = new dojo.dnd.Selector(dojo.byId("container4"));
+ c5 = new dojo.dnd.Selector(dojo.byId("container5"));
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo DnD selector test</h1>
+ <p>Containers have a notion of a "current container", and one element can be "current". All containers on this page are selectors that allow to select elements.</p>
+ <p>Following selection modes are supported by default:</p>
+ <ul>
+ <li>Simple click &mdash; selects a single element, all other elements will be unselected.</li>
+ <li>Ctrl+click &mdash; toggles a selection state of an element (use Meta key on Mac).</li>
+ <li>Shift+click &mdash; selects a range of elements from the previous anchor to the current element.</li>
+ <li>Ctrl+Shift+click &mdash; adds a range of elements from the previous anchor to the current element (use Meta key on Mac).</li>
+ </ul>
+ <h2>DIV selector</h2>
+ <p>This selector can select just one element a time. It was specified during the creation time.</p>
+ <div id="container1" class="container">
+ <div class="dojoDndItem">Item 1</div>
+ <div class="dojoDndItem">Item 2</div>
+ <div class="dojoDndItem">Item 3</div>
+ </div>
+ <h2>UL selector</h2>
+ <ul id="container2" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ul>
+ <h2>OL selector</h2>
+ <ol id="container3" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ol>
+ <h2>TABLE selector</h2>
+ <table id="container4" class="container" border="1px solid black">
+ <tr class="dojoDndItem">
+ <td>A</td>
+ <td>row 1</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>B</td>
+ <td>row 2</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>C</td>
+ <td>row 3</td>
+ </tr>
+ </table>
+ <h2>P selector with SPAN elements</h2>
+ <p>Elements of this container are layed out horizontally.</p>
+ <p id="container5" class="container">
+ <span class="dojoDndItem">&nbsp;Item 1&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 2&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 3&nbsp;</span>
+ </p>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_selector_markup.html b/includes/js/dojo/tests/dnd/test_selector_markup.html
new file mode 100644
index 0000000..43c8e9c
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_selector_markup.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Dojo DnD markup selector test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body { padding: 20px; }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../dnd/Selector.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojo.dnd.Selector");
+ </script>
+</head>
+<body>
+ <h1>Dojo DnD markup selector test</h1>
+ <p>This example is functionally equivalent to <a href="test_selector.html">test_selector.html</a> example but is done using the Dojo markup.</p>
+ <p>Containers have a notion of a "current container", and one element can be "current". All containers on this page are selectors that allow to select elements.</p>
+ <p>Following selection modes are supported by default:</p>
+ <ul>
+ <li>Simple click &mdash; selects a single element, all other elements will be unselected.</li>
+ <li>Ctrl+click &mdash; toggles a selection state of an element (use Meta key on Mac).</li>
+ <li>Shift+click &mdash; selects a range of elements from the previous anchor to the current element.</li>
+ <li>Ctrl+Shift+click &mdash; adds a range of elements from the previous anchor to the current element (use Meta key on Mac).</li>
+ </ul>
+ <h2>DIV selector</h2>
+ <p>This selector can select just one element a time. It was specified during the creation time.</p>
+ <div dojoType="dojo.dnd.Selector" jsId="c1" singular="true" class="container">
+ <div class="dojoDndItem">Item 1</div>
+ <div class="dojoDndItem">Item 2</div>
+ <div class="dojoDndItem">Item 3</div>
+ </div>
+ <h2>UL selector</h2>
+ <ul dojoType="dojo.dnd.Selector" jsId="c2" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ul>
+ <h2>OL selector</h2>
+ <ol dojoType="dojo.dnd.Selector" jsId="c3" class="container">
+ <li class="dojoDndItem">Item 1</li>
+ <li class="dojoDndItem">Item 2</li>
+ <li class="dojoDndItem">Item 3</li>
+ </ol>
+ <h2>TABLE selector</h2>
+ <table dojoType="dojo.dnd.Selector" jsId="c4" class="container" border="1px solid black">
+ <tr class="dojoDndItem">
+ <td>A</td>
+ <td>row 1</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>B</td>
+ <td>row 2</td>
+ </tr>
+ <tr class="dojoDndItem">
+ <td>C</td>
+ <td>row 3</td>
+ </tr>
+ </table>
+ <h2>P selector with SPAN elements</h2>
+ <p>Elements of this container are layed out horizontally.</p>
+ <p dojoType="dojo.dnd.Selector" jsId="c5" class="container">
+ <span class="dojoDndItem">&nbsp;Item 1&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 2&nbsp;</span>
+ <span class="dojoDndItem">&nbsp;Item 3&nbsp;</span>
+ </p>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/dnd/test_timed_moveable.html b/includes/js/dojo/tests/dnd/test_timed_moveable.html
new file mode 100644
index 0000000..685067e
--- /dev/null
+++ b/includes/js/dojo/tests/dnd/test_timed_moveable.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dojo TimedMoveable test</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ @import "dndDefault.css";
+
+ body {
+ padding: 1em;
+ color:#666;
+ background-color:#dedede;
+ }
+
+ #moveable1 {
+ background: #fff;
+ border: 1px solid black;
+ padding:8px;
+ }
+ #handle1 {
+ background: #333;
+ color: #fff;
+ font-weight:bold;
+ cursor: pointer;
+ border: 1px solid black;
+ }
+ #moveable2 {
+ background: #fff;
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ left: 100px;
+ top: 100px;
+ padding: 10px 20px;
+ margin: 10px 20px;
+ border: 10px solid black;
+ cursor: pointer;
+ radius:8pt;
+ -moz-border-radius:8pt 8pt;
+ }
+ #moveable3 {
+ background: #fff;
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ left: 350px;
+ top: 350px;
+ padding: 10px 20px;
+ margin: 10px 20px;
+ border: 10px solid green;
+ cursor: pointer;
+ radius:8pt;
+ -moz-border-radius:8pt 8pt;
+ }
+ </style>
+ <script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../../dnd/Mover.js"></script>
+ <script type="text/javascript" src="../../dnd/Moveable.js"></script>
+ <script type="text/javascript" src="../../dnd/TimedMoveable.js"></script>
+ <script type="text/javascript" src="../../dnd/move.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.dnd.TimedMoveable");
+ var m1, m2;
+ var init = function(){
+ m1 = new dojo.dnd.TimedMoveable("moveable1", {handle: "handle1"});
+ m2 = new dojo.dnd.TimedMoveable("moveable2");
+ m3 = new dojo.dnd.TimedMoveable("moveable3", {timeout: 500});
+
+ dojo.subscribe("/dnd/move/start", function(mover){
+ console.debug("Start move", mover);
+ });
+ dojo.subscribe("/dnd/move/stop", function(mover){
+ console.debug("Stop move", mover);
+ });
+
+ dojo.connect(m1, "onMoveStart", function(mover){
+ console.debug("Start moving m1", mover);
+ });
+ dojo.connect(m1, "onMoveStop", function(mover){
+ console.debug("Stop moving m1", mover);
+ });
+ };
+ dojo.addOnLoad(init);
+ </script>
+</head>
+<body>
+ <h1>Dojo TimedMoveable test</h1>
+ <p>One moveable (specially marked) is delayed by 500ms (2 fps). Other two are delayed by 40ms (25 fps) &mdash; this is the default value.</p>
+ <h2>1st run</h2>
+ <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam gravida dapibus ante. Nam viverra ligula in neque. Nullam at metus. Aenean ipsum.</p>
+ <p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin sodales vehicula purus. Quisque bibendum mi ac mauris. Quisque tellus. Morbi sagittis. Integer euismod rhoncus augue. Ut accumsan. Curabitur quis tellus sit amet odio ultricies tristique. Etiam malesuada.</p>
+ <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, elementum non, aliquam sed, luctus eu, augue. Aliquam elementum leo nec enim. Donec ornare sagittis magna. Mauris ac tellus.</p>
+ <p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante. Aliquam erat volutpat. Morbi quis velit eu mi sollicitudin lacinia. Suspendisse potenti. Donec lectus.</p>
+ <p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa enim vel turpis. Sed orci neque, sagittis eu, mattis vitae, rutrum condimentum, leo. Fusce wisi odio, convallis at, condimentum vel, imperdiet id, mi. Mauris semper, magna pretium consectetuer sollicitudin, eros enim vehicula risus, eu ultrices turpis quam at wisi. Nam mollis.</p>
+ <table id="moveable1">
+ <tr><td id="handle1" colspan="2">You can drag the table using this handle.</td></tr>
+ <tr><td>1</td><td>Lorem ipsum dolor sit amet...</td></tr>
+ <tr><td>2</td><td>Mauris vulputate elit a risus...</td></tr>
+ <tr><td>3</td><td>Pellentesque habitant morbi tristique senectus...</td></tr>
+ <tr><td>4</td><td>Duis ac augue rhoncus neque...</td></tr>
+ <tr><td>5</td><td>Quisque egestas turpis. Sed id...</td></tr>
+ </table>
+ <h2>2nd run</h2>
+ <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam gravida dapibus ante. Nam viverra ligula in neque. Nullam at metus. Aenean ipsum.</p>
+ <p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin sodales vehicula purus. Quisque bibendum mi ac mauris. Quisque tellus. Morbi sagittis. Integer euismod rhoncus augue. Ut accumsan. Curabitur quis tellus sit amet odio ultricies tristique. Etiam malesuada.</p>
+ <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, elementum non, aliquam sed, luctus eu, augue. Aliquam elementum leo nec enim. Donec ornare sagittis magna. Mauris ac tellus.</p>
+ <p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante. Aliquam erat volutpat. Morbi quis velit eu mi sollicitudin lacinia. Suspendisse potenti. Donec lectus.</p>
+ <p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa enim vel turpis. Sed orci neque, sagittis eu, mattis vitae, rutrum condimentum, leo. Fusce wisi odio, convallis at, condimentum vel, imperdiet id, mi. Mauris semper, magna pretium consectetuer sollicitudin, eros enim vehicula risus, eu ultrices turpis quam at wisi. Nam mollis.</p>
+ <div id="moveable2">You can drag this whole paragraph around.</div>
+ <div id="moveable3">My move is delayed by 500ms, which corresponds to 2 fps.</div>
+</body>
+</html>
diff --git a/includes/js/dojo/tests/fx.html b/includes/js/dojo/tests/fx.html
new file mode 100644
index 0000000..bd2c9c1
--- /dev/null
+++ b/includes/js/dojo/tests/fx.html
@@ -0,0 +1,310 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing dojo.fx</title>
+ <script type="text/javascript" src="../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.fx");
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function slideTo(t){
+ var s = dojo.fx.slideTo({
+ node: "foo",
+ duration: 500,
+ left: 500,
+ top: 50
+ }).play();
+ var d = new doh.Deferred();
+ dojo.connect(s, "onEnd", function(){
+ doh.is(dojo.style("foo", "left"), 500);
+ doh.is(dojo.style("foo", "top"), 50);
+ with(dojo.byId("foo").style){
+ position = left = top = "";
+ }
+ d.callback(true);
+ });
+ s.play();
+ return d;
+ },
+
+ function wipeOut(t){
+ dojo.byId("foo").style.height = "";
+ var d = new doh.Deferred();
+ var s = dojo.fx.wipeOut({
+ node: "foo",
+ onEnd: function(){
+ doh.t(dojo.style("foo", "height") < 5);
+ d.callback(true);
+ }
+ }).play();
+ return d;
+ },
+
+ function wipeIn(t){
+ var d = new doh.Deferred();
+ setTimeout(function(){
+ dojo.fx.wipeIn({
+ node: "foo",
+ onEnd: function(){
+ console.debug(dojo.style("foo", "height"));
+ doh.t(dojo.style("foo", "height") > 10);
+ d.callback(true);
+ }
+ }).play();
+ }, 10);
+ return d;
+ },
+
+ {
+ name: "chain",
+ timeout: 1500,
+ runTest: function(t){
+ dojo.byId("foo").style.height = "0px";
+ var d = new doh.Deferred();
+ var w = dojo.fx.wipeIn({
+ node: "foo",
+ duration: 500
+ });
+ var f = dojo.fadeOut({
+ node: "foo",
+ duration: 500
+ });
+ var a = dojo.fx.chain([w,f]);
+ dojo.connect(a, "onEnd", function(){
+ doh.t((w.status()=="stopped"&&f.status()=="stopped"));
+ d.callback(true);
+ });
+ a.play();
+ return d;
+ }
+ },
+
+ {
+ name: "combine",
+ timeout: 1500,
+ runTest: function(t){
+ dojo.byId("foo").style.height = "0px";
+ var d = new doh.Deferred();
+ var w = dojo.fx.wipeIn({
+ node: "foo",
+ duration: 500
+ });
+ var f = dojo.fadeIn({
+ node: "foo",
+ duration: 1000
+ });
+ var a = dojo.fx.combine([w,f]);
+ dojo.connect(a, "onEnd", function(){
+ doh.t((w.status()=="stopped"&&f.status()=="stopped"));
+ d.callback(true);
+ });
+ a.play();
+ return d;
+ }
+ },
+ {
+ name:"combineBeforeBegin",
+ timeout:1500,
+ runTest: function(t){
+ var d = new doh.Deferred();
+ var a = dojo.fadeOut({ node:"foo2", duration:400 });
+ var b = dojo.fadeIn({ node:"foo2", duration:400 });
+ var chain = dojo.fx.combine([a,b]);
+ dojo.connect(chain,"beforeBegin",dojo.hitch(d,"callback",true));
+ chain.play();
+ return d;
+ }
+
+ },
+ {
+ name:"delayTest",
+ timeout:2000,
+ runTest:function(t){
+ var d = new doh.Deferred();
+ var delay = 100;
+ var _anims = [];
+ var nodes = ["a","b","c","d"];
+ dojo.forEach(nodes,function(n){
+ _anims.push(dojo.fadeOut({ node:n, duration:100, delay: delay += 100 }));
+ });
+ var a = dojo.fx.combine(_anims);
+ var timer = (new Date()).getTime();
+ dojo.connect(a,"onEnd",function(){
+ console.warn("delayTest running time:", (new Date()).getTime() - timer, "ms, expected:", a.duration, "ms");
+ d.callback(true);
+ });
+ a.play();
+ return d;
+ }
+ },
+ {
+ name:"delayTestChain",
+ timeout:2200,
+ runTest:function(t){
+ var d = new doh.Deferred();
+ var delay = 100;
+ var _anims = [];
+ var nodes = ["a","b","c","d"];
+ dojo.forEach(nodes,function(n){
+ _anims.push(dojo.fadeIn({ node:n, duration:100, delay: delay += 100 }));
+ });
+ var a = dojo.fx.chain(_anims);
+ var timer = (new Date()).getTime();
+ dojo.connect(a,"onEnd",function(){
+ console.warn("delayTestChain running time:", (new Date()).getTime() - timer, "ms, expected:", a.duration, "ms");
+ d.callback(true);
+ });
+ a.play();
+ return d;
+ }
+ },
+ {
+ name:"combineOnEnd",
+ timeout:1500,
+ runTest: function(t){
+ var d = new doh.Deferred();
+ var a = dojo.fadeOut({ node:"foo2", duration:400 });
+ var b = dojo.fadeIn({ node:"foo2", duration:400 });
+ var combine = dojo.fx.combine([a,b]);
+ dojo.connect(combine,"onEnd",dojo.hitch(d,"callback",true));
+ combine.play();
+ return d;
+ }
+
+ },
+ {
+ name:"combineOnPlay",
+ timeout:1500,
+ runTest: function(t){
+ var d = new doh.Deferred();
+ var a = dojo.fadeOut({ node:"foo2", duration:400 });
+ var b = dojo.fadeIn({ node:"foo2", duration:400 });
+ var combine = dojo.fx.combine([a,b]);
+ dojo.connect(combine,"onPlay",dojo.hitch(d,"callback",true));
+ combine.play();
+ return d;
+ }
+
+ },
+ {
+ name:"chainOnEnd",
+ timeout:1500,
+ runTest: function(t){
+ var d = new doh.Deferred();
+ var a = dojo.fadeOut({ node:"foo2", duration:400 });
+ var b = dojo.fadeIn({ node:"foo2", duration:400 });
+ var chain = dojo.fx.chain([a,b]);
+ dojo.connect(chain,"onEnd",dojo.hitch(d,"callback",true));
+ chain.play();
+ return d;
+ }
+
+ },
+ {
+ name:"chainOnPlay",
+ timeout:1500,
+ runTest: function(t){
+
+ var d = new doh.Deferred();
+ var a = dojo.fadeOut({ node:"foo2", duration:200 });
+ var b = dojo.fadeIn({ node:"foo2", duration:200 });
+ var chain = dojo.fx.chain([a,b]);
+ dojo.connect(chain,"onPlay",dojo.hitch(d,"callback",true));
+ chain.play();
+ return d;
+ }
+
+ },
+
+ function Toggler(){
+ var d = new doh.Deferred();
+ var t = new dojo.fx.Toggler({
+ node: "foo",
+ hideDuration: 100,
+ hideFunc: dojo.fx.wipeOut,
+ showFunc: dojo.fx.wipeIn
+ });
+ t.hide();
+ setTimeout(function(){
+ var sa = t.show();
+ dojo.connect(sa, "onEnd", dojo.hitch(d, "callback", true));
+ }, 50);
+ return d;
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <style type="text/css">
+ @import "../resources/dojo.css";
+
+ body {
+ text-shadow: 0px 0px;
+ margin: 1em;
+ background-color: #DEDEDE;
+ }
+
+ .box {
+ color: #292929;
+ /* color: #424242; */
+ /* text-align: left; */
+ width: 300px;
+ border: 1px solid #BABABA;
+ background-color: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ margin-left: 10px;
+ margin-bottom: 1em;
+ -o-border-radius: 10px;
+ -moz-border-radius: 12px;
+ -webkit-border-radius: 10px;
+ -webkit-box-shadow: 0px 3px 7px #adadad;
+ /* -opera-border-radius: 10px; */
+ border-radius: 10px;
+ -moz-box-sizing: border-box;
+ -opera-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -khtml-box-sizing: border-box;
+ box-sizing: border-box;
+ overflow: hidden;
+ /* position: absolute; */
+ }
+ </style>
+ </head>
+ <body>
+ <div class="box" id="a">a</div><div class="box" id="b">b</div>
+ <div class="box" id="c">c</div><div class="box" id="d">d</div>
+
+ <div id="foo" class="box">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+ semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+ Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla
+ facilisi. Maecenas luctus venenatis nulla. In sit amet dui non mi
+ semper iaculis. Sed molestie tortor at ipsum. Morbi dictum rutrum
+ magna. Sed vitae risus.
+ </p>
+ <p>
+ Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+ imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+ lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+ id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+ mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+ pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+ tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+ elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+ ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+ pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+ massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+ nec est. Aenean id risus blandit tortor pharetra congue.
+ Suspendisse pulvinar.
+ </p>
+ </div>
+ <div id="foo2">foo2</div>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/fx.js b/includes/js/dojo/tests/fx.js
new file mode 100644
index 0000000..f5e2cfc
--- /dev/null
+++ b/includes/js/dojo/tests/fx.js
@@ -0,0 +1,9 @@
+if(!dojo._hasResource["tests.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.fx"] = true;
+dojo.provide("tests.fx");
+if(dojo.isBrowser){
+ doh.registerUrl("tests.fx", dojo.moduleUrl("tests", "fx.html"), 30000);
+ doh.registerUrl("tests.NodeList-fx", dojo.moduleUrl("tests", "NodeList-fx.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/i18n.js b/includes/js/dojo/tests/i18n.js
new file mode 100644
index 0000000..47bb946
--- /dev/null
+++ b/includes/js/dojo/tests/i18n.js
@@ -0,0 +1,88 @@
+if(!dojo._hasResource["tests.i18n"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.i18n"] = true;
+dojo.provide("tests.i18n");
+
+dojo.require("dojo.i18n");
+
+(function(){
+ var setUp = function(locale){
+ return function(){
+ dojo.requireLocalization("tests","salutations",locale, "");
+ }
+ }
+
+ var getTest = function(value, locale){
+ return function(){
+ doh.assertEqual(value, dojo.i18n.getLocalization("tests", "salutations", locale).hello);
+ }
+ }
+
+ var getFixture = function(locale, value){
+ return {
+ name: "salutations-"+locale,
+ setUp: setUp(locale),
+ runTest: getTest(value, locale)
+ };
+ }
+
+ var testSet = [
+ /* needs dojo.string,
+ // This doesn't actually test anything, it just gives an impressive list of translated output to the console
+ // See the 'salutations' test for something verifyable
+ function fun(t){
+ var salutations_default = dojo.i18n.getLocalization("tests", "salutations");
+ console.debug("In the local language: "+salutations_default.hello);
+
+ var salutations_en = dojo.i18n.getLocalization("tests", "salutations", "en");
+
+ for (i in tests.nls.salutations) {
+ var loc = i.replace('_', '-');
+ var salutations = dojo.i18n.getLocalization("tests", "salutations", loc);
+ var language_as_english = salutations_en[loc];
+ var language_as_native = salutations[loc];
+ var hello_dojo = dojo.string.substitute(salutations.hello_dojo, salutations);
+ if (!dojo.i18n.isLeftToRight(loc)) {
+ var RLE = "\u202b";
+ var PDF = "\u202c";
+ hello_dojo = RLE + hello_dojo + PDF;
+ }
+ hello_dojo += "\t[" + loc + "]";
+ if(language_as_english){hello_dojo += " " + language_as_english;}
+ if(language_as_native){hello_dojo += " (" + language_as_native + ")";}
+ console.debug(hello_dojo);
+ }
+
+ t.assertTrue(true);
+ },
+ */
+
+ // Test on-the-fly loading of localized string bundles from different locales, and
+ // the expected inheritance behavior
+
+ // Locale which overrides root translation
+ getFixture("de", "Hallo"),
+ // Locale which does not override root translation
+ getFixture("en", "Hello"),
+ // Locale which overrides its parent
+ getFixture("en-au", "G'day"),
+ // Locale which does not override its parent
+ getFixture("en-us", "Hello"),
+ // Locale which overrides its parent
+ getFixture("en-us-texas", "Howdy"),
+ // 3rd level variant which overrides its parent
+ getFixture("en-us-new_york", "Hello"),
+ // Locale which overrides its grandparent
+ getFixture("en-us-new_york-brooklyn", "Yo"),
+ // Locale which does not have any translation available
+ getFixture("xx", "Hello"),
+ // A double-byte string. Everything should be read in as UTF-8 and treated as unicode within Javascript.
+ getFixture("zh-cn", "\u4f60\u597d")
+ ];
+ testSet[testSet.length-1].tearDown = function(){
+ // Clean up bundles that should not exist if the test is re-run.
+ delete tests.nls.salutations;
+ };
+ tests.register("tests.i18n", testSet);
+})();
+
+}
diff --git a/includes/js/dojo/tests/io/iframe.html b/includes/js/dojo/tests/io/iframe.html
new file mode 100644
index 0000000..c37bcb1
--- /dev/null
+++ b/includes/js/dojo/tests/io/iframe.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing dojo.io.iframe</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.io.iframe");
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function ioIframeGetText(t){
+ var d = new doh.Deferred();
+ var td = dojo.io.iframe.send({
+ url: "iframeResponse.text.html",
+ method: "GET",
+ timeoutSeconds: 5,
+ preventCache: true,
+ handle: function(res, ioArgs){
+ if(!(res instanceof Error) &&
+ t.is("iframe succeeded", res)){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ return d;
+ },
+
+ function ioIframeGetJson(t){
+ var d = new doh.Deferred();
+ var td = dojo.io.iframe.send({
+ url: "iframeResponse.json.html",
+ method: "GET",
+ timeoutSeconds: 5,
+ preventCache: true,
+ handleAs: "json",
+ handle: function(res, ioArgs){
+ if(!(res instanceof Error) &&
+ t.is("blue", res.color)){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ return d;
+ },
+
+ function ioIframeGetJavascript(t){
+ var d = new doh.Deferred();
+ var td = dojo.io.iframe.send({
+ url: "iframeResponse.js.html",
+ method: "GET",
+ timeoutSeconds: 5,
+ preventCache: true,
+ handleAs: "javascript",
+ handle: function(res, ioArgs){
+ console.log("RES: ", res);
+ if(!(res instanceof Error) &&
+ t.is(42, window.iframeTestingFunction())){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ return d;
+ },
+
+ function ioIframeGetHtml(t){
+ var d = new doh.Deferred();
+ var td = dojo.io.iframe.send({
+ url: "iframeResponse.html",
+ method: "GET",
+ timeoutSeconds: 5,
+ preventCache: true,
+ handleAs: "html",
+ handle: function(res, ioArgs){
+ if(!(res instanceof Error) &&
+ t.is("SUCCESSFUL HTML response", res.getElementsByTagName("h1")[0].innerHTML)){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ }
+ });
+ return d;
+ }
+ ]
+ );
+ doh.run();
+ });
+
+/*
+dojo.addOnLoad(function(){
+ var td = dojo.io.iframe.get({
+ url: "iframeResponse.text.html",
+ timeoutSeconds: 5,
+ preventCache: true,
+ handle: function(res, ioArgs){
+ if(!(res instanceof Error) &&
+ "iframe succeeded" == res){
+ console.debug("OK");
+ }else{
+ console.debug("Error", res);
+ }
+ }
+ });
+});
+*/
+ </script>
+ </head>
+ <body>
+
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/io/iframe.js b/includes/js/dojo/tests/io/iframe.js
new file mode 100644
index 0000000..6e20af5
--- /dev/null
+++ b/includes/js/dojo/tests/io/iframe.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests.io.iframe"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.io.iframe"] = true;
+dojo.provide("tests.io.iframe");
+if(dojo.isBrowser){
+ doh.registerUrl("tests.io.iframe", dojo.moduleUrl("tests.io", "iframe.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/io/iframeResponse.html b/includes/js/dojo/tests/io/iframeResponse.html
new file mode 100644
index 0000000..cd26e21
--- /dev/null
+++ b/includes/js/dojo/tests/io/iframeResponse.html
@@ -0,0 +1,8 @@
+<html lang="en">
+ <head>
+ </head>
+ <body>
+ <h1>SUCCESSFUL HTML response</h1>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/io/iframeResponse.js.html b/includes/js/dojo/tests/io/iframeResponse.js.html
new file mode 100644
index 0000000..50c1855
--- /dev/null
+++ b/includes/js/dojo/tests/io/iframeResponse.js.html
@@ -0,0 +1,7 @@
+<html>
+ <head>
+ </head>
+ <body>
+ <textarea style="width: 100%; height: 100px;">window.iframeTestingFunction = function(){ return 42; };</textarea>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/io/iframeResponse.json.html b/includes/js/dojo/tests/io/iframeResponse.json.html
new file mode 100644
index 0000000..cb04ed7
--- /dev/null
+++ b/includes/js/dojo/tests/io/iframeResponse.json.html
@@ -0,0 +1,7 @@
+<html>
+ <head>
+ </head>
+ <body>
+ <textarea style="width: 100%; height: 100px;">{ color: "blue", size: 42 }</textarea>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/io/iframeResponse.text.html b/includes/js/dojo/tests/io/iframeResponse.text.html
new file mode 100644
index 0000000..2a05b83
--- /dev/null
+++ b/includes/js/dojo/tests/io/iframeResponse.text.html
@@ -0,0 +1,7 @@
+<html>
+ <head>
+ </head>
+ <body>
+ <textarea style="width: 100%; height: 100px;">iframe succeeded</textarea>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/io/iframeUploadTest.html b/includes/js/dojo/tests/io/iframeUploadTest.html
new file mode 100644
index 0000000..6f6db6f
--- /dev/null
+++ b/includes/js/dojo/tests/io/iframeUploadTest.html
@@ -0,0 +1,50 @@
+<html>
+ <head>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ djConfig="isDebug: true, dojoIframeHistoryUrl: '../../resource/blank.html'"
+ src="../../dojo.js"></script>
+
+ <script type="text/javascript">
+ dojo.require("dojo.io.iframe");
+
+ var callCount = 0;
+ var ioResponse;
+
+ function sendIt(){
+ dojo.io.iframe.send({
+ form: dojo.byId("uploadForm"),
+ handleAs: "application/json",
+ content: {
+ increment: callCount++,
+ fileFields: "ul1"
+ },
+ handle: function(response, ioArgs){
+ if(response instanceof Error){
+ console.debug("Request FAILED: ", response);
+ }else{
+ console.debug("Request complete: ", response);
+ }
+ ioResponse = response; // to get at afterwards in debugger.
+ }
+ });
+ }
+ </script>
+ </head>
+ <body>
+ <p>This file tests dojo.io.iframe upload using a form POST with a file upload button.</p>
+
+ <p>
+ <b>Note:</b> This test makes a form POST to upload.cgi. This cgi needs to be made executable for this test to work, and it won't work from local disk.
+ </p>
+ <form action="upload.cgi" id="uploadForm"
+ method="POST" enctype="multipart/form-data">
+ <input type="text" name="foo" value="bar">
+ <input type="file" name="ul1">
+ <input type="button" onclick="sendIt(); return false;" value="send it!">
+ </form>
+ </body>
+</html>
+
diff --git a/includes/js/dojo/tests/io/script.html b/includes/js/dojo/tests/io/script.html
new file mode 100644
index 0000000..db24ac9
--- /dev/null
+++ b/includes/js/dojo/tests/io/script.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing dojo.io.script</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.io.script");
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function ioScriptSimple(t){
+ var d = new doh.Deferred();
+ var td = dojo.io.script.get({
+ url: "scriptSimple.js",
+ checkString: "myTasks"
+ });
+ td.addBoth(function(res){
+ if(typeof(myTasks) != "undefined"
+ && t.is("Do dishes.", myTasks[1])){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ });
+ return d;
+ },
+ function ioScriptJsonp(t){
+ var d = new doh.Deferred();
+ var td = dojo.io.script.get({
+ url: "scriptJsonp.js",
+ content: { foo: "bar" },
+ callbackParamName: "callback"
+ });
+ td.addBoth(function(res){
+ if(!(res instanceof Error) &&
+ t.is("mammal", res.animalType)){
+ d.callback(true);
+ }else{
+ d.errback(false);
+ }
+ });
+ return d;
+ },
+ function ioScriptJsonpTimeout(t){
+ var d = new doh.Deferred();
+ var td = dojo.io.script.get({
+ url: "../_base/timeout.php",
+ callbackParamName: "callback",
+ content: {Foo: 'Bar'},
+ timeout: 500,
+ handleAs: "json",
+ preventCache: true,
+ handle: function(response, ioArgs){
+ if(response instanceof Error && response.dojoType == "timeout"){
+ console.debug("FOO OK TEST");
+ d.callback(true);
+ }else{
+ console.debug("FOO FAIL TEST");
+ d.errback(false);
+ }
+ }
+ });
+ return d;
+ }
+ ]
+ );
+ doh.run();
+ });
+
+/*
+ dojo.addOnLoad(function(){
+ td = dojo.io.script.get({
+ url: "scriptSimple.js",
+ checkString: "myTasks"
+ });
+ td.addCallback(function(res){
+ alert(myTasks);
+ alert(myTasks[1]);
+ if(typeof(myTasks) != "undefined"
+ && "Do dishes." == myTasks[1]){
+ alert("yeah");
+ }else{
+ alert("boo");
+ }
+ });
+ });
+*/
+
+ </script>
+ </head>
+ <body>
+
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/io/script.js b/includes/js/dojo/tests/io/script.js
new file mode 100644
index 0000000..722a805
--- /dev/null
+++ b/includes/js/dojo/tests/io/script.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests.io.script"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.io.script"] = true;
+dojo.provide("tests.io.script");
+if(dojo.isBrowser){
+ doh.registerUrl("tests.io.script", dojo.moduleUrl("tests.io", "script.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/io/scriptJsonp.js b/includes/js/dojo/tests/io/scriptJsonp.js
new file mode 100644
index 0000000..ad1a196
--- /dev/null
+++ b/includes/js/dojo/tests/io/scriptJsonp.js
@@ -0,0 +1,57 @@
+function getJsonpCallback(url){
+ var result = null;
+ var idMatch = url.match(/jsonp=(.*?)(&|$)/);
+ if(idMatch){
+ result = idMatch[1];
+ }else{
+ //jsonp didn't match, so maybe it is the jsonCallback thing.
+ idMatch = url.match(/callback=(.*?)(&|$)/);
+ if(idMatch){
+ result = idMatch[1];
+ }
+ }
+
+ if(result){
+ result = decodeURIComponent(result);
+ }
+ return result;
+}
+
+function findJsonpDone(){
+ var result = false;
+ var scriptUrls = getScriptUrls();
+
+ for(var i = 0; i < scriptUrls.length; i++){
+ var jsonp = getJsonpCallback(scriptUrls[i]);
+ if(jsonp){
+ eval(jsonp + "({animalType: 'mammal'});");
+ result = true;
+ break;
+ }
+ }
+ return result;
+}
+
+function getScriptUrls(){
+ //Get the script tags in the page to figure what state we are in.
+ var scripts = document.getElementsByTagName('script');
+ var scriptUrls = new Array();
+ for(var i = 0; scripts && i < scripts.length; i++){
+ var scriptTag = scripts[i];
+ if(scriptTag.id.indexOf("dojoIoScript") == 0){
+ scriptUrls.push(scriptTag.src);
+ }
+ }
+
+ return scriptUrls;
+}
+
+function doJsonpCallback(){
+ if(!findJsonpDone()){
+ alert('ERROR: Could not jsonp callback!');
+ }
+}
+
+//Set a timeout to do the callback check, since MSIE won't see the SCRIPT tag until
+//we complete processing of this page.
+setTimeout(function(){doJsonpCallback();}, 300);
diff --git a/includes/js/dojo/tests/io/scriptSimple.js b/includes/js/dojo/tests/io/scriptSimple.js
new file mode 100644
index 0000000..8ca316c
--- /dev/null
+++ b/includes/js/dojo/tests/io/scriptSimple.js
@@ -0,0 +1,5 @@
+myTasks = new Array();
+myTasks[0] = 'Take out trash.';
+myTasks[1] = 'Do dishes.';
+myTasks[2] = 'Brush teeth.';
+
diff --git a/includes/js/dojo/tests/io/scriptTimeout.html b/includes/js/dojo/tests/io/scriptTimeout.html
new file mode 100644
index 0000000..563e37c
--- /dev/null
+++ b/includes/js/dojo/tests/io/scriptTimeout.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Testing dojo.io.script</title>
+ <style type="text/css">
+ @import "../../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.io.script");
+
+ function startTest(){
+ var td = dojo.io.script.get({
+ url: "../_base/timeout.php",
+ callbackParamName: "callback",
+ content: {Foo: 'Bar'},
+ timeout: 500,
+ handleAs: "json",
+ preventCache: true,
+ handle: function(response, ioArgs){
+ if(response instanceof Error && response.dojoType == "timeout"){
+ console.debug("TEST OK. No errors should be seen after this timeout error.");
+ }else{
+ console.debug("TEST FAILED: some other error or response received: ", response);
+ }
+ }
+ });
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Timeout test</h1>
+
+ <p>
+ This test page tests the timeout functionality of dojo.io.script, and to make
+ sure that requests that time out get removed quickly. If the server response
+ is received after the script has been timed out, there should not be weird
+ errors as the browser tries to evaluate the responses after the desired time
+ period.
+ </p>
+
+ <p>This test requires a server running PHP to work.</p>
+
+ <p>
+ <p><strong>Firefox Oddity:</strong> Firefox
+ will print an error after the script response is received from the server:<br />
+ <span style="color: red">dojo.io.script.jsonp_dojoIoScript1 has no properties</span>
+ This is bad because Firefox goes ahead and evaluates the script contents in the page's
+ JavaScript space (this happens even when I turn off Firefox Add-Ons). All other browsers
+ do not evaluate the script (given the weird Opera 9.22 behavior below). You can test this
+ by clicking the <b>Test for SuperXFooBarVariable</b> button after receiving the response
+ for timeout.php (check Firebug Net tab to see when request is received). All other browsers
+ show an error or show the "undefined" value for SuperXFooBarVariable, but Firefox will show its
+ value as being: "Oh no! SuperXFooBarVariable is defined (should not be for timeout case)".
+
+ <p><strong>Opera Oddity:</strong> Opera 9.22 does not seem to trigger the timeout case,
+ but rather it waits for the server to send a response to the script before continuing past the
+ point where the script is added to the DOM? That seems wrong. Dynamic script tags are no longer
+ an async operation?
+ </p>
+
+ <button onclick="startTest()">Start Test</button>
+ <button onclick="alert(SuperXFooBarVariable)">Test for SuperXFooBarVariable</button>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/io/upload.cgi b/includes/js/dojo/tests/io/upload.cgi
new file mode 100644
index 0000000..a13656f
--- /dev/null
+++ b/includes/js/dojo/tests/io/upload.cgi
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+# FROM: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/273844
+
+import cgi
+import cgitb; cgitb.enable()
+import os, sys
+import string
+
+UPLOAD_DIR = "/tmp/upload/"
+form = cgi.FieldStorage()
+
+dbg = []
+
+def debug(dbgstr):
+ dbg.append(str(dbgstr))
+
+def save_uploaded_file(form_field, upload_dir):
+ global form
+ if not form.has_key(form_field):
+ debug("didn't find it! (1)")
+ return
+ fileitem = form[form_field]
+ if not fileitem.file:
+ debug(form.getvalue(form_field, ""))
+ debug(fileitem.__dict__)
+ debug("didn't find it! (2)")
+ return
+ fout = file(os.path.join(upload_dir, fileitem.filename), 'wb')
+ while 1:
+ chunk = fileitem.file.read(100000)
+ if not chunk: break
+ fout.write (chunk)
+ fout.close()
+
+retval = "false";
+fileFields = ""
+
+if form.has_key("fileFields"):
+ fval = str(form.getvalue("fileFields", ""))
+ fileFields = fval.split(",")
+ debug("'fileCount': '" + str(len(fileFields)) + "',")
+ for field in fileFields:
+ debug("'fileField' : '"+field + "',")
+ save_uploaded_file(str(field).strip(), UPLOAD_DIR)
+ retval = "true";
+
+debug("'retval': " + retval)
+
+print """Content-Type: text/html
+
+
+<html>
+ <head>
+ </head>
+ <body>
+ <textarea style="width: 100%; height: 100px;">{ %s }</textarea>
+ </body>
+</html>
+""" % (string.join(dbg, "\n"))
diff --git a/includes/js/dojo/tests/manualTests.html b/includes/js/dojo/tests/manualTests.html
new file mode 100644
index 0000000..26ff163
--- /dev/null
+++ b/includes/js/dojo/tests/manualTests.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <title>Dojo Manual Test Runner</title>
+ </head>
+ <body>
+ Redirecting to D.O.H runner
+ <script>
+ window.location.replace("../../util/doh/runner.html?testModule=dojo.tests.manualTests"+window.location.search.replace(/^\?/,"&"));
+ </script>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/manualTests.js b/includes/js/dojo/tests/manualTests.js
new file mode 100644
index 0000000..d60a01b
--- /dev/null
+++ b/includes/js/dojo/tests/manualTests.js
@@ -0,0 +1,45 @@
+if(!dojo._hasResource["dojo.tests.manualTests"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.tests.manualTests"] = true;
+dojo.provide("dojo.tests.manualTests");
+
+try{
+if(dojo.isBrowser){
+ var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+ doh.registerUrl("dojo/tests/back-bookmark.html", dojo.moduleUrl("dojo","tests/back-bookmark.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/back.html", dojo.moduleUrl("dojo","tests/back.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/test_FirebugLite.html", dojo.moduleUrl("dojo","tests/test_FirebugLite.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/test_fx.html", dojo.moduleUrl("dojo","tests/test_fx.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/flickr_viewer.html", dojo.moduleUrl("dojo","tests/dnd/flickr_viewer.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_box_constraints.html", dojo.moduleUrl("dojo","tests/dnd/test_box_constraints.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_container.html", dojo.moduleUrl("dojo","tests/dnd/test_container.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_container_markup.html", dojo.moduleUrl("dojo","tests/dnd/test_container_markup.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_custom_constraints.html", dojo.moduleUrl("dojo","tests/dnd/test_custom_constraints.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_dnd.html", dojo.moduleUrl("dojo","tests/dnd/test_dnd.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_dnd_handles.html", dojo.moduleUrl("dojo","tests/dnd/test_dnd_handles.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_form.html", dojo.moduleUrl("dojo","tests/dnd/test_form.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_moveable.html", dojo.moduleUrl("dojo","tests/dnd/test_moveable.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_moveable_markup.html", dojo.moduleUrl("dojo","tests/dnd/test_moveable_markup.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_params.html", dojo.moduleUrl("dojo","tests/dnd/test_params.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_parent_constraints.html", dojo.moduleUrl("dojo","tests/dnd/test_parent_constraints.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_parent_constraints_margins.html", dojo.moduleUrl("dojo","tests/dnd/test_parent_constraints_margins.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_selector.html", dojo.moduleUrl("dojo","tests/dnd/test_selector.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_selector_markup.html", dojo.moduleUrl("dojo","tests/dnd/test_selector_markup.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/dnd/test_timed_moveable.html", dojo.moduleUrl("dojo","tests/dnd/test_timed_moveable.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/io/iframeUploadTest.html", dojo.moduleUrl("dojo","tests/io/iframeUploadTest.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/io/scriptTimeout.html", dojo.moduleUrl("dojo","tests/io/scriptTimeout.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/fx_delay.html", dojo.moduleUrl("dojo","tests/_base/fx_delay.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/addLoadEvents.html", dojo.moduleUrl("dojo","tests/_base/_loader/addLoadEvents.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/afterOnLoad.html", dojo.moduleUrl("dojo","tests/_base/_loader/afterOnLoad.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/744/testEval.html", dojo.moduleUrl("dojo","tests/_base/_loader/744/testEval.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/scope/scope04.html", dojo.moduleUrl("dojo","tests/_base/_loader/scope/scope04.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/scope/scopeContained.html", dojo.moduleUrl("dojo","tests/_base/_loader/scope/scopeContained.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/scope/scopeContainedXd.html", dojo.moduleUrl("dojo","tests/_base/_loader/scope/scopeContainedXd.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/scope/scopeDjConfig.html", dojo.moduleUrl("dojo","tests/_base/_loader/scope/scopeDjConfig.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/scope/scopeSingle.html", dojo.moduleUrl("dojo","tests/_base/_loader/scope/scopeSingle.html"+userArgs), 99999999);
+ doh.registerUrl("dojo/tests/_base/_loader/scope/scopeSingleDaac.html", dojo.moduleUrl("dojo","tests/_base/_loader/scope/scopeSingleDaac.html"+userArgs), 99999999);
+}
+}catch(e){
+ doh.debug(e);
+}
+
+}
diff --git a/includes/js/dojo/tests/module.js b/includes/js/dojo/tests/module.js
new file mode 100644
index 0000000..c4995aa
--- /dev/null
+++ b/includes/js/dojo/tests/module.js
@@ -0,0 +1,29 @@
+if(!dojo._hasResource["dojo.tests.module"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.tests.module"] = true;
+dojo.provide("dojo.tests.module");
+
+try{
+ dojo.require("tests._base");
+ dojo.require("tests.i18n");
+ dojo.requireIf(dojo.isBrowser, "tests.back-hash");
+ dojo.require("tests.cldr");
+ dojo.require("tests.data");
+ dojo.require("tests.date");
+ dojo.require("tests.number");
+ dojo.require("tests.currency");
+ dojo.require("tests.AdapterRegistry");
+ dojo.require("tests.io.script");
+ dojo.require("tests.io.iframe");
+ dojo.requireIf(dojo.isBrowser, "tests.rpc");
+ dojo.require("tests.string");
+ dojo.require("tests.behavior");
+ dojo.require("tests.parser");
+ dojo.require("tests.colors");
+ dojo.requireIf(dojo.isBrowser,"tests.cookie");
+ dojo.require("tests.fx");
+ dojo.require("tests.DeferredList");
+}catch(e){
+ doh.debug(e);
+}
+
+}
diff --git a/includes/js/dojo/tests/nls/ar/salutations.js b/includes/js/dojo/tests/nls/ar/salutations.js
new file mode 100644
index 0000000..f6f2cbf
--- /dev/null
+++ b/includes/js/dojo/tests/nls/ar/salutations.js
@@ -0,0 +1 @@
+({"ar":"العربية","hello":"ﺎﺑﺣﺮﻣ","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/cs/salutations.js b/includes/js/dojo/tests/nls/cs/salutations.js
new file mode 100644
index 0000000..0d7b880
--- /dev/null
+++ b/includes/js/dojo/tests/nls/cs/salutations.js
@@ -0,0 +1 @@
+({"hello":"Ahoj","cs":"česky","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/de/salutations.js b/includes/js/dojo/tests/nls/de/salutations.js
new file mode 100644
index 0000000..efd62ec
--- /dev/null
+++ b/includes/js/dojo/tests/nls/de/salutations.js
@@ -0,0 +1 @@
+({"de":"Deutsch","hello":"Hallo","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/el/salutations.js b/includes/js/dojo/tests/nls/el/salutations.js
new file mode 100644
index 0000000..10d97c0
--- /dev/null
+++ b/includes/js/dojo/tests/nls/el/salutations.js
@@ -0,0 +1 @@
+({"hello":"Γειά","el":"Ελληνικά","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/en-au/salutations.js b/includes/js/dojo/tests/nls/en-au/salutations.js
new file mode 100644
index 0000000..314ab18
--- /dev/null
+++ b/includes/js/dojo/tests/nls/en-au/salutations.js
@@ -0,0 +1 @@
+({"hello":"G'day","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/en-us-hawaii/salutations.js b/includes/js/dojo/tests/nls/en-us-hawaii/salutations.js
new file mode 100644
index 0000000..dd35331
--- /dev/null
+++ b/includes/js/dojo/tests/nls/en-us-hawaii/salutations.js
@@ -0,0 +1 @@
+({"hello":"Aloha","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/en-us-new_york-brooklyn/salutations.js b/includes/js/dojo/tests/nls/en-us-new_york-brooklyn/salutations.js
new file mode 100644
index 0000000..9deae14
--- /dev/null
+++ b/includes/js/dojo/tests/nls/en-us-new_york-brooklyn/salutations.js
@@ -0,0 +1 @@
+({"hello":"Yo","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/en-us-texas/salutations.js b/includes/js/dojo/tests/nls/en-us-texas/salutations.js
new file mode 100644
index 0000000..410cde8
--- /dev/null
+++ b/includes/js/dojo/tests/nls/en-us-texas/salutations.js
@@ -0,0 +1 @@
+({"hello":"Howdy","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/es/salutations.js b/includes/js/dojo/tests/nls/es/salutations.js
new file mode 100644
index 0000000..c460414
--- /dev/null
+++ b/includes/js/dojo/tests/nls/es/salutations.js
@@ -0,0 +1 @@
+({"es":"Español","hello":"Hola","hello_dojo":"¡${hello}, ${dojo}!","yi":"Yiddish","en-us-texas":"English (Texas)","de":"German","pl":"Polish","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/fa/salutations.js b/includes/js/dojo/tests/nls/fa/salutations.js
new file mode 100644
index 0000000..aaf73ee
--- /dev/null
+++ b/includes/js/dojo/tests/nls/fa/salutations.js
@@ -0,0 +1 @@
+({"hello":"درود","fa":"فارسی","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/fr/salutations.js b/includes/js/dojo/tests/nls/fr/salutations.js
new file mode 100644
index 0000000..9f81ca2
--- /dev/null
+++ b/includes/js/dojo/tests/nls/fr/salutations.js
@@ -0,0 +1 @@
+({"fr":"Français","hello":"Bonjour","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/he/salutations.js b/includes/js/dojo/tests/nls/he/salutations.js
new file mode 100644
index 0000000..859fedc
--- /dev/null
+++ b/includes/js/dojo/tests/nls/he/salutations.js
@@ -0,0 +1 @@
+({"he":"עברית","hello":"שלום","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/hi/salutations.js b/includes/js/dojo/tests/nls/hi/salutations.js
new file mode 100644
index 0000000..12b23a8
--- /dev/null
+++ b/includes/js/dojo/tests/nls/hi/salutations.js
@@ -0,0 +1 @@
+({"hello":"नमस्ते","hi":"हिन्दी","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/it/salutations.js b/includes/js/dojo/tests/nls/it/salutations.js
new file mode 100644
index 0000000..c3dd9cc
--- /dev/null
+++ b/includes/js/dojo/tests/nls/it/salutations.js
@@ -0,0 +1 @@
+({"it":"italiano","hello":"Ciao","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/ja/salutations.js b/includes/js/dojo/tests/nls/ja/salutations.js
new file mode 100644
index 0000000..5456efe
--- /dev/null
+++ b/includes/js/dojo/tests/nls/ja/salutations.js
@@ -0,0 +1 @@
+({"hello":"こにちは","ja":"日本語","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/ko/salutations.js b/includes/js/dojo/tests/nls/ko/salutations.js
new file mode 100644
index 0000000..4b43561
--- /dev/null
+++ b/includes/js/dojo/tests/nls/ko/salutations.js
@@ -0,0 +1 @@
+({"hello":"안녕","ko":"한국어","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/pl/salutations.js b/includes/js/dojo/tests/nls/pl/salutations.js
new file mode 100644
index 0000000..e4a9a2b
--- /dev/null
+++ b/includes/js/dojo/tests/nls/pl/salutations.js
@@ -0,0 +1 @@
+({"pl":"Polski","hello":"Dzièn dobry","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/pt/salutations.js b/includes/js/dojo/tests/nls/pt/salutations.js
new file mode 100644
index 0000000..7bc14c0
--- /dev/null
+++ b/includes/js/dojo/tests/nls/pt/salutations.js
@@ -0,0 +1 @@
+({"hello":"Olá","pt":"Português","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/ru/salutations.js b/includes/js/dojo/tests/nls/ru/salutations.js
new file mode 100644
index 0000000..07e53e2
--- /dev/null
+++ b/includes/js/dojo/tests/nls/ru/salutations.js
@@ -0,0 +1 @@
+({"ru":"русский","hello":"Привет","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/salutations.js b/includes/js/dojo/tests/nls/salutations.js
new file mode 100644
index 0000000..2ad7c40
--- /dev/null
+++ b/includes/js/dojo/tests/nls/salutations.js
@@ -0,0 +1 @@
+({"yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","hello":"Hello","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/sw/salutations.js b/includes/js/dojo/tests/nls/sw/salutations.js
new file mode 100644
index 0000000..5bde087
--- /dev/null
+++ b/includes/js/dojo/tests/nls/sw/salutations.js
@@ -0,0 +1 @@
+({"hello":"Hujambo","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/th/salutations.js b/includes/js/dojo/tests/nls/th/salutations.js
new file mode 100644
index 0000000..48ff292
--- /dev/null
+++ b/includes/js/dojo/tests/nls/th/salutations.js
@@ -0,0 +1 @@
+({"th":"ქართული ენაქართული ენაქართული ენაสวัสดีครับ/คะ","hello":"ภาษาไทย","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/tr/salutations.js b/includes/js/dojo/tests/nls/tr/salutations.js
new file mode 100644
index 0000000..785fb02
--- /dev/null
+++ b/includes/js/dojo/tests/nls/tr/salutations.js
@@ -0,0 +1 @@
+({"tr":"Türkçe","hello":"Merhaba","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/yi/salutations.js b/includes/js/dojo/tests/nls/yi/salutations.js
new file mode 100644
index 0000000..76187d9
--- /dev/null
+++ b/includes/js/dojo/tests/nls/yi/salutations.js
@@ -0,0 +1 @@
+({"yi":"ייִדיש","hello":"אַ גוטן טאָג","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/zh-cn/salutations.js b/includes/js/dojo/tests/nls/zh-cn/salutations.js
new file mode 100644
index 0000000..cf7500d
--- /dev/null
+++ b/includes/js/dojo/tests/nls/zh-cn/salutations.js
@@ -0,0 +1 @@
+({"zh-cn":"汉语","hello":"你好","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","zh-tw":"Chinese (Traditional)","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/nls/zh-tw/salutations.js b/includes/js/dojo/tests/nls/zh-tw/salutations.js
new file mode 100644
index 0000000..1b2a6ad
--- /dev/null
+++ b/includes/js/dojo/tests/nls/zh-tw/salutations.js
@@ -0,0 +1 @@
+({"zh-tw":"漢語","hello":"你好","yi":"Yiddish","en-us-texas":"English (Texas)","es":"Spanish","de":"German","pl":"Polish","hello_dojo":"${hello}, ${dojo}!","fa":"Farsi","pt":"Portugese","sw":"Kiswahili","ar":"Arabic","en-us-new_york-brooklyn":"English (Brooklynese)","ru":"Russian","fr":"French","th":"Thai","it":"Italian","he":"Hebrew","cs":"Czech","hi":"Hindi","en-us-hawaii":"English (US-Hawaii)","file_not_found":"The file you requested, ${0}, is not found.","en-au":"English (Australia)","el":"Greek","ko":"Korean","tr":"Turkish","en":"English","ja":"Japanese","zh-cn":"Chinese (Simplified)","dojo":"Dojo"}) \ No newline at end of file
diff --git a/includes/js/dojo/tests/number.js b/includes/js/dojo/tests/number.js
new file mode 100644
index 0000000..902484a
--- /dev/null
+++ b/includes/js/dojo/tests/number.js
@@ -0,0 +1,966 @@
+if(!dojo._hasResource["tests.number"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.number"] = true;
+dojo.provide("tests.number");
+
+dojo.require("dojo.number");
+
+/**
+ * Refer to ICU4J's NumberFormatTest.expect(...)
+ */
+tests.number.check=function(t,options,sourceInput,expectResult){
+ tests.number.checkFormatParseCycle(t, t,options,sourceInput,expectResult,false);
+ tests.number.checkParse(t, t,options,expectResult,sourceInput);
+}
+
+/**
+ * Perform a single formatting check or a backward check
+ * backward check:number1 -(formatted)-> string1 -(parsed)-> number2 -(formated)-> string2
+ * then number should == number2; string1 should == string2
+ */
+tests.number.checkFormatParseCycle=function(t,options,sourceInput,expectResult,
+ backwardCheck/*boolean,indicates whether need a backward chain check,like formate->parse->format*/){
+ if(null != options){
+ var pattern = options.pattern;
+ var locale = options.locale;
+ //TODO: add more fields
+ }
+
+ //print("\n");
+ var str = null==pattern?"default":pattern;
+ //print("pattern:" + str + "| locale:" + locale);
+ //print("input:" + sourceInput);
+ var result = dojo.number.format(sourceInput,options);
+ //print("result:" + result);
+ if(null != expectResult){
+ t.is(expectResult,result);
+ }
+ if(backwardCheck){
+ var resultParsed = dojo.number.parse(result,options);
+ //print("resultParsed:" + resultParsed);
+ if(!tests.number._decimalNumberDiff(sourceInput,resultParsed)){
+ t.is(sourceInput,resultParsed);
+ }
+ var resultParsedReformatted = dojo.number.format(resultParsed,options);
+ //print("resultParsedReformatted:" + resultParsedReformatted);
+ if(!tests.number._decimalNumberDiff(result,resultParsedReformatted)){
+ t.is(result,resultParsedReformatted);
+ }
+ }
+}
+
+/**
+ * Perform a single parsing check
+ */
+tests.number.checkParse=function(t,options,sourceInput,expectResult){
+ var str = "default";
+ if(null != options && null != options.pattern){
+ str = options.pattern;
+ }
+ //print("input:" + sourceInput);
+ var result = dojo.number.parse(sourceInput,options);
+ //print("result :" + result);
+ if(null != expectResult){
+ t.is(expectResult,result);
+ }
+}
+
+/**
+ * //TODO:Round a given number
+ */
+tests.number.rounding = function(t,number,maxFractionDigits,expected){
+ var pattern="#0.";
+ for(var i=0; i<maxFractionDigits; i++){pattern += "#";}
+ var result = dojo.number.format(number,{pattern:pattern});
+ t.is(expected,result);
+}
+
+/**
+ * Run a batch parsing
+ */
+function runBatchParse(options,dataArray/*array*/,pass/*boolean*/){
+ var exception = null;
+ var result;
+ var i=0;
+ var str = (null==options.pattern)?"default":options.pattern;
+
+ //print("\n");
+ for(; i<dataArray.length; i++){
+ try{
+ //print("["+i+"]"+"input:"+dataArray[i]);
+ result = dojo.number.parse(dataArray[i],options);
+ if(isNaN(result)){
+ throw "\"" + dataArray[i] + "\" is parsed to NaN with pattern " + str;
+ }
+ //print("["+i+"]"+"output:"+result);
+ }catch(e){
+ exception = e;
+ break;
+ }
+ }
+
+ if(!pass && (exception == null)) {
+ throw "runBatchParse() - stric parse failed, no exception when parsing illegal data";
+ }else if(exception != null){
+ if(!pass && i == 0){
+ //strict parsing should fail for all the dataArray elements as expected
+ //pass condition for strict parsing
+ return;
+ }
+ throw "runBatchParse() failed: " + exception;
+ }
+}
+
+/**
+ * Check whether the given two numbers differ under the decimal bound
+ *
+ */
+tests.number._decimalNumberDiff = function(num1,num2){
+ //TODO: should be more accurate when dojo.number finish rounding in the future
+ var diffBound = 1e-3;
+ var diff = num1 - num2;
+ //print("Math.abs(diff) " + Math.abs(diff));
+ if(Math.abs(diff) < diffBound ){
+ return true;
+ }else if(isNaN(Math.abs(diff))){
+ var s = num1.toString().split(num2);
+ s[1] = s[1].replace(",","0");
+ s[1] = s[1].replace('\u066b','0');
+ return (new Number(s[1])< diffBound);
+ }
+ return false;
+}
+
+tests.register("tests.number",
+ [
+ {
+ // Test formatting and parsing of currencies in various locales pre-built in dojo.cldr
+ // NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+ // load resources here for specific locales:
+
+ name: "number",
+ setUp: function(){
+ var partLocaleList = ["en-us", "fr-fr", "de-de"];
+
+ for(var i = 0 ; i < partLocaleList.length; i ++){
+ dojo.requireLocalization("dojo.cldr","number",partLocaleList[i], "zh-cn,zh,ko-kr,pt,en-us,en-gb,de,ja,ja-jp,en,ROOT,en-au,fr,es,ko,zh-tw,it,es-es,de-de");
+ }
+ },
+ runTest: function(t){
+ }
+ },
+ {
+ name: "format", // old tests
+ runTest: function(t){
+
+ t.is("0123", dojo.number.format(123, {pattern: "0000"}));
+ t.is("-12,34,567.890", dojo.number.format(-1234567.89, {pattern: "#,##,##0.000##"}));
+ t.is("-12,34,567.89012", dojo.number.format(-1234567.890123, {pattern: "#,##,##0.000##"}));
+ t.is("(1,234,567.89012)", dojo.number.format(-1234567.890123, {pattern: "#,##0.000##;(#,##0.000##)"}));
+ t.is("(1,234,567.89012)", dojo.number.format(-1234567.890123, {pattern: "#,##0.000##;(#)"}));
+ t.is("50.1%", dojo.number.format(0.501, {pattern: "#0.#%"}));
+ t.is("98", dojo.number.format(1998, {pattern: "00"}));
+ t.is("01998", dojo.number.format(1998, {pattern: "00000"}));
+ t.is("0.13", dojo.number.format(0.125, {pattern: "0.##"})); //NOTE: expects round_half_up, not round_half_even
+ t.is("0.1250", dojo.number.format(0.125, {pattern: "0.0000"}));
+ t.is("0.1", dojo.number.format(0.100004, {pattern: "0.####"}));
+
+ t.is("-12", dojo.number.format(-12.3, {places:0, locale: "en-us"}));
+ t.is("-1,234,567.89", dojo.number.format(-1234567.89, {locale: "en-us"}));
+// t.is("-12,34,567.89", dojo.number.format(-1234567.89, {locale: "en-in"}));
+ t.is("-1,234,568", dojo.number.format(-1234567.89, {places:0, locale: "en-us"}));
+// t.is("-12,34,568", dojo.number.format(-1234567.89, {places:0, locale: "en-in"}));
+ t.is("-1\xa0000,10", dojo.number.format(-1000.1, {places:2, locale: "fr-fr"}));
+ t.is("-1,000.10", dojo.number.format(-1000.1, {places:2, locale: "en-us"}));
+ t.is("-1\xa0000,10", dojo.number.format(-1000.1, {places:2, locale: "fr-fr"}));
+ t.is("-1.234,56", dojo.number.format(-1234.56, {places:2, locale: "de-de"}));
+ t.is("-1,000.10", dojo.number.format(-1000.1, {places:2, locale: "en-us"}));
+ t.is("123.46%", dojo.number.format(1.23456, {places:2, locale: "en-us", type: "percent"}));
+
+ //rounding
+ t.is("-1,234,568", dojo.number.format(-1234567.89, {places:0, locale: "en-us"}));
+// t.is("-12,34,568", dojo.number.format(-1234567.89, {places:0, locale: "en-in"}));
+ t.is("-1,000.11", dojo.number.format(-1000.114, {places:2, locale: "en-us"}));
+ t.is("-1,000.11", dojo.number.format(-1000.115, {places:2, locale: "en-us"}));
+ t.is("-1,000.12", dojo.number.format(-1000.116, {places:2, locale: "en-us"}));
+ t.is("-0.00", dojo.number.format(-0.0001, {places:2, locale: "en-us"}));
+ t.is("0.00", dojo.number.format(0, {places:2, locale: "en-us"}));
+
+ //change decimal places
+ t.is("-1\xa0000,100", dojo.number.format(-1000.1, {places:3, locale: "fr-fr"}));
+ t.is("-1,000.100", dojo.number.format(-1000.1, {places:3, locale: "en-us"}));
+ }
+ },
+ {
+ name: "parse", // old tests
+ runTest: function(t){
+ t.is(1000, dojo.number.parse("1000", {locale: "en-us"}));
+ t.is(1000.123, dojo.number.parse("1000.123", {locale: "en-us"}));
+ t.is(1000, dojo.number.parse("1,000", {locale: "en-us"}));
+ t.is(-1000, dojo.number.parse("-1000", {locale: "en-us"}));
+ t.is(-1000.123, dojo.number.parse("-1000.123", {locale: "en-us"}));
+ t.is(-1234567.89, dojo.number.parse("-1,234,567.89", {locale: "en-us"}));
+ t.is(-1234567.89, dojo.number.parse("-1 234 567,89", {locale: "fr-fr"}));
+ t.t(isNaN(dojo.number.parse("-1 234 567,89", {locale: "en-us"})));
+
+ t.t(isNaN(dojo.number.parse("10,00", {locale: "en-us"})));
+ t.t(isNaN(dojo.number.parse("1000.1", {locale: "fr-fr"})));
+
+ t.t(isNaN(dojo.number.parse("")));
+ t.t(isNaN(dojo.number.parse("abcd")));
+
+ //test whitespace
+// t.is(-1234567, dojo.number.parse(" -1,234,567 ", {locale: "en-us"}));
+
+// t.t(dojo.number.parse("9.1093826E-31"));
+ t.is(0.501, dojo.number.parse("50.1%", {pattern: "#0.#%"}));
+
+ t.is(123.4, dojo.number.parse("123.4", {pattern: "#0.#"}));
+ t.is(-123.4, dojo.number.parse("-123.4", {pattern: "#0.#"}));
+ t.is(123.4, dojo.number.parse("123.4", {pattern: "#0.#;(#0.#)"}));
+ t.is(-123.4, dojo.number.parse("(123.4)", {pattern: "#0.#;(#0.#)"}));
+
+ t.is(null, dojo.number.format("abcd", {pattern: "0000"}));
+
+ t.is(123, dojo.number.parse("123", {places:0}));
+ t.is(123, dojo.number.parse("123", {places:'0'}));
+ t.is(123.4, dojo.number.parse("123.4", {places:1}));
+ t.is(123.45, dojo.number.parse("123.45", {places:'1,3'}));
+ t.is(123.45, dojo.number.parse("123.45", {places:'0,2'}));
+ }
+ },
+ {
+ name: "format_icu4j3_6",
+ runTest: function(t){
+
+/*************************************************************************************************
+ * Evan:The following test cases are referred from ICU4J 3.6 (NumberFormatTest etc.)
+ * see http://icu.sourceforge.net/download/3.6.html#ICU4J
+ *************************************************************************************************/
+
+
+/**
+ * In ICU4J, testing logic for NumberFormat.format() is seperated into
+ * differernt single tese cases. So part of these logic are
+ * collected together in this single method.
+ *
+ * !!Failed cases are as follows:
+ * 1.1234567890987654321234567890987654321 should be formatted as
+ * 1,234,567,890,987,654,321,234,567,890,987,654,321 with all the default parameters,
+ * but got 1.234 instead, may due to the unimplemeted exponent.
+ * 2.\u00a4 and ' are not replaced
+ * with pattern "'*&'' '\u00a4' ''&*' #,##0.00"
+ * 1.0 should be formatted to "*&' Re. '&* 1.00",but got "'*&'' '\u00a4' ''&*' 1.00" instead
+ * etc.
+ *
+ */
+ //print("test_number_format_icu4j3_6() start..............");
+ /* !!Failed case, 1.234 returned instead
+ //refer to ICU4J's NumberFormatTest.TestCoverage()
+ var bigNum = 1234567890987654321234567890987654321;
+ var expectResult = "1,234,567,890,987,654,321,234,567,890,987,654,321";
+ tests.number.checkFormatParseCycle(t, null,bigNum,expectResult,false);
+ */
+
+ //in icu4j should throw out an exception when formatting a string,
+ //but it seems dojo.number.format can deal with strings
+ //return 123,456,789
+ dojo.number.format("123456789");
+
+ //!!Failed case, \u00a4 and ' are not replaced
+ /*
+ var options = {pattern:"'*&'' '\u00a4' ''&*' #,##0.00",locale:"en-us"};
+ tests.number.check(t, options,1.0, "*&' Re. '&* 1.00");
+ tests.number.check(t, options,-2.0, "-*&' Rs. '&* 2.00");
+
+ options = {pattern:"#,##0.00 '*&'' '\u00a4' ''&*'",locale:"en-us"};
+ tests.number.check(t, options,1.0,"1.00 *&' Re. '&*");
+ tests.number.check(t, options,-2.0,"-2.00 *&' Rs. '&*");
+ */
+ //print("test_number_format_icu4j3_6() end..............\n");
+ }
+ },
+ {
+ name: "format_patterns",
+ runTest: function(t){
+
+/**
+ * Refer to ICU4J's NumberFormatTest.TestPatterns() which now only coveres us locale
+ */
+ //print("test_number_format_Patterns() start..............");
+ var patterns = (["#0.#", "#0.", "#.0", "#"]);
+ var patternsLength = patterns.length;
+ var num = (["0","0", "0.0", "0"]);
+ var options;
+ //icu4j result seems doesn't work as:
+ //var num = (["0","0.", ".0", "0"]);
+ for (var i=0; i<patternsLength; ++i)
+ {
+ options = {pattern:patterns[i]};
+ tests.number.checkFormatParseCycle(t, options,0,num[i],false);
+ }
+
+ //!!Failed case
+ //In ICU4J:
+ // unquoted special characters in the suffix are illegal
+ // so "000.000|###" is illegal; "000.000'|###'" is legal
+ //dojo.number.format:
+ // when formatting 1.2 with illegal pattern "000.000|###"
+ // no exception was thrown but got "001.200|###" instead.
+
+ /*
+ patterns = (["000.000|###","000.000'|###'"]);
+ var exception = false;
+ var result;
+ for(var i = 0; i < patterns.length; i ++){
+ try{
+ //"001.200'|###'" is return for "000.000'|###'"
+ //"001.200|###" is return for "000.000|###"
+ result = dojo.number.format(1.2,{pattern:patterns[i]});
+ print("["+i+"] 1.2 is formatted to " + result + " with pattern " + patterns[i]);
+ }catch(e){
+ exception = true;
+ }
+ if(exception && i==1){
+ throw "["+i+"]Failed when formatting 1.2 using legal pattern " + patterns[i];
+ }else if(!exception && i==0){
+ throw "["+i+"]Failed when formatting 1.2 using illegal pattern " + patterns[i];
+ }
+ }*/
+ //print("test_number_format_Patterns() end..............\n");
+ }
+ },
+ {
+ name: "exponential",
+ runTest: function(t){
+/**
+ * TODO: For dojo.number future version
+ * Refer to ICU4J's NumberFormatTest.TestExponential()
+ */
+ }
+ },
+ {
+ name: "format_quotes",
+ runTest: function(t){
+/**
+ * TODO: Failed case
+ * Refer to ICU4J's NumberFormatTest.TestQuotes()
+ */
+ //print("test_number_format_Quotes() start..............");
+ //TODO: add more locales
+
+ //TODO:!!Failed case
+ //Pattern "s'aa''s'c#" should format 6666 to "saa'sc6666", but got s'aa''s'c6666 instead
+ // is this case necessary?
+ /*
+ var pattern = "s'aa''s'c#";
+ var result = dojo.number.format(6666,{pattern:pattern,locale:"en-us"});
+ var expectResult = "saa'sc6666";
+ t.is(expectResult,result);
+ */
+ //print("test_number_format_Quotes() end..............");
+ }
+ },
+ {
+ name: "format_rounding",
+ runTest: function(t){
+/**
+ * Refer to ICU4J's NumberFormatTest.TestRounding487() and NumberFormatTest.TestRounding()
+ */
+ //print("test_number_format_rounding() start..............");
+ tests.number.rounding(t,0.000179999, 5, "0.00018");
+ tests.number.rounding(t,0.00099, 4, "0.001");
+ tests.number.rounding(t,17.6995, 3, "17.7");
+ tests.number.rounding(t,15.3999, 0, "15");
+ tests.number.rounding(t,-29.6, 0, "-30");
+
+ //TODO refer to NumberFormatTest.TestRounding()
+
+ //print("test_number_format_rounding() end..............");
+ }
+ },
+ {
+ name: "format_scientific",
+ runTest: function(t){
+/**
+ * TODO: For dojo.number future version
+ * Refer to ICU4J's NumberFormatTest.TestScientific()- Exponential testing
+ * Refer to ICU4J's NumberFormatTest.TestScientific2()
+ * Refer to ICU4J's NumberFormatTest.TestScientificGrouping()
+ */
+ }
+ },
+ {
+ name: "format_perMill",
+ runTest: function(t){
+/**
+ * TODO: Failed case
+ * Refer to ICU4J's NumberFormatTest.TestPerMill()
+ */
+ //print("test_number_format_PerMill() start..............");
+ var pattern;
+ var result;
+ var expectResult;
+
+ //TODO: !!Failed case - ###.###\u2030(\u2030 is ‰)
+ //Pattern ###.###\u2030 should format 0.4857 as 485.7\u2030,but got 485.700\u2030 instead
+ pattern = "###.###\u2030";
+ expectResult = "485.7\u2030";
+ result = dojo.number.format(0.4857,{pattern:pattern});
+ t.is(expectResult,result);
+
+ //TODO: !!Failed mile percent case - ###.###m
+ //Pattern "###.###m" should format 0.4857 to 485.7m, but got 0.485m instead
+ /*
+ pattern = "###.###m";
+ expectResult = "485.7m";
+ result = dojo.number.format(0.4857,{pattern:pattern,locale:"en"});
+ t.is(expectResult,result);
+ */
+ //print("test_number_format_PerMill() end..............\n");
+ }
+ },
+ {
+ name: "format_grouping",
+ runTest: function(t){
+/**
+ * Only test en-us and en-in
+ * Refer to ICU4J's NumberFormatTest.TestSecondaryGrouping()
+ */
+ //print("test_number_format_Grouping() start..............");
+ //primary grouping
+ var sourceInput = 123456789;
+ var expectResult = "12,34,56,789";
+ var options = {pattern:"#,##,###",locale:"en-us"};
+
+ //step1: 123456789 formated=> 12,34,56,789
+ //step2:12,34,56,789 parsed=> 123456789 => formated => 12,34,56,789
+ tests.number.checkFormatParseCycle(t, options,sourceInput,expectResult,true);
+
+ //TODO: sencondary grouping not implemented yet ?
+ //Pattern "#,###" and secondaryGroupingSize=4 should format 123456789 to "12,3456,789"
+
+ //Special case for "en-in" locale
+ //1876543210 should be formated as 1,87,65,43,210 in "en-in" (India)
+/*
+ sourceInput = 1876543210;
+ expectResult = "1,87,65,43,210";
+ var result = dojo.number.format(sourceInput,{locale:"en-in"});
+ t.is(expectResult,result);
+*/
+ //print("test_number_format_Grouping() end..............\n");
+ }
+ },
+ {
+ name: "format_pad",
+ runTest: function(t){
+/**
+ * TODO:!!Failed cases:
+ * According to ICU4J test criteria:
+ * 1.with pattern "*^##.##":
+ * 0 should be formatted to "^^^^0",but got "*^0" instead,
+ * -1.3 should be formatted to "^-1.3",but got "-*^1.3" instead.
+ *
+ * 2.with pattern "##0.0####*_ 'g-m/s^2'" :
+ * 0 should be formatted to "0.0______ g-m/s^2",but got ":0.0*_ 'g-m/s^2'" instead
+ * 1.0/3 should be formatted to "0.33333__ g-m/s^2",but got "0.33333*_ 'g-m/s^2'" instead
+ *
+ * 3.with pattern "*x#,###,###,##0.0#;*x(###,###,##0.0#)":
+ * -10 should be formatted to "xxxxxxxxxx(10.0)",but got "*x(10.0)" instead.
+ * 10 should be formatted to "xxxxxxxxxxxx10.0",but got "*x10.0" instead.
+ * ......
+ * -1120456.37 should be formatted to "xx(1,120,456.37)",but got "*x(1,120,456.37)" instead.
+ * 1120456.37 should be formatted to "xxxx1,120,456.37",but got "*x1,120,456.37" instead.
+ * -1252045600.37 should be formatted to "(1,252,045,600.37)",but got "*x(1,252,045,600.37)" instead.
+ * 1252045600.37 should be formatted to "10,252,045,600.37",but got "*x10,252,045,600.37" instead.
+ *
+ * 4.with pattern "#,###,###,##0.0#*x;(###,###,##0.0#*x)"
+ * -10 should be formatted to (10.0xxxxxxxxxx),but got "(10.0*x)" instead.
+ * 10 should be formatted to "10.0xxxxxxxxxxxx",but got "10.0*x" instead.
+ * ......
+ * -1120456.37 should be formatted to "(1,120,456.37xx)",but got "(1,120,456.37*x)" instead.
+ * 1120456.37 should be formatted to "xxxx1,120,456.37",but got "1,120,456.37*x" instead.
+ * -1252045600.37 should be formatted to "(1,252,045,600.37)",but got "(1,252,045,600.37*x)" instead.
+ * 1252045600.37 should be formatted to ""10,252,045,600.37"",but got "10,252,045,600.37*x" instead.*
+ *
+ * Refer to ICU4J's NumberFormatTest.TestPad()
+ */
+/*
+function test_number_format_pad(){
+ var locale = "en-us";
+ print("test_number_format_Pad() start..............");
+ var options = {pattern:"*^##.##",locale:locale};
+
+ tests.number.check(t, options,0,"^^^^0");
+ tests.number.check(t, options,-1.3,"^-1.3");
+
+
+ options = {pattern:"##0.0####*_ 'g-m/s^2'",locale:locale};
+ tests.number.check(t, options,0,"0.0______ g-m/s^2");
+ tests.number.checkFormatParseCycle(t, options,1.0/3,"0.33333__ g-m/s^2",true);
+
+ //exponent not implemented
+ //options = {pattern:"##0.0####E0*_ 'g-m/s^2'",locale:locale};
+ //tests.number.check(t, options,0,"0.0E0______ g-m/s^2");
+ //tests.number.checkFormatParseCycle(t, options,1.0/3,"333.333E-3_ g-m/s^2",true);
+
+ // Test padding before a sign
+ options = {pattern:"*x#,###,###,##0.0#;*x(###,###,##0.0#)",locale:locale};
+
+ tests.number.check(t, options,-10,"xxxxxxxxxx(10.0)");
+ tests.number.check(t, options,-1000, "xxxxxxx(1,000.0)");
+ tests.number.check(t, options,-1000000, "xxx(1,000,000.0)");
+ tests.number.check(t, options,-100.37, "xxxxxxxx(100.37)");
+ tests.number.check(t, options,-10456.37, "xxxxx(10,456.37)");
+ tests.number.check(t, options,-1120456.37, "xx(1,120,456.37)");
+ tests.number.check(t, options,-112045600.37, "(112,045,600.37)");
+ tests.number.check(t, options,-1252045600.37, "(1,252,045,600.37)");
+
+
+ tests.number.check(t, options,10, "xxxxxxxxxxxx10.0");
+ tests.number.check(t, options,1000, "xxxxxxxxx1,000.0");
+ tests.number.check(t, options,1000000, "xxxxx1,000,000.0");
+ tests.number.check(t, options,100.37, "xxxxxxxxxx100.37");
+ tests.number.check(t, options,10456.37, "xxxxxxx10,456.37");
+ tests.number.check(t, options,1120456.37, "xxxx1,120,456.37");
+ tests.number.check(t, options,112045600.37, "xx112,045,600.37");
+ tests.number.check(t, options,10252045600.37, "10,252,045,600.37");
+
+ // Test padding between a sign and a number
+ options = {pattern:"#,###,###,##0.0#*x;(###,###,##0.0#*x)",locale:locale};
+ tests.number.check(t, options, -10, "(10.0xxxxxxxxxx)");
+ tests.number.check(t, options, -1000, "(1,000.0xxxxxxx)");
+ tests.number.check(t, options, -1000000, "(1,000,000.0xxx)");
+ tests.number.check(t, options, -100.37, "(100.37xxxxxxxx)");
+ tests.number.check(t, options, -10456.37, "(10,456.37xxxxx)");
+ tests.number.check(t, options, -1120456.37, "(1,120,456.37xx)");
+ tests.number.check(t, options, -112045600.37, "(112,045,600.37)");
+ tests.number.check(t, options, -1252045600.37, "(1,252,045,600.37)");
+
+ tests.number.check(t, options, 10, "10.0xxxxxxxxxxxx");
+ tests.number.check(t, options, 1000, "1,000.0xxxxxxxxx");
+ tests.number.check(t, options, 1000000, "1,000,000.0xxxxx");
+ tests.number.check(t, options, 100.37, "100.37xxxxxxxxxx");
+ tests.number.check(t, options, 10456.37, "10,456.37xxxxxxx");
+ tests.number.check(t, options, 1120456.37, "1,120,456.37xxxx");
+ tests.number.check(t, options, 112045600.37, "112,045,600.37xx");
+ tests.number.check(t, options, 10252045600.37, "10,252,045,600.37");
+
+ //Not implemented yet,refer to NumberFormatTest.TestPatterns2()
+ //For future use - maily test pad patterns
+ print("test_number_format_Pad() end..............");
+}
+*/
+ }
+ },
+ {
+ name: "parse_icu4j3_6",
+ runTest: function(t){
+/**
+ * In ICU4J, testing logic for NumberFormat.parse() is seperated into
+ * differernt single tese cases. So part of these logic are
+ * collected together in this test case. *
+ */
+ //print("test_number_parse_icu4j3_6() start..............");
+ //Refer to ICU4J's NumberFormatTest.TestParse() which is only a rudimentary version
+ var pattern = "00";
+ var str = "0.0";
+ var result = dojo.number.parse(str,{pattern:pattern});
+ //TODO: add more locales
+//FIXME: is this a valid test?
+// t.is(0,result);
+
+ /**************************************** tolerant parse *****************************************
+ * refers to ICU4J's NumberFormatTest.TestStrictParse()??
+ * TODO: Seems dojo.number parses string in a tolerant way.
+ */
+ var options = {locale:"en-us"};
+ /*
+ * TODO: !!Failed case,Should all pass,
+ * but the following elements failed (all parsed to NaN):
+ * [1]-"0 ",[2]-"0.",[3]-"0,",[5]-"0. ",[6]-"0.100,5",
+ * [7]-".00",[9]-"12345, ",[10]-"1,234, ",[12]-"0E"
+ */
+ var passData = ([
+ "0", //[0] single zero before end of text is not leading
+ //"0 ", //[1] single zero at end of number is not leading
+ //"0.", //[2] single zero before period (or decimal, it's ambiguous) is not leading
+ //"0,", //[3] single zero before comma (not group separator) is not leading
+ "0.0", //[4] single zero before decimal followed by digit is not leading
+ //"0. ", //[5] same as above before period (or decimal) is not leading
+ //"0.100,5", //[6] comma stops parse of decimal (no grouping)
+ //".00", //[7] leading decimal is ok, even with zeros
+ "1234567", //[8] group separators are not required
+ //"12345, ", //[9] comma not followed by digit is not a group separator, but end of number
+ //"1,234, ", //[10] if group separator is present, group sizes must be appropriate
+ "1,234,567" //[11] ...secondary too
+ //,"0E" //[12]not implemented yet,an exponnent not followed by zero or digits is not an exponent
+ ]);
+ runBatchParse(options,passData,true/*tolerant parse*/);
+
+ /*
+ * TODO:!!Failed case,should all pass,
+ * but the following failed,
+ * [10]-"1,45 that" implies that we partially parse input
+ */
+ var failData = ([
+ "00", //[0] leading zero before zero
+ "012", //[1] leading zero before digit
+ "0,456", //[2] leading zero before group separator
+ "1,2", //[3] wrong number of digits after group separator
+ ",0", //[4] leading group separator before zero
+ ",1", //[5] leading group separator before digit
+ ",.02", //[6] leading group separator before decimal
+ "1,.02", //[7] group separator before decimal
+ "1,,200", //[8] multiple group separators
+ "1,45", //[9] wrong number of digits in primary group
+ //"1,45 that", //[10] wrong number of digits in primary group
+ "1,45.34", //[11] wrong number of digits in primary group
+ "1234,567", //[12] wrong number of digits in secondary group
+ "12,34,567", //[13] wrong number of digits in secondary group
+ "1,23,456,7890" //[14] wrong number of digits in primary and secondary groups
+ ]);
+ runBatchParse(options,failData,false);
+
+ options = {pattern:"#,##,##0.#",locale:"en-us"};
+ /*
+ * TODO:!!Failed case,shoudl all pass.
+
+ * but [1] [2] and [3] failed
+ * should be parsed to 1234567,but NaN instead
+ */
+ var mixedPassData = ([
+ "12,34,567" //[0]
+ //,"12,34,567," //[1]
+ //"12,34,567, that",//[2]
+ //"12,34,567 that" //[3]
+ ]);
+ runBatchParse(options,mixedPassData,true/*tolerant parse*/);
+
+ /*
+ * TODO:!!Failed case,should all pass,
+ * but actually mixedFailData[2] and mixedFailData[3] passed.
+ * "12,34,56, that " and [3]-"12,34,56 that" should be parsed to 123456,but NaN instead
+ */
+ var mixedFailData = ([
+ "12,34,56", //[0]
+ "12,34,56," //[1]
+ //,"12,34,56, that ",//[2]
+ //"12,34,56 that", //[3]
+ ]);
+ runBatchParse(options,mixedFailData,false);
+
+
+ /**************************************** strict parse ******************************************
+ * TODO:May need to test strict parsing in the future?
+ * e.g. A strict parsing like (with pattern "#,##0.#")
+ * 1.Leading zeros
+ * '00', '0123' fail the parse, but '0' and '0.001' pass
+ * 2.Leading or doubled grouping separators
+ * ',123' and '1,,234" fail
+ * 3.Groups of incorrect length when grouping is used
+ * '1,23' and '1234,567' fail, but '1234' passes
+ * 4.Grouping separators used in numbers followed by exponents
+ * '1,234E5' fails, but '1234E5' and '1,234E' pass
+ */
+ //options={locale:"en",strict:true};
+ //runBatchParse(options,passData,false/*strict parse*/);
+ //runBatchParse(options,failData,false/*strict parse*/);
+
+ //options = {pattern:"#,##,##0.#",locale:"en-us",strict:true};
+ //runBatchParse(options,mixedPassData,false/*strict parse*/);
+ //runBatchParse(options,mixedFailData,false/*strict parse*/);
+
+ //print("test_number_parse_icu4j3_6() end..............\n");
+ }
+ },
+ {
+ name: "parse_whitespace",
+ runTest: function(t){
+/**
+ * TODO:!!Failed case
+ * With pattern "a b#0c ",both "a b3456c " and and "a b1234c " should be parsed to 3456,but got NaN instead.
+ *
+ * Refer to ICU4J's NumberFormatTest.TestWhiteSpaceParsing
+ */
+ /*
+ print("test_number_parse_WhiteSpace() start..............");
+ var pattern = "a b#0c ";
+ var expectResult = 3456;
+ result = dojo.number.parse("a b3456c ",{pattern:pattern,locale:"en-us"});
+ t.is(expectResult,result);
+ result = dojo.number.parse("a b3456c ",{pattern:pattern,locale:"en-us"});
+ t.is(expectResult,result);
+ print("test_number_parse_WhiteSpace() end..............\n");
+ */
+ }
+ },
+/*************************************************************************************************
+ * Regression test cases
+ * These test cases are referred to ICU4J's NumberFormatRegressionTest and NumberFormatRegression.
+ * The regression cases in ICU4J are used as unit test cases for bug fixing,
+ * They are inluced here so that dojo.number may avoid those similar bugs.
+ *************************************************************************************************/
+ {
+ name: "number_regression_1",
+ runTest: function(t){
+/**
+ * Refer to ICU4J's NumberFormatRegressionTest.Test4161100()
+ */
+ tests.number.checkFormatParseCycle(t, {pattern:"#0.#"},-0.09,"-0.1",false);
+ }
+ },
+ {
+ name: "number_regression_2",
+ runTest: function(t){
+/**
+ * !!Failed case,rounding hasn't been implemented yet.
+ * Refer to ICU4J's NumberFormatRegressionTest.Test4408066()
+ */
+ /*
+ var data = ([-3.75, -2.5, -1.5,
+ -1.25, 0, 1.0,
+ 1.25, 1.5, 2.5,
+ 3.75, 10.0, 255.5]);
+ var expected = (["-4", "-2", "-2",
+ "-1", "0", "1",
+ "1", "2", "2",
+ "4", "10", "256"]);
+ var options = {locale:"zh-cn",round:true};
+ for(var i =0; i < data.length; i++){
+ tests.number.checkFormatParseCycle(t, options,data[i],expected[i],false);
+ }
+
+ data = ([ "-3.75", "-2.5", "-1.5",
+ "-1.25", "0", "1.0",
+ "1.25", "1.5", "2.5",
+ "3.75", "10.0", "255.5"]);
+ expected =([ -3, -2, -1,
+ -1, 0, 1,
+ 1, 1, 2,
+ 3, 10, 255]);
+
+ for(var i =0; i < data.length; i++){
+ tests.number.checkParse(t, options,data[i],expected[i]);
+ }
+ */
+ }
+ },
+ {
+ name: "number_regression_3",
+ runTest: function(t){
+/**
+ * Refer to ICU4J's NumberRegression.Test4087535() and Test4243108()
+ */
+ tests.number.checkFormatParseCycle(t, {places:0},0,"0",false);
+ //TODO:in icu4j,0.1 should be formatted to ".1" when minimumIntegerDigits=0
+ tests.number.checkFormatParseCycle(t, {places:0},0.1,"0",false);
+ tests.number.checkParse(t, {pattern:"#0.#####"},123.55456,123.55456);
+//!! fails because default pattern only has 3 decimal places
+// tests.number.checkParse(t, null,123.55456,123.55456);
+
+ //See whether it fails first format 0.0 ,parse "99.99",and then reformat 0.0
+ tests.number.checkFormatParseCycle(t, {pattern:"#.#"},0.0,"0",false);
+ tests.number.checkParse(t, null,"99.99",99.99);
+ tests.number.checkFormatParseCycle(t, {pattern:"#.#"},0.0,"0",false);
+ }
+ },
+ {
+ name: "number_regression_4",
+ runTest: function(t){
+/**
+ * TODO:
+ * In ICU -0.0 and -0.0001 should be formatted to "-0" with FieldPosition(0)
+ * dojo.i18n.number format -0.0 to "-0"; -0.0001 to "-0.000100"
+ *
+ * Refer to ICU4J's NumberRegression.Test4088503() and Test4106658()
+ */
+ tests.number.checkFormatParseCycle(t, {places:0},123,"123",false);
+
+ //TODO: differernt from ICU where -0.0 is formatted to "-0"
+ tests.number.checkFormatParseCycle(t, {locale:"en-us"},-0.0,"0",false);
+
+ //TODO: differernt from ICU where -0.0001 is formatted to "-0"
+ tests.number.checkFormatParseCycle(t, {locale:"en-us",places:6},-0.0001,"-0.000100",false);
+ }
+ },
+ {
+ name: "number_regression_5",
+ runTest: function(t){
+/**
+ * !!Failed case,rounding has not implemented yet.
+ * 0.00159999 should be formatted as 0.0016 but got 0.0015 instead.
+ * Refer to ICU4J's NumberRegression.Test4071492()
+ */
+ //tests.number.checkFormatParseCycle(t, {places:4,round:true},0.00159999,"0.0016",false);
+ }
+ },
+ {
+ name: "number_regression_6",
+ runTest: function(t){
+/**
+ * Refer to ICU4J's NumberRegression.Test4086575()
+ */
+ var pattern = "###.00;(###.00)";
+ var locale = "fr";
+ var options = {pattern:pattern,locale:locale};
+
+ //no group separator
+ tests.number.checkFormatParseCycle(t, options,1234,"1234,00",false);
+ tests.number.checkFormatParseCycle(t, options,-1234,"(1234,00)",false);
+
+ //space as group separator
+ pattern = "#,###.00;(#,###.00)";
+ options = {pattern:pattern,locale:locale};
+ tests.number.checkFormatParseCycle(t, options,1234,"1\u00a0234,00",false);// Expect 1 234,00
+ tests.number.checkFormatParseCycle(t, options,-1234,"(1\u00a0234,00)",false); // Expect (1 234,00)
+ }
+ },
+ {
+ name: "number_regression_7",
+ runTest: function(t){
+/**
+ * !!Failed case - expontent has not implemented yet
+ * shuold format 1.000000000000001E7 to 10000000.00000001, but got 10,000,000.000 instead
+ * Refer to ICU4J's NumberRegression.Test4090489() - loses precision
+ */
+ //tests.number.checkFormatParseCycle(t, null,1.000000000000001E7,"10000000.00000001",false);
+ }
+ },
+ {
+ name: "number_regression_8",
+ runTest: function(t){
+/**
+ * !!Failed case
+ * 1.with pattern "#,#00.00 p''ieces;-#,#00.00 p''ieces"
+ * 3456.78 should be formated to "3,456.78 p'ieces",
+ * but got "3,456.78 p''ieces","''" should be replaced with "'"
+ * 2.with illegal pattern "000.0#0"
+ * no error for the illegal pattern, and 3456.78 is formatted to 456.780
+ * 3.with illegal pattern "0#0.000"
+ * no error for the illegal pattern, and 3456.78 is formatted to 3456.780
+ *
+ * Refer to ICU4J's NumberRegression.Test4092480(),Test4074454()
+ */
+ var patterns = (["#0000","#000","#00","#0","#"]);
+ var expect = (["0042","042","42","42","42"]);
+
+ for(var i =0; i < patterns.length; i ++){
+ tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},42,expect[i],false);
+ tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},-42,"-"+expect[i],false);
+ }
+
+ tests.number.checkFormatParseCycle(t, {pattern:"#,#00.00;-#.#"},3456.78,"3,456.78",false);
+ //!!Failed case
+ //tests.number.checkFormatParseCycle(t, {pattern:"#,#00.00 p''ieces;-#,#00.00 p''ieces"},3456.78,"3,456.78 p'ieces",false);
+ //tests.number.checkFormatParseCycle(t, {pattern:"000.0#0"},3456.78,null,false);
+ //tests.number.checkFormatParseCycle(t, {pattern:"0#0.000"},3456.78,null,false);
+ }
+ },
+ {
+ name: "number_regression_9",
+ runTest: function(t){
+/**
+ * TODO
+ * Refer to ICU4J's NumberRegression.Test4052223()
+ */
+ //TODO:only got NaN,need an illegal pattern exception?
+ tests.number.checkParse(t, {pattern:"#,#00.00"},"abc3");
+
+ //TODO: got NaN instead of 1.222, is it ok?
+ //tests.number.checkParse(t, {pattern:"#,##0.###",locale:"en-us"},"1.222,111",1.222);
+ //tests.number.checkParse(t, {pattern:"#,##0.###",locale:"en-us"},"1.222x111",1.222);
+
+ //got NaN for illeal input,ok
+ tests.number.checkParse(t, null,"hello: ,.#$@^&**10x");
+ }
+ },
+ {
+ name: "number_regression_10",
+ runTest: function(t){
+/**
+ * Refer to ICU4J's NumberRegression.Test4125885()
+ */
+ tests.number.checkFormatParseCycle(t, {pattern:"000.00"},12.34,"012.34",false);
+ tests.number.checkFormatParseCycle(t, {pattern:"+000.00%;-000.00%"},0.1234,"+012.34%",false);
+ tests.number.checkFormatParseCycle(t, {pattern:"##,###,###.00"},9.02,"9.02",false);
+
+ var patterns =(["#.00", "0.00", "00.00", "#0.0#", "#0.00"]);
+ var expect = (["1.20", "1.20", "01.20", "1.2", "1.20" ]);
+ for(var i =0 ; i < patterns.length; i ++){
+ tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},1.2,expect[i],false);
+ }
+ }
+ },
+ {
+ name: "number_regression_11",
+ runTest: function(t){
+/**
+ * TODO:!!Failed case
+ * Make sure that all special characters, when quoted in a suffix or prefix, lose their special meaning.
+ * The detail error info :
+ * for input 123
+ * pattern:'0'#0'0'; expect:"01230"; but got "'3'#0'0'" instead
+ * pattern:','#0','; expect:",123,"; but got "','123','" instead
+ * pattern:'.'#0'.'; expect:".123."; but got "'.'123'.'" instead
+ * pattern:'‰'#0'‰'; expect:"‰123‰"; but got "'‰'123000'‰'" instead
+ * pattern:'%'#0'%'; expect:"%123%"; but got "'%'12300'%'" instead
+ * pattern:'#'#0'#'; expect:"#123#"; but got "'123'#0'#'" instead
+ * pattern:';'#0';'; expect:";123;"; but got "[dojo-test] FATAL exception raised:
+ * unable to find a number expression in pattern: '"
+ * pattern:'E'#0'E'; expect:"E123E"; not implemeted yet
+ * pattern:'*'#0'*'; expect:"*123*"; but got "'*'123'*'" instead
+ * pattern:'+'#0'+'; expect:"+123+"; but got "'+'123'+'" instead
+ * pattern:'-'#0'-'; expect:"-123-"; but got "'-'123'-'" instead
+ *
+ * TODO: is it ok to remain "'" in the formatted result as above??
+ *
+ * Refer to ICU4J's NumberRegression.Test4212072()
+ */
+/*
+ var specials = ([ '0', ',', '.', '\u2030', '%', '#',';', 'E', '*', '+', '-']);
+ var pattern;
+ var expect;
+
+ for(var i=0; i < specials.length; i ++){
+ pattern = "'" + specials[i] + "'#0'" + specials[i] + "'";
+ expect = "" + specials[i] + "123" + specials[i];
+ tests.number.checkFormatParseCycle(t, {pattern:pattern,locale:"en-us"},123,expect,false);
+ }
+*/
+ }
+ },
+ {
+ name: "number_regression_12",
+ runTest: function(t){
+/**
+ * TODO: add more rounding test cases, refer to ICU4J's NumberRegression.Test4071005(),Test4071014() etc..
+ */
+
+/**
+ * TODO:Decimal format doesnt round a double properly when the number is less than 1
+ *
+ * Refer to ICU4J's NumberRegression.test4241880()
+ */
+/*
+ var input = ([ .019, .009, .015, .016, .014,
+ .004, .005, .006, .007, .008,
+ .5, 1.5, .05, .15, .005,
+ .015, .0005, .0015]);
+ var patterns = (["##0%", "##0%", "##0%", "##0%", "##0%",
+ "##0%", "##0%", "##0%", "##0%", "##0%",
+ "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00",
+ "#,##0.00", "#,##0.000", "#,##0.000"]);
+ var expect =([ "2%", "1%", "2%", "2%", "1%",
+ "0%", "0%", "1%", "1%", "1%",
+ "0", "2", "0.0", "0.2", "0.00",
+ "0.02", "0.000", "0.002",]);
+ for(var i = 0; i <input.length; i ++){
+ tests.number.checkFormatParseCycle(t, {pattern:patterns[i],round:true},input[i],expect[i],false);
+ }
+*/
+ }
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/parser.html b/includes/js/dojo/tests/parser.html
new file mode 100644
index 0000000..8d7565b
--- /dev/null
+++ b/includes/js/dojo/tests/parser.html
@@ -0,0 +1,241 @@
+<html>
+ <head>
+ <title>Parser Unit Test</title>
+ <style type="text/css">
+ @import "../resources/dojo.css";
+ </style>
+ <script type="text/javascript"
+ src="../dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("doh.runner");
+
+ dojo.declare("tests.parser.Class1", null, {
+ constructor: function(args, node){ dojo.mixin(this, args); },
+ preambleTestProp: 1,
+ preamble: function(){
+ this.preambleTestProp++;
+ },
+ intProp: 1,
+ callCount: 0, // for connect testing
+ callInc: function(){ this.callCount++; },
+ callCount2: 0, // for assignment testing
+ strProp1: "original1",
+ strProp2: "original2",
+ arrProp: [],
+ boolProp1: false,
+ boolProp2: true,
+ boolProp3: false,
+ boolProp4: true,
+ dateProp1: dojo.date.stamp.fromISOString('2007-01-01'),
+ dateProp2: dojo.date.stamp.fromISOString('2007-01-01'),
+ dateProp3: dojo.date.stamp.fromISOString('2007-01-01'),
+ funcProp: function(){},
+ funcProp2: function(){},
+ funcProp3: function(){},
+ onclick: function(){ this.prototypeOnclick=true; }
+ // FIXME: have to test dates!!
+ // FIXME: need to test the args property!!
+ });
+
+ dojo.declare("tests.parser.Class2", null, {
+ constructor: function(){
+ this.fromMarkup = false;
+ },
+ fromMarkup: false,
+ markupFactory: function(args, node, classCtor){
+ var i = new tests.parser.Class2();
+ i.fromMarkup = true;
+ return i;
+ }
+ });
+
+
+ dojo.declare("tests.parser.Class3", tests.parser.Class2, {
+ fromMarkup: false,
+ markupFactory: function(args, node, classCtor){
+ var i = new classCtor();
+ i.classCtor = classCtor;
+ return i;
+ }
+ });
+
+ dojo.declare("tests.parser.inputClass", null, {
+ constructor: function(args, node){ dojo.mixin(this, args); },
+ // these attributes are special in HTML, they don't have a value specified
+ disabled: false,
+ checked: false
+ });
+
+ deepTestProp = {
+ blah: {
+ thinger: 1
+ }
+ };
+
+ dojo.addOnLoad(function(){
+ doh.register("t",
+ [
+ function testJsId(t){
+ // console.debug(obj);
+ t.t(typeof obj == "object");
+ },
+
+ // Attribute parsing tests
+ function testStrProp(t){
+ // normal string parameter
+ t.t(dojo.isString(obj.strProp1));
+ t.is("text", obj.strProp1);
+
+ // make sure that you override a string value like "foo" to a blank value
+ t.t(dojo.isString(obj.strProp2));
+ t.is("", obj.strProp2);
+ },
+ function testIntProp(t){
+ t.is("number", (typeof obj.intProp));
+ t.is(5, obj.intProp);
+ },
+ function testArrProp(t){
+ t.is(3, obj.arrProp.length);
+ t.is(3, obj.arrProp[1].length);
+ t.is(["foo", "bar", "baz"], obj.arrProp);
+ },
+ function testBoolProp(t){
+ // make sure that both true and false get read correctly,
+ // and that unspecified attributes' values don't change
+
+ // boolProp1 specified at true
+ t.is("boolean", (typeof obj.boolProp1));
+ t.t(obj.boolProp1);
+
+ // boolProp2 specified as false
+ t.is("boolean", (typeof obj.boolProp2));
+ t.f(obj.boolProp2);
+
+ // boolProp3 not specified (prototype says false)
+ t.is("boolean", (typeof obj.boolProp3));
+ t.f(obj.boolProp3);
+
+ // boolProp4 not specified (prototype says true)
+ t.is("boolean", (typeof obj.boolProp4));
+ t.t(obj.boolProp4);
+ },
+ function testDateProp(t){
+ // dateProp1 specified as 2006-1-1
+ t.is("2006-01-01", dojo.date.stamp.toISOString(obj.dateProp1, {selector: 'date'}));
+
+ // dateProp2="", should map to NaN (a blank value on DateTextBox)
+ t.t(isNaN(obj.dateProp2));
+
+ // dateProp3="now", should map to current date
+ t.is(dojo.date.stamp.toISOString(new Date(), {selector: 'date'}),
+ dojo.date.stamp.toISOString(obj.dateProp3, {selector: 'date'}));
+ },
+ function testDisabledFlag(t){
+ t.is("boolean", (typeof disabledObj.disabled));
+ t.t(disabledObj.disabled);
+ t.f(disabledObj.checked);
+ },
+ function testCheckedFlag(t){
+ t.is("boolean", (typeof checkedObj.checked));
+ t.f(checkedObj.disabled);
+ t.t(checkedObj.checked);
+ },
+ function testFunctionProp(t){
+ // make sure that unspecified functions (even with common names)
+ // don't get overridden (bug #3074)
+ obj.onclick();
+ t.t(obj.prototypeOnclick);
+
+ // funcProp2="foo"
+ obj.funcProp2();
+ t.t(obj.fooCalled);
+
+ // funcProp3="this.func3Called=true;"
+ obj.funcProp3();
+ t.t(obj.func3Called);
+ },
+
+ // test <script> tags inside innerHTML of source node
+ "t.is(4, obj.preambleTestProp);",
+ "t.is(deepTestProp, obj.deepProp);",
+ function testConnect(t){
+ obj.callInc();
+ t.is(2, obj.callCount);
+ },
+ function testFunctionAssignment(t){
+ obj.callInc2();
+ t.is(1, obj.callCount2);
+ },
+ function testSubNodeParse(t){
+ t.f(dojo.exists("obj2"));
+ var toParse = dojo.byId("toParse");
+ toParse.setAttribute("dojoType", toParse.getAttribute("type"));
+ dojo.parser.parse(toParse.parentNode);
+ t.t(dojo.exists("obj2"));
+ t.is("tests.parser.Class1", obj2.declaredClass);
+ },
+ function testMarkupFactory(t){
+ t.t(dojo.exists("obj3"));
+ t.t(obj3.fromMarkup);
+ },
+ function testMarkupFactoryClass(t){
+ t.t(dojo.exists("obj4"));
+ t.is(obj4.classCtor, tests.parser.Class3);
+ t.t(obj4 instanceof tests.parser.Class3);
+ t.t(obj4 instanceof tests.parser.Class2);
+ },
+ function testDisabledFlag(t){
+ t.t(disabledObj.disabled);
+ t.f(disabledObj.checked);
+ },
+ function testCheckedFlag(t){
+ t.f(checkedObj.disabled);
+ t.t(checkedObj.checked);
+ }
+ ]
+ );
+ doh.run();
+ })
+ </script>
+ </head>
+ <body>
+ <h1>Parser Unit Test</h1>
+ <script>
+ function foo(){ this.fooCalled=true; }
+ </script>
+ <div dojoType="tests.parser.Class1" jsId="obj"
+ strProp1="text" strProp2=""
+ intProp="5"
+ arrProp="foo, bar, baz"
+ boolProp1="true" boolProp2="false"
+ dateProp1="2006-01-01" dateProp2="" dateProp3="now"
+ funcProp2="foo" funcProp3="this.func3Called=true;"
+ >
+ <script type="dojo/method" event="preamble">
+ this.preambleTestProp = 3;
+ </script>
+ <script type="dojo/method">
+ // this should be run immediately
+ this.deepProp = deepTestProp;
+ </script>
+ <script type="dojo/connect" event="callInc">
+ this.callCount++;
+ </script>
+ <script type="dojo/method" event="callInc2">
+ this.callCount2++;
+ </script>
+ </div>
+ <div>
+ <div type="tests.parser.Class1" jsId="obj2" id="toParse">
+ </div>
+ </div>
+ <div dojoType="tests.parser.Class2" jsId="obj3">
+ </div>
+ <div dojoType="tests.parser.Class3" jsId="obj4">
+ </div>
+ <input dojoType="tests.parser.inputClass" jsId="checkedObj" checked type="checkbox">
+ <button dojoType="tests.parser.inputClass" jsId="disabledObj" disabled>hi</button>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/parser.js b/includes/js/dojo/tests/parser.js
new file mode 100644
index 0000000..3f5028a
--- /dev/null
+++ b/includes/js/dojo/tests/parser.js
@@ -0,0 +1,8 @@
+if(!dojo._hasResource["tests.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.parser"] = true;
+dojo.provide("tests.parser");
+if(dojo.isBrowser){
+ doh.registerUrl("tests.parser", dojo.moduleUrl("tests", "parser.html"));
+}
+
+}
diff --git a/includes/js/dojo/tests/resources/ApplicationState.js b/includes/js/dojo/tests/resources/ApplicationState.js
new file mode 100644
index 0000000..a25e7ff
--- /dev/null
+++ b/includes/js/dojo/tests/resources/ApplicationState.js
@@ -0,0 +1,28 @@
+/*
+ApplicationState is an object that represents the application state.
+It will be given to dojo.undo.browser to represent the current application state.
+*/
+ApplicationState = function(stateData, outputDivId, backForwardOutputDivId, bookmarkValue){
+ this.stateData = stateData;
+ this.outputDivId = outputDivId;
+ this.backForwardOutputDivId = backForwardOutputDivId;
+ this.changeUrl = bookmarkValue;
+}
+
+ApplicationState.prototype.back = function(){
+ this.showBackForwardMessage("BACK for State Data: " + this.stateData);
+ this.showStateData();
+}
+
+ApplicationState.prototype.forward = function(){
+ this.showBackForwardMessage("FORWARD for State Data: " + this.stateData);
+ this.showStateData();
+}
+
+ApplicationState.prototype.showStateData = function(){
+ dojo.byId(this.outputDivId).innerHTML += this.stateData + '<br />';
+}
+
+ApplicationState.prototype.showBackForwardMessage = function(message){
+ dojo.byId(this.backForwardOutputDivId).innerHTML += message + '<br />';
+}
diff --git a/includes/js/dojo/tests/resources/JSON.php b/includes/js/dojo/tests/resources/JSON.php
new file mode 100644
index 0000000..e87e4d0
--- /dev/null
+++ b/includes/js/dojo/tests/resources/JSON.php
@@ -0,0 +1,724 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Converts to and from JSON format.
+ *
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ *
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * LICENSE: Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met: Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * @category
+ * @package Services_JSON
+ * @author Michal Migurski <mike-json@teczno.com>
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright 2005 Michal Migurski
+ * @license http://www.opensource.org/licenses/bsd-license.php
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE', 1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR', 2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR', 4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ', 8);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 10);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_STRICT_TYPE', 11);
+
+/**
+ * Converts to and from JSON format.
+ *
+ * Brief example of use:
+ *
+ * <code>
+ * // create a new instance of Services_JSON
+ * $json = new Services_JSON();
+ *
+ * // convert a complexe value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+ * $output = $json->encode($value);
+ *
+ * print($output);
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+ *
+ * // accept incoming POST data, assumed to be in JSON notation
+ * $input = file_get_contents('php://input', 1000000);
+ * $value = $json->decode($input);
+ * </code>
+ */
+class Services_JSON
+{
+ /**
+ * constructs a new JSON instance
+ *
+ * @param int $use object behavior: when encoding or decoding,
+ * be loose or strict about object/array usage
+ *
+ * possible values:
+ * - SERVICES_JSON_STRICT_TYPE: strict typing, default.
+ * "{...}" syntax creates objects in decode().
+ * - SERVICES_JSON_LOOSE_TYPE: loose typing.
+ * "{...}" syntax creates associative arrays in decode().
+ */
+ function Services_JSON($use = SERVICES_JSON_STRICT_TYPE)
+ {
+ $this->use = $use;
+ }
+
+ /**
+ * convert a string from one UTF-16 char to one UTF-8 char
+ *
+ * Normally should be handled by mb_convert_encoding, but
+ * provides a slower PHP-only method for installations
+ * that lack the multibye string extension.
+ *
+ * @param string $utf16 UTF-16 character
+ * @return string UTF-8 character
+ * @access private
+ */
+ function utf162utf8($utf16)
+ {
+ // oh please oh please oh please oh please oh please
+ if(function_exists('mb_convert_encoding'))
+ return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+
+ $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+ switch(true) {
+ case ((0x7F & $bytes) == $bytes):
+ // this case should never be reached, because we are in ASCII range
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0x7F & $bytes);
+
+ case (0x07FF & $bytes) == $bytes:
+ // return a 2-byte UTF-8 character
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0xC0 | (($bytes >> 6) & 0x1F))
+ . chr(0x80 | ($bytes & 0x3F));
+
+ case (0xFFFF & $bytes) == $bytes:
+ // return a 3-byte UTF-8 character
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0xE0 | (($bytes >> 12) & 0x0F))
+ . chr(0x80 | (($bytes >> 6) & 0x3F))
+ . chr(0x80 | ($bytes & 0x3F));
+ }
+
+ // ignoring UTF-32 for now, sorry
+ return '';
+ }
+
+ /**
+ * convert a string from one UTF-8 char to one UTF-16 char
+ *
+ * Normally should be handled by mb_convert_encoding, but
+ * provides a slower PHP-only method for installations
+ * that lack the multibye string extension.
+ *
+ * @param string $utf8 UTF-8 character
+ * @return string UTF-16 character
+ * @access private
+ */
+ function utf82utf16($utf8)
+ {
+ // oh please oh please oh please oh please oh please
+ if(function_exists('mb_convert_encoding'))
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+
+ switch(strlen($utf8)) {
+ case 1:
+ // this case should never be reached, because we are in ASCII range
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return $utf8;
+
+ case 2:
+ // return a UTF-16 character from a 2-byte UTF-8 char
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0x07 & (ord($utf8{0}) >> 2))
+ . chr((0xC0 & (ord($utf8{0}) << 6))
+ | (0x3F & ord($utf8{1})));
+
+ case 3:
+ // return a UTF-16 character from a 3-byte UTF-8 char
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr((0xF0 & (ord($utf8{0}) << 4))
+ | (0x0F & (ord($utf8{1}) >> 2)))
+ . chr((0xC0 & (ord($utf8{1}) << 6))
+ | (0x7F & ord($utf8{2})));
+ }
+
+ // ignoring UTF-32 for now, sorry
+ return '';
+ }
+
+ /**
+ * encodes an arbitrary variable into JSON format
+ *
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
+ * if var is a strng, note that encode() always expects it
+ * to be in ASCII or UTF-8 format!
+ *
+ * @return string JSON string representation of input var
+ * @access public
+ */
+ function encode($var)
+ {
+ switch (gettype($var)) {
+ case 'boolean':
+ return $var ? 'true' : 'false';
+
+ case 'NULL':
+ return 'null';
+
+ case 'integer':
+ return (int) $var;
+
+ case 'double':
+ case 'float':
+ return (float) $var;
+
+ case 'string':
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+ $ascii = '';
+ $strlen_var = strlen($var);
+
+ /*
+ * Iterate over every character in the string,
+ * escaping with a slash or encoding to UTF-8 where necessary
+ */
+ for ($c = 0; $c < $strlen_var; ++$c) {
+
+ $ord_var_c = ord($var{$c});
+
+ switch (true) {
+ case $ord_var_c == 0x08:
+ $ascii .= '\b';
+ break;
+ case $ord_var_c == 0x09:
+ $ascii .= '\t';
+ break;
+ case $ord_var_c == 0x0A:
+ $ascii .= '\n';
+ break;
+ case $ord_var_c == 0x0C:
+ $ascii .= '\f';
+ break;
+ case $ord_var_c == 0x0D:
+ $ascii .= '\r';
+ break;
+
+ case $ord_var_c == 0x22:
+ case $ord_var_c == 0x2F:
+ case $ord_var_c == 0x5C:
+ // double quote, slash, slosh
+ $ascii .= '\\'.$var{$c};
+ break;
+
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+ // characters U-00000000 - U-0000007F (same as ASCII)
+ $ascii .= $var{$c};
+ break;
+
+ case (($ord_var_c & 0xE0) == 0xC0):
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+ $c += 1;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xF0) == 0xE0):
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}));
+ $c += 2;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xF8) == 0xF0):
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}),
+ ord($var{$c + 3}));
+ $c += 3;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xFC) == 0xF8):
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}),
+ ord($var{$c + 3}),
+ ord($var{$c + 4}));
+ $c += 4;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xFE) == 0xFC):
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}),
+ ord($var{$c + 3}),
+ ord($var{$c + 4}),
+ ord($var{$c + 5}));
+ $c += 5;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+ }
+ }
+
+ return '"'.$ascii.'"';
+
+ case 'array':
+ /*
+ * As per JSON spec if any array key is not an integer
+ * we must treat the the whole array as an object. We
+ * also try to catch a sparsely populated associative
+ * array with numeric keys here because some JS engines
+ * will create an array with empty indexes up to
+ * max_index which can cause memory issues and because
+ * the keys, which may be relevant, will be remapped
+ * otherwise.
+ *
+ * As per the ECMA and JSON specification an object may
+ * have any string as a property. Unfortunately due to
+ * a hole in the ECMA specification if the key is a
+ * ECMA reserved word or starts with a digit the
+ * parameter is only accessible using ECMAScript's
+ * bracket notation.
+ */
+
+ // treat as a JSON object
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+ return '{' .
+ join(',', array_map(array($this, 'name_value'),
+ array_keys($var),
+ array_values($var)))
+ . '}';
+ }
+
+ // treat it like a regular array
+ return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']';
+
+ case 'object':
+ $vars = get_object_vars($var);
+ return '{' .
+ join(',', array_map(array($this, 'name_value'),
+ array_keys($vars),
+ array_values($vars)))
+ . '}';
+
+ default:
+ return '';
+ }
+ }
+
+ /**
+ * array-walking function for use in generating JSON-formatted name-value pairs
+ *
+ * @param string $name name of key to use
+ * @param mixed $value reference to an array element to be encoded
+ *
+ * @return string JSON-formatted name-value pair, like '"name":value'
+ * @access private
+ */
+ function name_value($name, $value)
+ {
+ return $this->encode(strval($name)) . ':' . $this->encode($value);
+ }
+
+ /**
+ * reduce a string by removing leading and trailing comments and whitespace
+ *
+ * @param $str string string value to strip of comments and whitespace
+ *
+ * @return string string value stripped of comments and whitespace
+ * @access private
+ */
+ function reduce_string($str)
+ {
+ $str = preg_replace(array(
+
+ // eliminate single line comments in '// ...' form
+ '#^\s*//(.+)$#m',
+
+ // eliminate multi-line comments in '/* ... */' form, at start of string
+ '#^\s*/\*(.+)\*/#Us',
+
+ // eliminate multi-line comments in '/* ... */' form, at end of string
+ '#/\*(.+)\*/\s*$#Us'
+
+ ), '', $str);
+
+ // eliminate extraneous space
+ return trim($str);
+ }
+
+ /**
+ * decodes a JSON string into appropriate variable
+ *
+ * @param string $str JSON-formatted string
+ *
+ * @return mixed number, boolean, string, array, or object
+ * corresponding to given JSON input string.
+ * See argument 1 to Services_JSON() above for object-output behavior.
+ * Note that decode() always returns strings
+ * in ASCII or UTF-8 format!
+ * @access public
+ */
+ function decode($str)
+ {
+ $str = $this->reduce_string($str);
+
+ switch (strtolower($str)) {
+ case 'true':
+ return true;
+
+ case 'false':
+ return false;
+
+ case 'null':
+ return null;
+
+ default:
+ if (is_numeric($str)) {
+ // Lookie-loo, it's a number
+
+ // This would work on its own, but I'm trying to be
+ // good about returning integers where appropriate:
+ // return (float)$str;
+
+ // Return float or int, as appropriate
+ return ((float)$str == (integer)$str)
+ ? (integer)$str
+ : (float)$str;
+
+ } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+ // STRINGS RETURNED IN UTF-8 FORMAT
+ $delim = substr($str, 0, 1);
+ $chrs = substr($str, 1, -1);
+ $utf8 = '';
+ $strlen_chrs = strlen($chrs);
+
+ for ($c = 0; $c < $strlen_chrs; ++$c) {
+
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
+ $ord_chrs_c = ord($chrs{$c});
+
+ switch (true) {
+ case $substr_chrs_c_2 == '\b':
+ $utf8 .= chr(0x08);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\t':
+ $utf8 .= chr(0x09);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\n':
+ $utf8 .= chr(0x0A);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\f':
+ $utf8 .= chr(0x0C);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\r':
+ $utf8 .= chr(0x0D);
+ ++$c;
+ break;
+
+ case $substr_chrs_c_2 == '\\"':
+ case $substr_chrs_c_2 == '\\\'':
+ case $substr_chrs_c_2 == '\\\\':
+ case $substr_chrs_c_2 == '\\/':
+ if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+ ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+ $utf8 .= $chrs{++$c};
+ }
+ break;
+
+ case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+ // single, escaped unicode character
+ $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+ . chr(hexdec(substr($chrs, ($c + 4), 2)));
+ $utf8 .= $this->utf162utf8($utf16);
+ $c += 5;
+ break;
+
+ case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+ $utf8 .= $chrs{$c};
+ break;
+
+ case ($ord_chrs_c & 0xE0) == 0xC0:
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
+ //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 2);
+ ++$c;
+ break;
+
+ case ($ord_chrs_c & 0xF0) == 0xE0:
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 3);
+ $c += 2;
+ break;
+
+ case ($ord_chrs_c & 0xF8) == 0xF0:
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 4);
+ $c += 3;
+ break;
+
+ case ($ord_chrs_c & 0xFC) == 0xF8:
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 5);
+ $c += 4;
+ break;
+
+ case ($ord_chrs_c & 0xFE) == 0xFC:
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 6);
+ $c += 5;
+ break;
+
+ }
+
+ }
+
+ return $utf8;
+
+ } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+ // array, or object notation
+
+ if ($str{0} == '[') {
+ $stk = array(SERVICES_JSON_IN_ARR);
+ $arr = array();
+ } else {
+ if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+ $stk = array(SERVICES_JSON_IN_OBJ);
+ $obj = array();
+ } else {
+ $stk = array(SERVICES_JSON_IN_OBJ);
+ $obj = new stdClass();
+ }
+ }
+
+ array_push($stk, array('what' => SERVICES_JSON_SLICE,
+ 'where' => 0,
+ 'delim' => false));
+
+ $chrs = substr($str, 1, -1);
+ $chrs = $this->reduce_string($chrs);
+
+ if ($chrs == '') {
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
+ return $arr;
+
+ } else {
+ return $obj;
+
+ }
+ }
+
+ //print("\nparsing {$chrs}\n");
+
+ $strlen_chrs = strlen($chrs);
+
+ for ($c = 0; $c <= $strlen_chrs; ++$c) {
+
+ $top = end($stk);
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
+
+ if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+ // found a comma that is not inside a string, array, etc.,
+ // OR we've reached the end of the character list
+ $slice = substr($chrs, $top['where'], ($c - $top['where']));
+ array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+ //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
+ // we are in an array, so just push an element onto the stack
+ array_push($arr, $this->decode($slice));
+
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+ // we are in an object, so figure
+ // out the property name and set an
+ // element in an associative array,
+ // for now
+ if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+ // "name":value pair
+ $key = $this->decode($parts[1]);
+ $val = $this->decode($parts[2]);
+
+ if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+ $obj[$key] = $val;
+ } else {
+ $obj->$key = $val;
+ }
+ } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+ // name:value pair, where name is unquoted
+ $key = $parts[1];
+ $val = $this->decode($parts[2]);
+
+ if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+ $obj[$key] = $val;
+ } else {
+ $obj->$key = $val;
+ }
+ }
+
+ }
+
+ } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+ // found a quote, and we are not inside a string
+ array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+ //print("Found start of string at {$c}\n");
+
+ } elseif (($chrs{$c} == $top['delim']) &&
+ ($top['what'] == SERVICES_JSON_IN_STR) &&
+ (($chrs{$c - 1} != '\\') ||
+ ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {
+ // found a quote, we're in a string, and it's not escaped
+ array_pop($stk);
+ //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+ } elseif (($chrs{$c} == '[') &&
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+ // found a left-bracket, and we are in an array, object, or slice
+ array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+ //print("Found start of array at {$c}\n");
+
+ } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+ // found a right-bracket, and we're in an array
+ array_pop($stk);
+ //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ } elseif (($chrs{$c} == '{') &&
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+ // found a left-brace, and we are in an array, object, or slice
+ array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+ //print("Found start of object at {$c}\n");
+
+ } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+ // found a right-brace, and we're in an object
+ array_pop($stk);
+ //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ } elseif (($substr_chrs_c_2 == '/*') &&
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+ // found a comment start, and we are in an array, object, or slice
+ array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+ $c++;
+ //print("Found start of comment at {$c}\n");
+
+ } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+ // found a comment end, and we're in one now
+ array_pop($stk);
+ $c++;
+
+ for ($i = $top['where']; $i <= $c; ++$i)
+ $chrs = substr_replace($chrs, ' ', $i, 1);
+
+ //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ }
+
+ }
+
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
+ return $arr;
+
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+ return $obj;
+
+ }
+
+ }
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/includes/js/dojo/tests/resources/testClass.php b/includes/js/dojo/tests/resources/testClass.php
new file mode 100644
index 0000000..acf7f16
--- /dev/null
+++ b/includes/js/dojo/tests/resources/testClass.php
@@ -0,0 +1,20 @@
+<?php
+class testClass {
+
+ function myecho ($somestring) {
+ return "<P>" . $somestring . "</P>";
+ }
+
+ function contentB () {
+ return "<P>Content B</P>";
+ }
+
+ function contentC () {
+ return "<P>Content C</P>";
+ }
+
+ function add($x,$y) {
+ return $x + $y;
+ }
+}
+?>
diff --git a/includes/js/dojo/tests/resources/testClass.smd b/includes/js/dojo/tests/resources/testClass.smd
new file mode 100644
index 0000000..9be6988
--- /dev/null
+++ b/includes/js/dojo/tests/resources/testClass.smd
@@ -0,0 +1,40 @@
+{
+ "SMDVersion":".1",
+ "objectName":"testClass",
+ "serviceType":"JSON-RPC",
+ "serviceURL":"../../dojo/tests/resources/test_JsonRPCMediator.php",
+ "methods":[
+ {
+ "name":"myecho",
+ "parameters":[
+ {
+ "name":"somestring",
+ "type":"STRING"
+ }
+ ]
+ },
+ {
+ "name":"contentB"
+ },
+ {
+ "name":"contentC"
+ },
+ {
+ "name":"add",
+ "parameters":[
+ {
+ "name":"x",
+ "type":"STRING"
+ },
+ {
+ "name":"y",
+ "type":"STRING"
+ }
+ ]
+ },
+ {
+ "name":"triggerRpcError"
+ },
+
+ ]
+}
diff --git a/includes/js/dojo/tests/resources/test_JsonRPCMediator.php b/includes/js/dojo/tests/resources/test_JsonRPCMediator.php
new file mode 100644
index 0000000..42a9711
--- /dev/null
+++ b/includes/js/dojo/tests/resources/test_JsonRPCMediator.php
@@ -0,0 +1,43 @@
+<?php
+ require_once("./JSON.php");
+
+ // FIXME: doesn't look like we really need Pear at all
+ // which decreases the testing burden.
+ // Commenting out.the require and the new File() call.
+
+ // NOTE: File.php is installed via Pear using:
+ // %> sudo pear install File
+ // Your server will also need the Pear library directory included in PHP's
+ // include_path configuration directive
+ // require_once('File.php');
+
+ // ensure that we don't try to send "html" down to the client
+ header("Content-Type: text/plain");
+
+ $json = new Services_JSON;
+ //$fp = new File();
+
+ $results = array();
+ $results['error'] = null;
+
+ $jsonRequest = file_get_contents('php://input');
+ //$jsonRequest = '{"params":["Blah"],"method":"myecho","id":86}';
+
+ $req = $json->decode($jsonRequest);
+
+ include("./testClass.php");
+ $testObject = new testClass();
+
+ $method = $req->method;
+ if ($method != "triggerRpcError") {
+ $ret = call_user_func_array(array($testObject,$method),$req->params);
+ $results['result'] = $ret;
+ } else {
+ $results['error'] = "Triggered RPC Error test";
+ }
+ $results['id'] = $req->id;
+
+ $encoded = $json->encode($results);
+
+ print $encoded;
+?>
diff --git a/includes/js/dojo/tests/resources/test_css.html b/includes/js/dojo/tests/resources/test_css.html
new file mode 100644
index 0000000..b999f02
--- /dev/null
+++ b/includes/js/dojo/tests/resources/test_css.html
@@ -0,0 +1,100 @@
+<html>
+ <head>
+ <title>Dojo CSS Stylesheet Test</title>
+ <link rel="stylesheet" type="text/css" href="../../resources/dojo.css" />
+ </head>
+ <body>
+ <h1>Lorem ipsum dolor sit amet.</h1>
+ <p>Lorem ipsum dolor sit amet, <a href="">consectetuer adipiscing elit</a>. In porta. Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, sapien ac faucibus feugiat, ligula felis laoreet justo, eu sollicitudin purus purus in nibh. Phasellus in nunc.</p>
+ <q>Donec eu nunc vitae lorem egestas convallis <code>var test=null;</code> Nullam at enim id mauris vestibulum ornare. Cras facilisis tellus at risus. Phasellus ut pede at erat posuere vehicula. Donec auctor sodales risus. Maecenas dictum erat at justo. Nullam fringilla dictum orci. Ut vitae erat. Fusce nunc. Duis quis orci. Morbi faucibus. Ut fermentum augue ac nulla. Duis cursus eleifend felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris tincidunt, justo quis venenatis congue, nisi purus dignissim nisi, ullamcorper tempus dolor nulla at metus.</q>
+ <h2>Donec eu nunc vitae lorem.</h2>
+ <p>Donec eu nunc vitae lorem egestas convallis. Nullam at enim id mauris vestibulum ornare. Cras facilisis tellus at risus. Phasellus ut pede at erat posuere vehicula. Donec auctor sodales risus. Maecenas dictum erat at justo. Nullam fringilla dictum orci. Ut vitae erat. Fusce nunc. Duis quis orci. Morbi faucibus. Ut fermentum augue ac nulla. Duis cursus eleifend felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris tincidunt, justo quis venenatis congue, nisi purus dignissim nisi, ullamcorper tempus dolor nulla at metus.</p>
+ <p>Vestibulum ultricies bibendum tortor. Nam auctor dignissim neque. Cras vehicula. Nulla facilisi. Duis quis tellus in est aliquet condimentum. Sed elementum, felis vel pharetra bibendum, neque lorem pulvinar nulla, consequat tempor libero enim vel nulla. Nulla eleifend, lorem accumsan convallis lobortis, diam dui eleifend urna, eu imperdiet purus urna nec nibh. Nullam pede odio, molestie eu, interdum sagittis, imperdiet ac, lectus. Sed pede nisl, vulputate at, pellentesque id, consectetuer ac, elit. Duis laoreet, elit sed tempus vehicula, lacus orci pulvinar nibh, non malesuada ante mi in enim. Etiam pulvinar, sapien ut vulputate venenatis, risus lectus sollicitudin sapien, in dapibus felis ligula congue ante. Vivamus sit amet ligula. Morbi pharetra augue egestas massa. Sed a ligula. In ac mi id nibh semper accumsan. Nunc luctus nibh vel magna. Nunc viverra nonummy tortor. Curabitur interdum convallis dui. Integer mollis hendrerit elit. Nam a lorem.</p>
+ <ol>
+ <li>A List item.</li>
+ <li>A List item.</li>
+ <li>A List item.</li>
+ <li>A List item.</li>
+ <li>A List item.</li>
+ <li>A List item.</li>
+ </ol>
+ <h2>Cras pellentesque</h2>
+ <h3>Aliquam dapibus</h3>
+ <pre>
+var test = someVariable;
+function foo(bar){
+ alert(baz);
+} </pre>
+ <p>Cras pellentesque tristique lorem. Aliquam dapibus, massa id posuere volutpat, sem sem nonummy turpis, ut ultricies nibh neque sed dolor. Duis commodo elit et massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed eu urna. Donec sit amet odio sit amet turpis facilisis molestie. In id mi. Nulla consequat ante ut elit. In risus urna, venenatis imperdiet, consequat vel, porttitor et, quam. In hac habitasse platea dictumst. Vestibulum id velit. Donec a eros. Donec quis quam at pede aliquet porta. Donec id ligula mollis turpis pulvinar dapibus. Praesent imperdiet, justo pulvinar accumsan scelerisque, lacus felis bibendum justo, id posuere augue libero eu velit.</p>
+ <h4>An unstyled table.</h4>
+ <table>
+ <thead>
+ <tr>
+ <th>Foo</th>
+ <th>Bar</th>
+ <th>Baz</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>baz</td>
+ <td>foo</td>
+ <td>bar</td>
+ </tr>
+ <tr>
+ <td>bar</td>
+ <td>baz</td>
+ <td>foo</td>
+ </tr>
+ <tr>
+ <td>foo</td>
+ <td>bar</td>
+ <td>baz</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td>Foo</td>
+ <td>Bar</td>
+ <td>Baz</td>
+ </tr>
+ </tfoot>
+ </table>
+ <h4>The same table, styled with dojoTabular.</h4>
+ <table class="dojoTabular">
+ <thead>
+ <tr>
+ <th>Foo</th>
+ <th>Bar</th>
+ <th>Baz</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>baz</td>
+ <td>foo</td>
+ <td>bar</td>
+ </tr>
+ <tr>
+ <td>bar</td>
+ <td>baz</td>
+ <td>foo</td>
+ </tr>
+ <tr>
+ <td>foo</td>
+ <td>bar</td>
+ <td>baz</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td>Foo</td>
+ <td>Bar</td>
+ <td>Baz</td>
+ </tr>
+ </tfoot>
+ </table>
+ <blockquote>Donec eu nunc vitae lorem egestas convallis. Nullam at enim id mauris vestibulum ornare. Cras facilisis tellus at risus. Phasellus ut pede at erat posuere vehicula. Donec auctor sodales risus. Maecenas dictum erat at justo. Nullam fringilla dictum orci. Ut vitae erat. Fusce nunc. Duis quis orci. Morbi faucibus. Ut fermentum augue ac nulla. Duis cursus eleifend felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris tincidunt, justo quis venenatis congue, nisi purus dignissim nisi, ullamcorper tempus dolor nulla at metus.</blockquote>
+ <p>Phasellus quis velit. Curabitur porta dolor in arcu. Maecenas mollis purus. Donec nec erat et tellus laoreet elementum. Pellentesque vitae mi. Aenean pharetra libero ultricies augue. Vestibulum et nibh. Proin nibh quam, rutrum faucibus, auctor eget, mollis vel, orci. Duis tortor quam, tincidunt eu, lacinia id, fermentum at, turpis. Mauris at augue. Nulla facilisi. Pellentesque ut enim.</p>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/resources/yahoo_smd_v1.smd b/includes/js/dojo/tests/resources/yahoo_smd_v1.smd
new file mode 100644
index 0000000..8f6a1f7
--- /dev/null
+++ b/includes/js/dojo/tests/resources/yahoo_smd_v1.smd
@@ -0,0 +1,268 @@
+{
+ "SMDVersion":".1",
+ "objectName":"yahoo",
+ "serviceType":"JSON-P",
+ "required": {
+ "appid": "dojotoolkit",
+ "output": "json"
+ },
+ "methods":[
+ //
+ // MAPS
+ //
+ {
+ // http://developer.yahoo.com/maps/rest/V1/mapImage.html
+ "name":"mapImage",
+ "serviceURL": "http://api.local.yahoo.com/MapsService/V1/mapImage",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ { "name":"city", "type":"STRING" },
+ { "name":"zip", "type":"INTEGER" },
+ { "name":"location", "type":"STRING" },
+ { "name":"longitude", "type":"FLOAT" },
+ { "name":"latitude", "type":"FLOAT" },
+ { "name":"image_type", "type":"STRING" },
+ { "name":"image_width", "type":"INTEGER" },
+ { "name":"image_height", "type":"INTEGER" },
+ { "name":"zoom", "type":"INTEGER" },
+ { "name":"radius", "type":"INTEGER" }
+ ]
+ },
+ {
+ // http://developer.yahoo.com/traffic/rest/V1/index.html
+ "name":"trafficData",
+ "serviceURL": "http://api.local.yahoo.com/MapsService/V1/trafficData",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ { "name":"city", "type":"STRING" },
+ { "name":"zip", "type":"INTEGER" },
+ { "name":"location", "type":"STRING" },
+ { "name":"longitude", "type":"FLOAT" },
+ { "name":"latitude", "type":"FLOAT" },
+ { "name":"severity", "type":"INTEGER" },
+ { "name":"include_map", "type":"INTEGER" },
+ { "name":"image_type", "type":"STRING" },
+ { "name":"image_width", "type":"INTEGER" },
+ { "name":"image_height", "type":"INTEGER" },
+ { "name":"zoom", "type":"INTEGER" },
+ { "name":"radius", "type":"INTEGER" }
+ ]
+ },
+ //
+ // LOCAL SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/local/V3/localSearch.html
+ "name":"localSearch",
+ "serviceURL": "http://api.local.yahoo.com/LocalSearchService/V3/localSearch",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ { "name":"city", "type":"STRING" },
+ { "name":"zip", "type":"INTEGER" },
+ { "name":"location", "type":"STRING" },
+ { "name":"listing_id", "type":"STRING" },
+ { "name":"sort", "type":"STRING" }, // "relevence", "title", "distance", or "rating"
+ { "name":"start", "type":"INTEGER" },
+ { "name":"radius", "type":"FLOAT" },
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"longitude", "type":"FLOAT" },
+ { "name":"latitude", "type":"FLOAT" },
+ { "name":"category", "type":"INTEGER" },
+ { "name":"omit_category", "type":"INTEGER" },
+ { "name":"minimum_rating", "type":"INTEGER" }
+ ]
+ },
+ //
+ // WEB SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/web/V1/webSearch.html
+ "name":"webSearch",
+ "serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/webSearch",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all"
+ { "name":"region", "type":"STRING" }, // defaults to "us"
+ { "name":"results", "type":"INTEGER" }, // defaults to 10
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"format", "type":"STRING" }, // defaults to "any", can be "html", "msword", "pdf", "ppt", "rst", "txt", or "xls"
+ { "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"similar_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"language", "type":"STRING" }, // defaults to null
+ { "name":"country", "type":"STRING" }, // defaults to null
+ { "name":"site", "type":"STRING" }, // defaults to null
+ { "name":"subscription", "type":"STRING" }, // defaults to null
+ { "name":"license", "type":"STRING" } // defaults to "any"
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/web/V1/spellingSuggestion.html
+ "name":"spellingSuggestion",
+ "serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion",
+ "parameters":[ { "name":"query", "type":"STRING" } ]
+ },
+ {
+ // http://developer.yahoo.com/search/web/V1/relatedSuggestion.html
+ "name":"spellingSuggestion",
+ "serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/relatedSuggestion",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"results", "type":"INTEGER" } // 1-50, defaults to 10
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/content/V1/termExtraction.html
+ "name":"termExtraction",
+ "serviceURL": "http://search.yahooapis.com/ContentAnalysisService/V1/termExtraction",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"context", "type":"STRING" },
+ { "name":"results", "type":"INTEGER" } // 1-50, defaults to 10
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/web/V1/contextSearch.html
+ "name":"contextSearch",
+ "serviceURL": "http://search.yahooapis.com/WebSearchService/V1/contextSearch",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"context", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all"
+ { "name":"results", "type":"INTEGER" }, // defaults to 10
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"format", "type":"STRING" }, // defaults to "any", can be "html", "msword", "pdf", "ppt", "rst", "txt", or "xls"
+ { "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"similar_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"language", "type":"STRING" }, // defaults to null
+ { "name":"country", "type":"STRING" }, // defaults to null
+ { "name":"site", "type":"STRING" }, // defaults to null
+ { "name":"license", "type":"STRING" } // defaults to "any", could be "cc_any", "cc_commercial", "cc_modifiable"
+ ]
+ },
+ //
+ // IMAGE SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/image/V1/imageSearch.html
+ "name":"imageSearch",
+ "serviceURL": "http://api.search.yahoo.com/ImageSearchService/V1/imageSearch",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+ { "name":"results", "type":"INTEGER" }, // defaults to 10
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"format", "type":"STRING" }, // defaults to "any", can be "bmp", "gif", "jpeg", or "png"
+ { "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"coloration", "type":"STRING" }, // "any", "color", or "bw"
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ },
+ //
+ // SITE EXPLORER
+ //
+ {
+ // http://developer.yahoo.com/search/siteexplorer/V1/inlinkData.html
+ "name":"inlinkData",
+ "serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/inlinkData",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+ { "name":"entire_site", "type":"INTEGER" }, // defaults to null
+ { "name":"omit_inlinks", "type":"STRING" }, // "domain" or "subdomain", defaults to null
+ { "name":"results", "type":"INTEGER" }, // defaults to 50
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/siteexplorer/V1/pageData.html
+ "name":"pageData",
+ "serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/pageData",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+ { "name":"domain_only", "type":"INTEGER" }, // defaults to null
+ { "name":"results", "type":"INTEGER" }, // defaults to 50
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ },
+ //
+ // MUSIC SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/audio/V1/artistSearch.html
+ "name":"artistSearch",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/artistSearch",
+ "parameters":[
+ { "name":"artist", "type":"STRING" },
+ { "name":"artistid", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/audio/V1/albumSearch.html
+ "name":"albumSearch",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/albumSearch",
+ "parameters":[
+ { "name":"artist", "type":"STRING" },
+ { "name":"artistid", "type":"STRING" },
+ { "name":"album", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/audio/V1/songSearch.html
+ "name":"songSearch",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songSearch",
+ "parameters":[
+ { "name":"artist", "type":"STRING" },
+ { "name":"artistid", "type":"STRING" },
+ { "name":"album", "type":"STRING" },
+ { "name":"albumid", "type":"STRING" },
+ { "name":"song", "type":"STRING" },
+ { "name":"songid", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/audio/V1/songDownloadLocation.html
+ "name":"songDownloadLocation",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songDownloadLocation",
+ "parameters":[
+ { "name":"songid", "type":"STRING" },
+ // "source" can contain:
+ // audiolunchbox artistdirect buymusic dmusic
+ // emusic epitonic garageband itunes yahoo
+ // livedownloads mp34u msn musicmatch mapster passalong
+ // rhapsody soundclick theweb
+ { "name":"source", "type":"STRING" },
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ //
+ // NEWS SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/news/V1/newsSearch.html
+ "name":"newsSearch",
+ "serviceURL": "http://api.search.yahoo.com/NewsSearchService/V1/newsSearch",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all"
+ { "name":"results", "type":"INTEGER" }, // defaults to 10
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"sort", "type":"STRING" }, // "rank" or "date"
+ { "name":"language", "type":"STRING" }, // defaults to null
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ }
+ ]
+}
diff --git a/includes/js/dojo/tests/rpc.js b/includes/js/dojo/tests/rpc.js
new file mode 100644
index 0000000..09c8ef2
--- /dev/null
+++ b/includes/js/dojo/tests/rpc.js
@@ -0,0 +1,151 @@
+if(!dojo._hasResource["tests.rpc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.rpc"] = true;
+dojo.provide("tests.rpc");
+
+dojo.require("dojo.rpc.RpcService");
+dojo.require("dojo.rpc.JsonService");
+dojo.require("dojo.rpc.JsonpService");
+
+doh.register("tests.rpc",
+ [
+
+ {
+ name: "JsonRPC-EchoTest",
+ timeout: 2000,
+ setUp: function(){
+
+ var testSmd = {
+ serviceURL:"../../dojo/tests/resources/test_JsonRPCMediator.php",
+ methods:[
+ {
+ name:"myecho",
+ parameters:[
+ {
+ name:"somestring",
+ type:"STRING"
+ }
+ ]
+ }
+ ]
+ }
+
+ this.svc = new dojo.rpc.JsonService(testSmd);
+ },
+ runTest: function(){
+ var d = new doh.Deferred();
+ var td = this.svc.myecho("RPC TEST");
+
+ if (window.location.protocol=="file:") {
+ var err= new Error("This Test requires a webserver and PHP and will fail intentionally if loaded from file://");
+ d.errback(err);
+ return d;
+ }
+
+ td.addCallbacks(function(result) {
+ if(result=="<P>RPC TEST</P>"){
+ return true;
+ }else{
+ return new Error("JsonRpc-EchoTest test failed, resultant content didn't match");
+ }
+ }, function(result){
+ return new Error(result);
+ });
+
+ td.addBoth(d, "callback");
+
+ return d;
+ }
+
+ },
+
+ {
+ name: "JsonRPC-EmptyParamTest",
+ timeout: 2000,
+ setUp: function(){
+ var testSmd={
+ serviceURL:"../../dojo/tests/resources/test_JsonRPCMediator.php",
+ methods:[ { name:"contentB" } ]
+ }
+
+ this.svc = new dojo.rpc.JsonService(testSmd);
+ },
+ runTest: function(){
+ var d = new doh.Deferred();
+ var td = this.svc.contentB();
+
+ if (window.location.protocol=="file:") {
+ var err= new Error("This Test requires a webserver and PHP and will fail intentionally if loaded from file://");
+ d.errback(err);
+ return d;
+ }
+
+ td.addCallbacks(function(result){
+ if(result=="<P>Content B</P>"){
+ return true;
+ }else{
+ return new Error("JsonRpc-EmpytParamTest test failed, resultant content didn't match");
+ }
+ }, function(result){
+ return new Error(result);
+ });
+
+ td.addBoth(d, "callback");
+
+ return d;
+ }
+ },
+
+ {
+ name: "JsonRPC_SMD_Loading_test",
+ setUp: function(){
+ this.svc = new dojo.rpc.JsonService("../../dojo/tests/resources/testClass.smd");
+ },
+ runTest: function(){
+
+ if (this.svc.objectName=="testClass") {
+ return true;
+ } else {
+ return new Error("Error loading and/or parsing an smd file");
+ }
+ }
+ },
+
+ {
+ name: "JsonP_test",
+ timeout: 10000,
+ setUp: function(){
+ this.svc = new dojo.rpc.JsonpService(dojo.moduleUrl("dojo.tests.resources","yahoo_smd_v1.smd"), {appid: "foo"});
+ },
+ runTest: function(){
+ var d = new doh.Deferred();
+
+ if (window.location.protocol=="file:") {
+ var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+ d.errback(err);
+ return d;
+ }
+
+ var td = this.svc.webSearch({query:"dojotoolkit"});
+
+ td.addCallbacks(function(result){
+ return true;
+ if (result["ResultSet"]["Result"][0]["DisplayUrl"]=="dojotoolkit.org/") {
+ return true;
+ }else{
+ return new Error("JsonRpc_SMD_Loading_Test failed, resultant content didn't match");
+ }
+ }, function(result){
+ return new Error(result);
+ });
+
+ td.addBoth(d, "callback");
+
+ return d;
+ }
+ }
+ ]
+);
+
+
+
+}
diff --git a/includes/js/dojo/tests/runTests.html b/includes/js/dojo/tests/runTests.html
new file mode 100644
index 0000000..a83f534
--- /dev/null
+++ b/includes/js/dojo/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <title>Dojo CORE and BASE D.O.H. Unit Test Runner</title>
+ <meta http-equiv="REFRESH" content="0;url=../../util/doh/runner.html?testModule=dojo.tests.module"></HEAD>
+ <BODY>
+ Redirecting to D.O.H runner.
+ </BODY>
+</HTML>
diff --git a/includes/js/dojo/tests/string.js b/includes/js/dojo/tests/string.js
new file mode 100644
index 0000000..2f9c2cb
--- /dev/null
+++ b/includes/js/dojo/tests/string.js
@@ -0,0 +1,31 @@
+if(!dojo._hasResource["tests.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["tests.string"] = true;
+dojo.provide("tests.string");
+
+dojo.require("dojo.string");
+
+tests.register("tests.string",
+ [
+ function test_string_pad(t){
+ t.is("00001", dojo.string.pad("1", 5));
+ t.is("000001", dojo.string.pad("000001", 5));
+ t.is("10000", dojo.string.pad("1", 5, null, true));
+ },
+
+ function test_string_substitute(t){
+ t.is("File 'foo.html' is not found in directory '/temp'.", dojo.string.substitute("File '${0}' is not found in directory '${1}'.", ["foo.html","/temp"]));
+ t.is("File 'foo.html' is not found in directory '/temp'.", dojo.string.substitute("File '${name}' is not found in directory '${info.dir}'.", {name: "foo.html", info: {dir: "/temp"}}));
+ // Verify that an error is thrown!
+ t.assertError(Error, dojo.string, "substitute", ["${x}", {y:1}]);
+ },
+
+ function test_string_trim(t){
+ t.is("astoria", dojo.string.trim(" \f\n\r\t astoria "));
+ t.is("astoria", dojo.string.trim("astoria "));
+ t.is("astoria", dojo.string.trim(" astoria"));
+ t.is("astoria", dojo.string.trim("astoria"));
+ }
+ ]
+);
+
+}
diff --git a/includes/js/dojo/tests/test_FirebugLite.html b/includes/js/dojo/tests/test_FirebugLite.html
new file mode 100644
index 0000000..f87f01b
--- /dev/null
+++ b/includes/js/dojo/tests/test_FirebugLite.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>Firebug Lite Tests</title>
+ <script type="text/javascript">
+ // enable Lite in Firefox:
+ console = null;
+ var djConfig = {
+ isDebug: true,
+ debugHeight: 100,
+ popup:false
+ };
+ </script>
+
+ <script type="text/javascript" src="../dojo.js"></script>
+ <script type="text/javascript">
+ obj = { // a long object to test scrolling in object inspector
+ mobby:{d:"objectify", e:"erroroneous", f:"functastic", obby:{lilOb:"moOb"}},
+ a:"Dojo",
+ b:2,
+ c:[0,8],
+ id:"MyCoolObject",
+ extra:{d:"objectify2", e:"erroroneous2", f:"functastic2", obby:{lilOb:"moOb2"}},
+ aaa:"Dojo",
+ bbb:22,
+ ccc:[10,18],
+ idDeedYee:"MyCoolObjectie"
+ }
+
+ obj2 = {
+ a:"Dojo",
+ b:2,
+ c:[0,8],
+ id:"MyCoolObject"
+ }
+
+ obj3 = {
+ a:"Dojo",
+ b:2,
+ c:[0,8]
+ }
+
+ outputText = function(){
+ for ( var i = 0; i < 20 ; i++){
+ console.log (i+":: foo");
+ }
+ }
+ doStuff = function(){
+ console.log("FOO! More FOO! Gotta have some FOO MAN!")
+ }
+
+ doStuffLots = function(){
+ for ( var i = 0; i < 5 ; i++){
+ console.log("xxxxxxxx")
+ doStuff();
+ }}
+ dojo.addOnLoad(function(){
+ console.time("foo time")
+ // test objects
+ console.log(obj3, "::", [1,2,3,4,5,6,7,8,9,0]);
+ console.log("Dojo was here", obj, "object over", obj2);
+
+ // test that tracing dom node does not break (due to lack of support)
+ console.log(dojo.byId("foo"))
+
+ // test error functionality
+ console.error( new Error("There was a dummy error") );
+
+ //throws exception:
+ //console.assert(true == false)
+
+ console.group("myGroup");
+ console.log("group me 1");
+ console.log("group me 2");
+ console.log("group me 3");
+ console.groupEnd();
+
+ // testing log styling
+ console.log("foo");
+ console.debug("foo");
+ console.info("foo");
+ console.warn("foo");
+ console.error("foo");
+ //timer end
+ console.timeEnd("foo time")
+ })
+
+ function doCon(){
+ }
+ </script>
+</head>
+<body>
+ <div id="foo" font="Arial" style="display:none;">Dojo was here</div>
+ <button onclick="doStuff()">Do Foo Stuff</button>
+ <button onclick="doStuffLots()">Do Stuff Lots</button>
+ <div id="trc"></div>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/test_FirebugLitePopup.html b/includes/js/dojo/tests/test_FirebugLitePopup.html
new file mode 100644
index 0000000..926713e
--- /dev/null
+++ b/includes/js/dojo/tests/test_FirebugLitePopup.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>Firebug Lite Tests</title>
+ <script type="text/javascript">
+ // enable Lite in Firefox:
+ console = null;
+ var djConfig = {
+ isDebug: true,
+ debugHeight: 100,
+ popup:true // who knew?
+ };
+ </script>
+
+ <script type="text/javascript" src="../dojo.js"></script>
+ <script type="text/javascript">
+ obj = { // a long object to test scrolling in object inspector
+ mobby:{d:"objectify", e:"erroroneous", f:"functastic", obby:{lilOb:"moOb"}},
+ a:"Dojo",
+ b:2,
+ c:[0,8],
+ id:"MyCoolObject",
+ extra:{d:"objectify2", e:"erroroneous2", f:"functastic2", obby:{lilOb:"moOb2"}},
+ aaa:"Dojo",
+ bbb:22,
+ ccc:[10,18],
+ idDeedYee:"MyCoolObjectie"
+ }
+
+ obj2 = {
+ a:"Dojo",
+ b:2,
+ c:[0,8],
+ id:"MyCoolObject"
+ }
+
+ obj3 = {
+ a:"Dojo",
+ b:2,
+ c:[0,8]
+ }
+
+ outputText = function(){
+ for ( var i = 0; i < 20 ; i++){
+ console.log (i+":: foo");
+ }
+ }
+ doStuff = function(){
+ console.log("FOO! More FOO! Gotta have some FOO MAN!")
+ }
+
+ doStuffLots = function(){
+ for ( var i = 0; i < 5 ; i++){
+ console.log("xxxxxxxx")
+ doStuff();
+ }}
+ dojo.addOnLoad(function(){
+ console.time("foo time")
+ // test objects
+ console.log(obj3, "::", [1,2,3,4,5,6,7,8,9,0]);
+ console.log("Dojo was here", obj, "object over", obj2);
+
+ // test that tracing dom node does not break (due to lack of support)
+ console.log(dojo.byId("foo"))
+
+ // test error functionality
+ console.error( new Error("There was a dummy error") );
+
+ //throws exception:
+ //console.assert(true == false)
+
+ console.group("myGroup");
+ console.log("group me 1");
+ console.log("group me 2");
+ console.log("group me 3");
+ console.groupEnd();
+
+ // testing log styling
+ console.log("foo");
+ console.debug("foo");
+ console.info("foo");
+ console.warn("foo");
+ console.error("foo");
+ //timer end
+ console.timeEnd("foo time")
+ })
+
+ function doCon(){
+ }
+ </script>
+</head>
+<body>
+ <h1>test Firebug popup window</h1>
+ <div id="foo" font="Arial" style="display:none;">Dojo was here</div>
+ <button onclick="doStuff()">Do Foo Stuff</button>
+ <button onclick="doStuffLots()">Do Stuff Lots</button>
+ <div id="trc"></div>
+ </body>
+</html>
diff --git a/includes/js/dojo/tests/test_fx.html b/includes/js/dojo/tests/test_fx.html
new file mode 100644
index 0000000..8d9b0de
--- /dev/null
+++ b/includes/js/dojo/tests/test_fx.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style type="text/css">
+ @import "../resources/dojo.css";
+ </style>
+ <style type="text/css">
+ @import "../resources/dojo.css";
+
+ body {
+ text-shadow: 0px 0px;
+ margin: 1em;
+ background-color: #DEDEDE;
+ }
+
+ .box {
+ color: #292929;
+ /* color: #424242; */
+ /* text-align: left; */
+ width: 300px;
+ border: 1px solid #BABABA;
+ background-color: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ margin-left: 10px;
+ margin-bottom: 1em;
+ -o-border-radius: 10px;
+ -moz-border-radius: 12px;
+ -webkit-border-radius: 10px;
+ -webkit-box-shadow: 0px 3px 7px #adadad;
+ /* -opera-border-radius: 10px; */
+ border-radius: 10px;
+ -moz-box-sizing: border-box;
+ -opera-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -khtml-box-sizing: border-box;
+ box-sizing: border-box;
+ overflow: hidden;
+ /* position: absolute; */
+ }
+ </style>
+ <script type="text/javascript" src="../dojo.js" djConfig="isDebug: true"></script>
+ <script type="text/javascript" src="../fx.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.fx");
+ dojo.addOnLoad(function(){
+ dojo.byId("foo").style.height = "0px";
+ var w1 = dojo.fx.wipeIn({
+ node: "foo",
+ duration: 500
+ });
+ var f1 = dojo.fadeOut({
+ node: "foo",
+ duration: 500
+ });
+ var a1 = dojo.fx.chain([w1, f1]);
+
+ dojo.byId("foo").style.height = "0px";
+ var w2 = dojo.fx.wipeIn({
+ node: "foo",
+ duration: 500
+ });
+ var f2 = dojo.fadeIn({
+ node: "foo",
+ duration: 1000
+ });
+ var a2 = dojo.fx.combine([w2, f2]);
+
+ dojo.connect(a1, "onEnd", function(){
+ console.log("finish1");
+ a2.play();
+ });
+ dojo.connect(a2, "onEnd", function(){
+ console.log("finish2");
+ });
+ a1.play();
+ });
+ </script>
+ </head>
+ <body>
+ <div id="foo" class="box">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+ semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+ Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla
+ facilisi. Maecenas luctus venenatis nulla. In sit amet dui non mi
+ semper iaculis. Sed molestie tortor at ipsum. Morbi dictum rutrum
+ magna. Sed vitae risus.
+ </p>
+ <p>
+ Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+ imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+ lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+ id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+ mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+ pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+ tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+ elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+ ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+ pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+ massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+ nec est. Aenean id risus blandit tortor pharetra congue.
+ Suspendisse pulvinar.
+ </p>
+ </div>
+ </body>
+</html> \ No newline at end of file