import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,5 @@
this.EXPORTED_SYMBOLS = ["ImportTesting"];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
// Empty module for testing via SpecialPowers.importInMainProcess.

View file

@ -0,0 +1,15 @@
// Just receive 'foo' message and forward it back
// as 'bar' message
addMessageListener("foo", function (message) {
sendAsyncMessage("bar", message);
});
addMessageListener("valid-assert", function (message) {
assert.ok(true, "valid assertion");
assert.equal(1, 1, "another valid assertion");
sendAsyncMessage("valid-assert-done");
});
addMessageListener("sync-message", () => {
return "Received a synchronous message.";
});

View file

@ -0,0 +1,14 @@
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="content" style="display: none">
<script type="text/javascript">
is(SpecialPowers.sanityCheck(), "foo", "Check Special Powers in iframe");
</script>
</div>
</body>
</html>

View file

@ -0,0 +1,3 @@
addMessageListener("ImportTesting:IsModuleLoaded", function (msg) {
sendAsyncMessage("ImportTesting:IsModuleLoadedReply", Components.utils.isModuleLoaded(msg));
});

View file

@ -0,0 +1,44 @@
[DEFAULT]
[test_TestsRunningAfterSimpleTestFinish.html]
skip-if = true #depends on fix for bug 1048446
[test_add_task.html]
[test_createFiles.html]
[test_importInMainProcess.html]
support-files = importtesting_chromescript.js
[test_sanity.html]
[test_sanityException.html]
[test_sanityException2.html]
[test_sanityParams.html]
[test_sanityRegisteredServiceWorker.html]
support-files = empty.js
[test_sanityRegisteredServiceWorker2.html]
support-files = empty.js
[test_sanityWindowSnapshot.html]
[test_SpecialPowersExtension.html]
[test_SpecialPowersExtension2.html]
support-files = file_SpecialPowersFrame1.html
[test_SpecialPowersPushPermissions.html]
support-files =
specialPowers_framescript.js
[test_SpecialPowersPushPrefEnv.html]
[test_SimpletestGetTestFileURL.html]
[test_SpecialPowersLoadChromeScript.html]
support-files = SpecialPowersLoadChromeScript.js
[test_SpecialPowersLoadChromeScript_function.html]
[test_SpecialPowersLoadPrivilegedScript.html]
[test_bug649012.html]
[test_sanity_cleanup.html]
[test_sanity_cleanup2.html]
[test_sanityEventUtils.html]
skip-if = toolkit == 'android' # bug 688052
[test_sanitySimpletest.html]
subsuite = clipboard
skip-if = toolkit == 'android' # bug 688052
[test_sanity_manifest.html]
skip-if = toolkit == 'android' # we use the old manifest style on android
fail-if = true
[test_sanity_manifest_pf.html]
skip-if = toolkit == 'android' # we use the old manifest style on android
fail-if = true
[test_spawn_task.html]
[test_sanity_waitForCondition.html]

View file

@ -0,0 +1,13 @@
Components.utils.import("resource://gre/modules/Services.jsm");
var permChangedObs = {
observe: function(subject, topic, data) {
if (topic == 'perm-changed') {
var permission = subject.QueryInterface(Components.interfaces.nsIPermission);
var msg = { op: data, type: permission.type };
sendAsyncMessage('perm-changed', msg);
}
}
};
Services.obs.addObserver(permChangedObs, 'perm-changed', false);

View file

@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers extension</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var filename = "MyTestDataFile.txt";
var url = SimpleTest.getTestFileURL(filename);
is(url, document.location.href.replace(/test_SimpletestGetTestFileURL\.html.*/, filename));
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,192 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers extension</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="starttest();">
<div id="content" style="display: none">
<canvas id="testcanvas" width="200" height="200">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var eventCount = 0;
function testEventListener(e) {
++eventCount;
}
function testEventListener2(e) {
++eventCount;
}
function dispatchTestEvent() {
var e = document.createEvent("Event");
e.initEvent("TestEvent", true, true);
window.dispatchEvent(e);
}
dump("\nSPECIALPTEST:::Test script loaded " + (new Date).getTime() + "\n");
SimpleTest.waitForExplicitFinish();
var startTime = new Date();
function starttest(){
dump("\nSPECIALPTEST:::Test script running after load " + (new Date).getTime() + "\n");
/** Test for SpecialPowers extension **/
is(SpecialPowers.sanityCheck(), "foo", "check to see whether the Special Powers extension is installed.");
// Test a sync call into chrome
SpecialPowers.setBoolPref('extensions.checkCompatibility', true);
is(SpecialPowers.getBoolPref('extensions.checkCompatibility'), true, "Check to see if we can set a preference properly");
SpecialPowers.clearUserPref('extensions.checkCompatibility');
// Test a int pref
SpecialPowers.setIntPref('extensions.foobar', 42);
is(SpecialPowers.getIntPref('extensions.foobar'), 42, "Check int pref");
SpecialPowers.clearUserPref('extensions.foobar');
// Test a string pref
SpecialPowers.setCharPref("extensions.foobaz", "hi there");
is(SpecialPowers.getCharPref("extensions.foobaz"), "hi there", "Check string pref");
SpecialPowers.clearUserPref("extensions.foobaz");
// Test an invalid pref
var retVal = null;
try {
retVal = SpecialPowers.getBoolPref('extensions.checkCompat0123456789');
} catch (ex) {
retVal = ex;
}
is(retVal, "Error getting pref 'extensions.checkCompat0123456789'", "received an exception trying to get an unset preference value");
SpecialPowers.addChromeEventListener("TestEvent", testEventListener, true, true);
SpecialPowers.addChromeEventListener("TestEvent", testEventListener2, true, false);
dispatchTestEvent();
is(eventCount, 1, "Should have got an event!");
SpecialPowers.removeChromeEventListener("TestEvent", testEventListener, true);
SpecialPowers.removeChromeEventListener("TestEvent", testEventListener2, true);
dispatchTestEvent();
is(eventCount, 1, "Shouldn't have got an event!");
// Test Complex Pref - TODO: Without chrome access, I don't know how you'd actually
// set this preference since you have to create an XPCOM object.
// Leaving untested for now.
// Test a DOMWindowUtils method and property
is(SpecialPowers.DOMWindowUtils.getClassName(window), "Proxy");
is(SpecialPowers.DOMWindowUtils.docCharsetIsForced, false);
// QueryInterface and getPrivilegedProps tests
is(SpecialPowers.can_QI(SpecialPowers), false);
ok(SpecialPowers.can_QI(window));
ok(SpecialPowers.do_QueryInterface(window, "nsIDOMWindow"));
is(SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(window, "nsIDOMWindow"), "document.nodeName"), "#document");
//try to run garbage collection
SpecialPowers.gc();
//
// Test the SpecialPowers wrapper.
//
// Try some basic stuff with XHR.
var xhr2 = SpecialPowers.Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(SpecialPowers.Ci.nsIXMLHttpRequest);
is(xhr2.readyState, XMLHttpRequest.UNSENT, "Should be able to get props off privileged objects");
var testURI = SpecialPowers.Cc['@mozilla.org/network/standard-url;1']
.createInstance(SpecialPowers.Ci.nsIURI);
testURI.spec = "http://www.foobar.org/";
is(testURI.spec, "http://www.foobar.org/", "Getters/Setters should work correctly");
is(SpecialPowers.wrap(document).getElementsByTagName('details').length, 0, "Should work with proxy-based DOM bindings.");
// Play with the window object.
var webnav = SpecialPowers.wrap(window).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsIWebNavigation);
webnav.QueryInterface(SpecialPowers.Ci.nsIDocShell);
ok(webnav.allowJavascript, "Able to pull properties off of docshell!");
// Make sure Xray-wrapped functions work.
try {
SpecialPowers.wrap(SpecialPowers.Components).ID('{00000000-0000-0000-0000-000000000000}');
ok(true, "Didn't throw");
}
catch (e) {
ok(false, "Threw while trying to call Xray-wrapped function.");
}
// Check constructors.
var BinaryInputStream = SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/binaryinputstream;1");
var bis = new BinaryInputStream();
ok(/nsISupports/.exec(bis.toString()), "Should get the proper object out of the constructor");
function TestConstructor() {
SpecialPowers.wrap(this).foo = 2;
}
var WrappedConstructor = SpecialPowers.wrap(TestConstructor);
is((new WrappedConstructor()).foo, 2, "JS constructors work properly when wrapped");
// Try messing around with QuickStubbed getters/setters and make sure the wrapper deals.
var ctx = SpecialPowers.wrap(document).getElementById('testcanvas').getContext('2d');
var pixels = ctx.getImageData(0,0,1,1);
try {
pixels.data;
ok(true, "Didn't throw getting quickstubbed accessor prop from proto");
}
catch (e) {
ok(false, "Threw while getting quickstubbed accessor prop from proto");
}
// Check functions that return null.
var returnsNull = function() { return null; }
is(SpecialPowers.wrap(returnsNull)(), null, "Should be able to handle functions that return null.");
// Check a function that throws.
var thrower = function() { throw new Error('hah'); }
try {
SpecialPowers.wrap(thrower)();
ok(false, "Should have thrown");
} catch (e) {
ok(SpecialPowers.isWrapper(e), "Exceptions should be wrapped for call");
is(e.message, 'hah', "Correct message");
}
try {
var ctor = SpecialPowers.wrap(thrower);
new ctor();
ok(false, "Should have thrown");
} catch (e) {
ok(SpecialPowers.isWrapper(e), "Exceptions should be wrapped for construct");
is(e.message, 'hah', "Correct message");
}
// Play around with a JS object to check the non-xray path.
var noxray_proto = {a: 3, b: 12};
var noxray = {a: 5, c: 32};
noxray.__proto__ = noxray_proto;
var noxray_wrapper = SpecialPowers.wrap(noxray);
is(noxray_wrapper.c, 32, "Regular properties should work.");
is(noxray_wrapper.a, 5, "Shadow properties should work.");
is(noxray_wrapper.b, 12, "Proto properties should work.");
noxray.b = 122;
is(noxray_wrapper.b, 122, "Should be able to shadow.");
// Try setting file input values via an Xray wrapper.
SpecialPowers.wrap(document).title = "foo";
is(document.title, "foo", "Set property correctly on Xray-wrapped DOM object");
is(SpecialPowers.wrap(document).URI, document.URI, "Got property correctly on Xray-wrapped DOM object");
info("\nProfile::SpecialPowersRunTime: " + (new Date() - startTime) + "\n");
// bug 855192
ok(SpecialPowers.MockPermissionPrompt, "check mock permission prompt");
// Set a pref using pushPrefEnv to make sure that flushPrefEnv is
// automatically called before we invoke
// test_SpecialPowersExtension2.html.
SpecialPowers.pushPrefEnv({set: [['testing.some_arbitrary_pref', true]]},
function() { SimpleTest.finish(); });
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,21 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers extension</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="content" class="testbody">
<script type="text/javascript">
dump("\nSPECIALPTEST2:::Loading test2 file now " + (new Date).getTime() + "\n");
is(SpecialPowers.sanityCheck(), "foo", "Special Powers top level");
ok(!SpecialPowers.Services.prefs.prefHasUserValue('testing.some_arbitrary_pref'),
"should not retain pref from previous test");
</script>
<iframe id="frame1" src="file_SpecialPowersFrame1.html">
</iframe>
</div>
</body>
</html>

View file

@ -0,0 +1,49 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers.loadChromeScript</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var url = SimpleTest.getTestFileURL("SpecialPowersLoadChromeScript.js");
var script = SpecialPowers.loadChromeScript(url);
var MESSAGE = { bar: true };
script.addMessageListener("bar", function (message) {
is(JSON.stringify(message), JSON.stringify(MESSAGE),
"received back message from the chrome script");
checkAssert();
});
function checkAssert() {
script.sendAsyncMessage("valid-assert");
script.addMessageListener("valid-assert-done", endOfTest);
}
function endOfTest() {
script.destroy();
SimpleTest.finish();
}
script.sendAsyncMessage("foo", MESSAGE);
/*
* [0][0] is because we're using one real message listener in SpecialPowersObserverAPI.js
* and dispatching that to multiple _chromeScriptListeners. The outer array comes
* from the message manager since there can be multiple real listeners. The inner
* array is for the return values of _chromeScriptListeners.
*/
is(script.sendSyncMessage("sync-message")[0][0], "Received a synchronous message.",
"Check sync return value");
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,67 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers.loadChromeScript</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var script = SpecialPowers.loadChromeScript(function loadChromeScriptTest() {
// Copied from SpecialPowersLoadChromeScript.js
// Just receive 'foo' message and forward it back
// as 'bar' message
addMessageListener("foo", function (message) {
sendAsyncMessage("bar", message);
});
addMessageListener("valid-assert", function (message) {
assert.ok(true, "valid assertion");
assert.equal(1, 1, "another valid assertion");
sendAsyncMessage("valid-assert-done");
});
addMessageListener("sync-message", () => {
return "Received a synchronous message.";
});
});
var MESSAGE = { bar: true };
script.addMessageListener("bar", function (message) {
is(JSON.stringify(message), JSON.stringify(MESSAGE),
"received back message from the chrome script");
checkAssert();
});
function checkAssert() {
script.sendAsyncMessage("valid-assert");
script.addMessageListener("valid-assert-done", endOfTest);
}
function endOfTest() {
script.destroy();
SimpleTest.finish();
}
script.sendAsyncMessage("foo", MESSAGE);
/*
* [0][0] is because we're using one real message listener in SpecialPowersObserverAPI.js
* and dispatching that to multiple _chromeScriptListeners. The outer array comes
* from the message manager since there can be multiple real listeners. The inner
* array is for the return values of _chromeScriptListeners.
*/
is(script.sendSyncMessage("sync-message")[0][0], "Received a synchronous message.",
"Check sync return value");
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers.loadChromeScript</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function loadPrivilegedScriptTest() {
var Cc = Components.classes;
var Ci = Components.interfaces;
function isMainProcess() {
return Cc["@mozilla.org/xre/app-info;1"].
getService(Ci.nsIXULRuntime).
processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
}
port.postMessage({'isMainProcess': isMainProcess()});
}
var contentProcessType = SpecialPowers.isMainProcess();
var port;
try {
port = SpecialPowers.loadPrivilegedScript(loadPrivilegedScriptTest.toSource());
} catch (e) {
ok(false, "loadPrivilegedScript shoulde not throw");
}
port.onmessage = (e) => {
is(contentProcessType, e.data['isMainProcess'], "content and the script should be in the same process");
SimpleTest.finish();
};
</script>

View file

@ -0,0 +1,237 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers extension</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="starttest();">
<pre id="test">
<script class="testbody" type="text/javascript">
const ALLOW_ACTION = SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION;
const DENY_ACTION = SpecialPowers.Ci.nsIPermissionManager.DENY_ACTION;
const UNKNOWN_ACTION = SpecialPowers.Ci.nsIPermissionManager.UNKNOWN_ACTION;
const PROMPT_ACTION = SpecialPowers.Ci.nsIPermissionManager.PROMPT_ACTION;
const ACCESS_SESSION = SpecialPowers.Ci.nsICookiePermission.ACCESS_SESSION;
const ACCESS_ALLOW_FIRST_PARTY_ONLY = SpecialPowers.Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY;
const ACCESS_LIMIT_THIRD_PARTY = SpecialPowers.Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY;
const EXPIRE_TIME = SpecialPowers.Ci.nsIPermissionManager.EXPIRE_TIME;
// expire Setting:
// start expire time point
// ----|------------------------|-----------
// <------------------------>
// PERIOD
var start;
// PR_Now() that called in nsPermissionManager to get the system time
// is sometimes 100ms~600s more than Date.now() on Android 4.3 API11.
// Thus, the PERIOD should be larger than 600ms in this test.
const PERIOD = 900;
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('specialPowers_framescript.js'));
SimpleTest.requestFlakyTimeout("untriaged");
function starttest(){
SpecialPowers.addPermission("pPROMPT", PROMPT_ACTION, document);
SpecialPowers.addPermission("pALLOW", ALLOW_ACTION, document);
SpecialPowers.addPermission("pDENY", DENY_ACTION, document);
SpecialPowers.addPermission("pREMOVE", ALLOW_ACTION, document);
SpecialPowers.addPermission("pSESSION", ACCESS_SESSION, document);
SpecialPowers.addPermission("pFIRSTPARTY", ACCESS_ALLOW_FIRST_PARTY_ONLY, document);
SpecialPowers.addPermission("pTHIRDPARTY", ACCESS_LIMIT_THIRD_PARTY, document);
setTimeout(test1, 0);
}
SimpleTest.waitForExplicitFinish();
function test1() {
if (!SpecialPowers.testPermission('pALLOW', ALLOW_ACTION, document)) {
dump('/**** allow not set ****/\n');
setTimeout(test1, 0);
} else if (!SpecialPowers.testPermission('pDENY', DENY_ACTION, document)) {
dump('/**** deny not set ****/\n');
setTimeout(test1, 0);
} else if (!SpecialPowers.testPermission('pPROMPT', PROMPT_ACTION, document)) {
dump('/**** prompt not set ****/\n');
setTimeout(test1, 0);
} else if (!SpecialPowers.testPermission('pREMOVE', ALLOW_ACTION, document)) {
dump('/**** remove not set ****/\n');
setTimeout(test1, 0);
} else if (!SpecialPowers.testPermission('pSESSION', ACCESS_SESSION, document)) {
dump('/**** ACCESS_SESSION not set ****/\n');
setTimeout(test1, 0);
} else if (!SpecialPowers.testPermission('pFIRSTPARTY', ACCESS_ALLOW_FIRST_PARTY_ONLY, document)) {
dump('/**** ACCESS_ALLOW_FIRST_PARTY_ONLY not set ****/\n');
setTimeout(test1, 0);
} else if (!SpecialPowers.testPermission('pTHIRDPARTY', ACCESS_LIMIT_THIRD_PARTY, document)) {
dump('/**** ACCESS_LIMIT_THIRD_PARTY not set ****/\n');
setTimeout(test1, 0);
} else {
test2();
}
}
function test2() {
ok(SpecialPowers.testPermission('pUNKNOWN', UNKNOWN_ACTION, document), 'pUNKNOWN value should have UNKOWN permission');
SpecialPowers.pushPermissions([{'type': 'pUNKNOWN', 'allow': true, 'context': document}, {'type': 'pALLOW', 'allow': false, 'context': document}, {'type': 'pDENY', 'allow': true, 'context': document}, {'type': 'pPROMPT', 'allow': true, 'context': document}, {'type': 'pSESSION', 'allow': true, 'context': document}, {'type': 'pFIRSTPARTY', 'allow': true, 'context': document}, {'type': 'pTHIRDPARTY', 'allow': true, 'context': document}, {'type': 'pREMOVE', 'remove': true, 'context': document}], test3);
}
function test3() {
ok(SpecialPowers.testPermission('pUNKNOWN', ALLOW_ACTION, document), 'pUNKNOWN value should have ALLOW permission');
ok(SpecialPowers.testPermission('pPROMPT', ALLOW_ACTION, document), 'pPROMPT value should have ALLOW permission');
ok(SpecialPowers.testPermission('pALLOW', DENY_ACTION, document), 'pALLOW should have DENY permission');
ok(SpecialPowers.testPermission('pDENY', ALLOW_ACTION, document), 'pDENY should have ALLOW permission');
ok(SpecialPowers.testPermission('pREMOVE', UNKNOWN_ACTION, document), 'pREMOVE should have REMOVE permission');
ok(SpecialPowers.testPermission('pSESSION', ALLOW_ACTION, document), 'pSESSION should have ALLOW permission');
ok(SpecialPowers.testPermission('pFIRSTPARTY', ALLOW_ACTION, document), 'pFIRSTPARTY should have ALLOW permission');
ok(SpecialPowers.testPermission('pTHIRDPARTY', ALLOW_ACTION, document), 'pTHIRDPARTY should have ALLOW permission');
// only pPROMPT (last one) is different, the other stuff is just to see if it doesn't cause test failures
SpecialPowers.pushPermissions([{'type': 'pUNKNOWN', 'allow': true, 'context': document}, {'type': 'pALLOW', 'allow': false, 'context': document}, {'type': 'pDENY', 'allow': true, 'context': document}, {'type': 'pPROMPT', 'allow': false, 'context': document}, {'type': 'pREMOVE', 'remove': true, 'context': document}], test3b);
}
function test3b() {
ok(SpecialPowers.testPermission('pPROMPT', DENY_ACTION, document), 'pPROMPT value should have DENY permission');
SpecialPowers.pushPermissions([{'type': 'pUNKNOWN', 'allow': DENY_ACTION, 'context': document}, {'type': 'pALLOW', 'allow': PROMPT_ACTION, 'context': document}, {'type': 'pDENY', 'allow': PROMPT_ACTION, 'context': document}, {'type': 'pPROMPT', 'allow': ALLOW_ACTION, 'context': document}], test4);
}
function test4() {
ok(SpecialPowers.testPermission('pUNKNOWN', DENY_ACTION, document), 'pUNKNOWN value should have DENY permission');
ok(SpecialPowers.testPermission('pPROMPT', ALLOW_ACTION, document), 'pPROMPT value should have ALLOW permission');
ok(SpecialPowers.testPermission('pALLOW', PROMPT_ACTION, document), 'pALLOW should have PROMPT permission');
ok(SpecialPowers.testPermission('pDENY', PROMPT_ACTION, document), 'pDENY should have PROMPT permission');
//this should reset all the permissions to before all the pushPermissions calls
SpecialPowers.flushPermissions(test5);
}
function test5() {
ok(SpecialPowers.testPermission('pUNKNOWN', UNKNOWN_ACTION, document), 'pUNKNOWN should have UNKNOWN permission');
ok(SpecialPowers.testPermission('pALLOW', ALLOW_ACTION, document), 'pALLOW should have ALLOW permission');
ok(SpecialPowers.testPermission('pDENY', DENY_ACTION, document), 'pDENY should have DENY permission');
ok(SpecialPowers.testPermission('pPROMPT', PROMPT_ACTION, document), 'pPROMPT should have PROMPT permission');
ok(SpecialPowers.testPermission('pREMOVE', ALLOW_ACTION, document), 'pREMOVE should have ALLOW permission');
ok(SpecialPowers.testPermission('pSESSION', ACCESS_SESSION, document), 'pSESSION should have ACCESS_SESSION permission');
ok(SpecialPowers.testPermission('pFIRSTPARTY', ACCESS_ALLOW_FIRST_PARTY_ONLY, document), 'pFIRSTPARTY should have ACCESS_ALLOW_FIRST_PARTY_ONLY permission');
ok(SpecialPowers.testPermission('pTHIRDPARTY', ACCESS_LIMIT_THIRD_PARTY, document), 'pTHIRDPARTY should have ACCESS_LIMIT_THIRD_PARTY permission');
SpecialPowers.removePermission("pPROMPT", document);
SpecialPowers.removePermission("pALLOW", document);
SpecialPowers.removePermission("pDENY", document);
SpecialPowers.removePermission("pREMOVE", document);
SpecialPowers.removePermission("pSESSION", document);
SpecialPowers.removePermission("pFIRSTPARTY", document);
SpecialPowers.removePermission("pTHIRDPARTY", document);
setTimeout(test6, 0);
}
function test6() {
if (!SpecialPowers.testPermission('pALLOW', UNKNOWN_ACTION, document)) {
dump('/**** allow still set ****/\n');
setTimeout(test6, 0);
} else if (!SpecialPowers.testPermission('pDENY', UNKNOWN_ACTION, document)) {
dump('/**** deny still set ****/\n');
setTimeout(test6, 0);
} else if (!SpecialPowers.testPermission('pPROMPT', UNKNOWN_ACTION, document)) {
dump('/**** prompt still set ****/\n');
setTimeout(test6, 0);
} else if (!SpecialPowers.testPermission('pREMOVE', UNKNOWN_ACTION, document)) {
dump('/**** remove still set ****/\n');
setTimeout(test6, 0);
} else if (!SpecialPowers.testPermission('pSESSION', UNKNOWN_ACTION, document)) {
dump('/**** pSESSION still set ****/\n');
setTimeout(test6, 0);
} else if (!SpecialPowers.testPermission('pFIRSTPARTY', UNKNOWN_ACTION, document)) {
dump('/**** pFIRSTPARTY still set ****/\n');
setTimeout(test6, 0);
} else if (!SpecialPowers.testPermission('pTHIRDPARTY', UNKNOWN_ACTION, document)) {
dump('/**** pTHIRDPARTY still set ****/\n');
setTimeout(test6, 0);
} else {
test7();
}
}
function test7() {
afterPermissionChanged('pEXPIRE', 'deleted', test8);
afterPermissionChanged('pEXPIRE', 'added', permissionPollingCheck);
start = Number(Date.now());
SpecialPowers.addPermission('pEXPIRE',
true,
document,
EXPIRE_TIME,
(start + PERIOD + getPlatformInfo().timeCompensation));
}
function test8() {
afterPermissionChanged('pEXPIRE', 'deleted', SimpleTest.finish);
afterPermissionChanged('pEXPIRE', 'added', permissionPollingCheck);
start = Number(Date.now());
SpecialPowers.pushPermissions([
{ 'type': 'pEXPIRE',
'allow': true,
'expireType': EXPIRE_TIME,
'expireTime': (start + PERIOD + getPlatformInfo().timeCompensation),
'context': document
}], function() {
info("Wait for permission-changed signal!");
}
);
}
function afterPermissionChanged(type, op, callback) {
// handle the message from specialPowers_framescript.js
gScript.addMessageListener('perm-changed', function onChange(msg) {
if (msg.type == type && msg.op == op) {
gScript.removeMessageListener('perm-changed', onChange);
callback();
}
});
}
function permissionPollingCheck() {
var now = Number(Date.now());
if (now < (start + PERIOD)) {
if (SpecialPowers.testPermission('pEXPIRE', ALLOW_ACTION, document)) {
// To make sure that permission will be expired in next round,
// the next permissionPollingCheck calling will be fired 100ms later after
// permission is out-of-period.
setTimeout(permissionPollingCheck, PERIOD + 100);
return;
}
errorHandler('unexpired permission should be allowed!');
}
// The permission is already expired!
if (SpecialPowers.testPermission('pEXPIRE', ALLOW_ACTION, document)) {
errorHandler('expired permission should be removed!');
}
}
function getPlatformInfo() {
var version = SpecialPowers.Services.sysinfo.getProperty('version');
version = parseFloat(version);
// PR_Now() that called in nsPermissionManager to get the system time and
// Date.now() are out of sync on win32 platform(XP/win7). The PR_Now() is
// 15~20ms less than Date.now(). Unfortunately, this time skew can't be
// avoided, so it needs to add a time buffer to compensate.
// Version 5.1 is win XP, 6.1 is win7
if (navigator.platform.startsWith('Win32') && (version <= 6.1)) {
return { platform: "Win32", timeCompensation: -100 };
}
return { platform: "NoMatter", timeCompensation: 0 };
}
function errorHandler(msg) {
ok(false, msg);
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,211 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers extension</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="starttest();">
<pre id="test">
<script class="testbody" type="text/javascript">
function starttest() {
try {
SpecialPowers.setBoolPref("test.bool", 1);
} catch(e) {
SpecialPowers.setBoolPref("test.bool", true);
}
try {
SpecialPowers.setIntPref("test.int", true);
} catch(e) {
SpecialPowers.setIntPref("test.int", 1);
}
SpecialPowers.setCharPref("test.char", 'test');
setTimeout(test1, 0, 0);
}
SimpleTest.waitForExplicitFinish();
function test1(aCount) {
if (aCount >= 20) {
ok(false, "Too many times attempting to set pref, aborting");
SimpleTest.finish();
return;
}
try {
is(SpecialPowers.getBoolPref('test.bool'), true, 'test.bool should be true');
} catch(e) {
setTimeout(test1, 0, ++aCount);
return;
}
try {
is(SpecialPowers.getIntPref('test.int'), 1, 'test.int should be 1');
} catch(e) {
setTimeout(test1, 0, ++aCount);
return;
}
try {
is(SpecialPowers.getCharPref('test.char'), 'test', 'test.char should be test');
} catch(e) {
setTimeout(test1, 0, ++aCount);
return;
}
test2();
}
function test2() {
// test non-changing values
SpecialPowers.pushPrefEnv({"set": [["test.bool", true], ["test.int", 1], ["test.char", "test"]]}, test3);
}
function test3() {
// test changing char pref using the Promise
is(SpecialPowers.getBoolPref('test.bool'), true, 'test.bool should be true');
is(SpecialPowers.getIntPref('test.int'), 1, 'test.int should be 1');
is(SpecialPowers.getCharPref('test.char'), 'test', 'test.char should be test');
SpecialPowers.pushPrefEnv({"set": [["test.bool", true], ["test.int", 1], ["test.char", "test2"]]}).then(test4);
}
function test4() {
// test changing all values and adding test.char2 pref
is(SpecialPowers.getCharPref('test.char'), 'test2', 'test.char should be test2');
SpecialPowers.pushPrefEnv({"set": [["test.bool", false], ["test.int", 10], ["test.char", "test2"], ["test.char2", "test"]]}, test5);
}
function test5() {
// test flushPrefEnv
is(SpecialPowers.getBoolPref('test.bool'), false, 'test.bool should be false');
is(SpecialPowers.getIntPref('test.int'), 10, 'test.int should be 10');
is(SpecialPowers.getCharPref('test.char'), 'test2', 'test.char should be test2');
is(SpecialPowers.getCharPref('test.char2'), 'test', 'test.char2 should be test');
SpecialPowers.flushPrefEnv(test6);
}
function test6() {
// test clearing prefs
is(SpecialPowers.getBoolPref('test.bool'), true, 'test.bool should be true');
is(typeof SpecialPowers.getBoolPref('test.bool'), typeof true, 'test.bool should be boolean');
is(SpecialPowers.getIntPref('test.int'), 1, 'test.int should be 1');
is(typeof SpecialPowers.getIntPref('test.int'), typeof 1, 'test.int should be integer');
is(SpecialPowers.getCharPref('test.char'), 'test', 'test.char should be test');
is(typeof SpecialPowers.getCharPref('test.char'), typeof 'test', 'test.char should be String');
try {
SpecialPowers.getCharPref('test.char2');
ok(false, 'This ok should not be reached!');
} catch(e) {
ok(true, 'getCharPref("test.char2") should throw');
}
SpecialPowers.pushPrefEnv({"clear": [["test.bool"], ["test.int"], ["test.char"], ["test.char2"]]}, test6b);
}
function test6b() {
// test if clearing another time doesn't cause issues
SpecialPowers.pushPrefEnv({"clear": [["test.bool"], ["test.int"], ["test.char"], ["test.char2"]]}, test7);
}
function test7() {
try {
SpecialPowers.getBoolPref('test.bool');
ok(false, 'This ok should not be reached!');
} catch(e) {
ok(true, 'getBoolPref("test.bool") should throw');
}
try {
SpecialPowers.getIntPref('test.int');
ok(false, 'This ok should not be reached!');
} catch(e) {
ok(true, 'getIntPref("test.int") should throw');
}
try {
SpecialPowers.getCharPref('test.char');
ok(false, 'This ok should not be reached!');
} catch(e) {
ok(true, 'getCharPref("test.char") should throw');
}
try {
SpecialPowers.getCharPref('test.char2');
ok(false, 'This ok should not be reached!');
} catch(e) {
ok(true, 'getCharPref("test.char2") should throw');
}
SpecialPowers.flushPrefEnv().then(test8);
}
function test8() {
is(SpecialPowers.getBoolPref('test.bool'), true, 'test.bool should be true');
is(typeof SpecialPowers.getBoolPref('test.bool'), typeof true, 'test.bool should be boolean');
is(SpecialPowers.getIntPref('test.int'), 1, 'test.int should be 1');
is(typeof SpecialPowers.getIntPref('test.int'), typeof 1, 'test.int should be integer');
is(SpecialPowers.getCharPref('test.char'), 'test', 'test.char should be test');
is(typeof SpecialPowers.getCharPref('test.char'), typeof 'test', 'test.char should be String');
try {
SpecialPowers.getCharPref('test.char2');
ok(false, 'This ok should not be reached!');
} catch(e) {
ok(true, 'getCharPref("test.char2") should throw');
}
SpecialPowers.clearUserPref("test.bool");
SpecialPowers.clearUserPref("test.int");
SpecialPowers.clearUserPref("test.char");
setTimeout(test9, 0, 0);
}
function test9(aCount) {
if (aCount >= 20) {
ok(false, "Too many times attempting to set pref, aborting");
SimpleTest.finish();
return;
}
try {
SpecialPowers.getBoolPref('test.bool');
setTimeout(test9, 0, ++aCount);
} catch(e) {
test10(0);
}
}
function test10(aCount) {
if (aCount >= 20) {
ok(false, "Too many times attempting to set pref, aborting");
SimpleTest.finish();
return;
}
try {
SpecialPowers.getIntPref('test.int');
setTimeout(test10, 0, ++aCount);
} catch(e) {
test11(0);
}
}
function test11(aCount) {
if (aCount >= 20) {
ok(false, "Too many times attempting to set pref, aborting");
SimpleTest.finish();
return;
}
try {
SpecialPowers.getCharPref('test.char');
setTimeout(test11, 0, ++aCount);
} catch(e) {
SimpleTest.finish();
}
}
// todo - test non-changing values, test complex values, test mixing of pushprefEnv 'set' and 'clear'
// When bug 776424 gets fixed, getPref doesn't throw anymore, so this test would have to be changed accordingly
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for whether SimpLeTest.ok after SimpleTest.finish is causing an error to be logged</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="content" class="testbody">
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(true, "This should pass");
SimpleTest.finish();
});
window.onbeforeunload = function() {
ok(true, "This should cause failures in the harness, because it's run after SimpleTest.finish()");
}
</script>
</div>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for mochitest add_task, found in SpawnTask.js</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 1187701</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script class="testbody" type="text/javascript">
// Check that we can 'add_task' a few times and all tasks run asynchronously before test finishes.
add_task(function* () {
var x = yield Promise.resolve(1);
is(x, 1, "task yields Promise value as expected");
});
add_task(function* () {
var x = yield [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)];
is(x.join(""), "123", "task yields Promise value as expected");
});
add_task(function* () {
var x = yield (function* () {
return 3;
}());
is(x, 3, "task yields generator function return value as expected");
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=649012
-->
<head>
<title>Test for Bug 649012</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=649012">Mozilla Bug 649012</a>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 649012 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
// Test that setTimeout(f, 0) doesn't raise an error
setTimeout(function() {
// Test that setTimeout(f, t) where t > 0 doesn't raise an error if we've used
// SimpleTest.requestFlakyTimeout
SimpleTest.requestFlakyTimeout("Just testing to make sure things work. I would never do this in real life of course!");
setTimeout(function() {
SimpleTest.finish();
}, 1);
}, 0);
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,91 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers.createFiles</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="content" class="testbody">
<script type="text/javascript">
// Creating one file, followed by failing to create a file.
function test1() {
const fileType = "some file type";
let fdata = "this is same data for a file";
SpecialPowers.createFiles([{name: "test1.txt", data:fdata, options:{type:fileType}}],
function (files) {
is(files.length, 1, "Created 1 file");
let f = files[0];
is("[object File]", f.toString(), "first thing in array is a file");
is(f.size, fdata.length, "test1 size of first file should be length of its data");
is("test1.txt", f.name, "test1 test file should have the right name");
is(f.type, fileType, "File should have the specified type");
test2();
},
function (msg) { ok(false, "Should be able to create a file without an error"); test2(); }
);
}
// Failing to create a file, followed by creating a file.
function test2() {
function test3Check(passed) {
ok(passed, "Should trigger the error handler for a bad file name.");
test3();
};
SpecialPowers.createFiles([{name: "/\/\/\/\/\/\/\/\/\/\/\invalidname",}],
function () { test3Check(false); },
function (msg) { test3Check(true); }
);
}
// Creating two files at the same time.
function test3() {
let f1data = "hello";
SpecialPowers.createFiles([{name: "test3_file.txt", data:f1data}, {name: "emptyfile.txt"}],
function (files) {
is(files.length, 2, "Expected two files to be created");
let f1 = files[0];
let f2 = files[1];
is("[object File]", f1.toString(), "first thing in array is a file");
is("[object File]", f2.toString(), "second thing in array is a file");
is("test3_file.txt", f1.name, "first test3 test file should have the right name");
is("emptyfile.txt", f2.name, "second test3 test file should have the right name");
is(f1.size, f1data.length, "size of first file should be length of its data");
is(f2.size, 0, "size of second file should be 0");
test4();
},
function (msg) {
ok(false, "Failed to create files: " + msg);
test4();
}
);
};
// Creating a file without specifying a name should work.
function test4() {
let fdata = "this is same data for a file";
SpecialPowers.createFiles([{data:fdata}],
function (files) {
is(files.length, 1, "Created 1 file");
let f = files[0];
is("[object File]", f.toString(), "first thing in array is a file");
is(f.size, fdata.length, "test4 size of first file should be length of its data");
ok(f.name, "test4 test file should have a name");
SimpleTest.finish();
},
function (msg) {
ok(false, "Should be able to create a file without a name without an error");
SimpleTest.finish();
}
);
}
SimpleTest.waitForExplicitFinish();
test1();
</script>
</div>
</body>
</html>

View file

@ -0,0 +1,54 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers.importInMainProcess</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="content" class="testbody">
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
var failed = false;
try {
SpecialPowers.importInMainProcess("invalid file for import");
} catch (e) {
ok(e.toString().indexOf("NS_ERROR_MALFORMED_URI") > -1, "Exception should be for a malformed URI");
failed = true;
}
ok(failed, "An invalid import should throw");
const testingResource = "resource://testing-common/ImportTesting.jsm";
var script = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('importtesting_chromescript.js'));
script.addMessageListener("ImportTesting:IsModuleLoadedReply", handleFirstReply);
script.sendAsyncMessage("ImportTesting:IsModuleLoaded", testingResource);
function handleFirstReply(aMsg) {
ok(!aMsg, "ImportTesting.jsm shouldn't be loaded before we import it");
try {
SpecialPowers.importInMainProcess(testingResource);
} catch (e) {
ok(false, "Unexpected exception when importing a valid resource: " + e.toString());
}
script.removeMessageListener("ImportTesting:IsModuleLoadedReply", handleFirstReply);
script.addMessageListener("ImportTesting:IsModuleLoadedReply", handleSecondReply);
script.sendAsyncMessage("ImportTesting:IsModuleLoaded", testingResource);
}
function handleSecondReply(aMsg) {
script.removeMessageListener("ImportTesting:IsModuleLoadedReply", handleSecondReply);
ok(aMsg, "ImportTesting.jsm should be loaded after we import it");
SimpleTest.finish();
}
</script>
</div>
</body>
</html>

View file

@ -0,0 +1,63 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for mochitest harness sanity</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
<p id="display">
<input id="testKeyEvent1" onkeypress="press1 = true">
<input id="testKeyEvent2" onkeydown="return false;" onkeypress="press2 = true">
<input id="testKeyEvent3" onkeypress="press3 = true">
<input id="testKeyEvent4" onkeydown="return false;" onkeypress="press4 = true">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for sanity **/
ok(true, "true must be ok");
isnot(1, true, "1 must not be true");
isnot(1, false, "1 must not be false");
isnot(0, false, "0 must not be false");
isnot(0, true, "0 must not be true");
isnot("", 0, "Empty string must not be 0");
isnot("1", 1, "Numeric string must not equal the number");
isnot("", null, "Empty string must not be null");
isnot(undefined, null, "Undefined must not be null");
var press1 = false;
$("testKeyEvent1").focus();
synthesizeKey("x", {});
is($("testKeyEvent1").value, "x", "synthesizeKey should work");
is(press1, true, "synthesizeKey should dispatch keyPress");
var press2 = false;
$("testKeyEvent2").focus();
synthesizeKey("x", {});
is($("testKeyEvent2").value, "", "synthesizeKey should respect keydown preventDefault");
is(press2, false, "synthesizeKey should not dispatch keyPress with default prevented");
var press3 = false;
$("testKeyEvent3").focus();
sendChar("x")
is($("testKeyEvent3").value, "x", "sendChar should work");
is(press3, true, "sendChar should dispatch keyPress");
var press4 = false;
$("testKeyEvent4").focus();
sendChar("x")
is($("testKeyEvent4").value, "", "sendChar should respect keydown preventDefault");
is(press4, false, "sendChar should not dispatch keyPress with default prevented");
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,188 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Profiling test suite for EventUtils</title>
<script type="text/javascript">
var start = new Date();
</script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript">
var loadTime = new Date();
</script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="starttest()">
<input type="radio" id="radioTarget1" name="group">Radio Target 1</input>
<input id="textBoxA">
<input id="textBoxB">
<input id="testMouseEvent" type="button" value="click">
<input id="testKeyEvent" >
<input id="testStrEvent" >
<div id="scrollB" style="width: 190px;height: 250px;overflow:auto">
<p>blah blah blah blah</p>
<p>blah blah blah blah</p>
<p>blah blah blah blah</p>
<p>blah blah blah blah</p>
<p>blah blah blah blah</p>
<p>blah blah blah blah</p>
<p>blah blah blah blah</p>
<p>blah blah blah blah</p>
</div>
<script class="testbody" type="text/javascript">
info("\nProfile::EventUtilsLoadTime: " + (loadTime - start) + "\n");
function starttest() {
SimpleTest.waitForFocus(
function () {
SimpleTest.waitForExplicitFinish();
var startTime = new Date();
var check = false;
/* test send* functions */
$("testMouseEvent").addEventListener("click", function() { check=true; }, false);
sendMouseEvent({type:'click'}, "testMouseEvent");
is(check, true, 'sendMouseEvent should dispatch click event');
check = false;
$("testKeyEvent").addEventListener("keypress", function() { check = true; }, false);
$("testKeyEvent").focus();
sendChar("x");
is($("testKeyEvent").value, "x", "sendChar should work");
is(check, true, "sendChar should dispatch keyPress");
$("testKeyEvent").value = "";
$("testStrEvent").focus();
sendString("string");
is($("testStrEvent").value, "string", "sendString should work");
$("testStrEvent").value = "";
check = false;
$("testKeyEvent").focus();
sendKey("DOWN");
is(check, true, "sendKey should dispatch keyPress");
/* test synthesizeMouse* */
//focus trick enables us to run this in iframes
$("radioTarget1").addEventListener('focus', function (aEvent) {
$("radioTarget1").removeEventListener('focus', arguments.callee, false);
synthesizeMouse($("radioTarget1"), 1, 1, {});
is($("radioTarget1").checked, true, "synthesizeMouse should work")
$("radioTarget1").checked = false;
disableNonTestMouseEvents(true);
synthesizeMouse($("radioTarget1"), 1, 1, {});
is($("radioTarget1").checked, true, "synthesizeMouse should still work with non-test mouse events disabled");
$("radioTarget1").checked = false;
disableNonTestMouseEvents(false);
});
$("radioTarget1").focus();
//focus trick enables us to run this in iframes
$("textBoxA").addEventListener("focus", function (aEvent) {
$("textBoxA").removeEventListener("focus", arguments.callee, false);
check = false;
$("textBoxA").addEventListener("click", function() { check = true; }, false);
synthesizeMouseAtCenter($("textBoxA"), {});
is(check, true, 'synthesizeMouse should dispatch mouse event');
check = false;
synthesizeMouseExpectEvent($("textBoxA"), 1, 1, {}, $("textBoxA"), "click", "synthesizeMouseExpectEvent should fire click event");
is(check, true, 'synthesizeMouse should dispatch mouse event');
});
$("textBoxA").focus();
/**
* TODO: testing synthesizeWheel requires a setTimeout
* since there is delay between the scroll event and a check, so for now just test
* that we can successfully call it to avoid having setTimeout vary the runtime metric.
* Testing of this method is currently done here:
* toolkit/content/tests/chrome/test_mousescroll.xul
*/
synthesizeWheel($("scrollB"), 5, 5, {'deltaY': 10.0, deltaMode: WheelEvent.DOM_DELTA_LINE});
/* test synthesizeKey* */
check = false;
$("testKeyEvent").addEventListener("keypress", function() { check = true; }, false);
$("testKeyEvent").focus();
synthesizeKey("a", {});
is($("testKeyEvent").value, "a", "synthesizeKey should work");
is(check, true, "synthesizeKey should dispatch keyPress");
$("testKeyEvent").value = "";
check = false;
synthesizeKeyExpectEvent("a", {}, $("testKeyEvent"), "keypress");
is($("testKeyEvent").value, "a", "synthesizeKey should work");
is(check, true, "synthesizeKey should dispatch keyPress");
$("testKeyEvent").value = "";
/* test synthesizeComposition */
$("textBoxB").focus();
check = false;
window.addEventListener("compositionstart", function() { check = true; }, false);
synthesizeComposition({ type: "compositionstart" });
is(check, true, 'synthesizeComposition() should dispatch compositionstart');
check = false;
window.addEventListener("compositionupdate", function() { check = true; }, false);
synthesizeComposition({ type: "compositionupdate", data: "a" });
is(check, false, 'synthesizeComposition() should not dispatch compositionupdate without error');
check = false;
window.addEventListener("text", function() { check = true; }, false);
synthesizeCompositionChange(
{ "composition":
{ "string": "a",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
}
);
is(check, true, "synthesizeCompositionChange should cause dispatching a DOM text event");
synthesizeCompositionChange(
{ "composition":
{ "string": "a",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
}
);
check = false;
window.addEventListener("compositionend", function() { check = true; }, false);
synthesizeComposition({ type: "compositionend", data: "a" });
is(check, false, 'synthesizeComposition() should not dispatch compositionend');
synthesizeComposition({ type: "compositioncommit", data: "a" });
is(check, true, 'synthesizeComposition() should dispatch compositionend');
var querySelectedText = synthesizeQuerySelectedText();
ok(querySelectedText, "query selected text event result is null");
ok(querySelectedText.succeeded, "query selected text event failed");
is(querySelectedText.offset, 1,
"query selected text event returns wrong offset");
is(querySelectedText.text, "",
"query selected text event returns wrong selected text");
$("textBoxB").value = "";
querySelectedText = synthesizeQuerySelectedText();
ok(querySelectedText, "query selected text event result is null");
ok(querySelectedText.succeeded, "query selected text event failed");
is(querySelectedText.offset, 0,
"query selected text event returns wrong offset");
is(querySelectedText.text, "",
"query selected text event returns wrong selected text");
var endTime = new Date();
info("\nProfile::EventUtilsRunTime: " + (endTime-startTime) + "\n");
SimpleTest.finish();
}
);
};
</script>
</body>
</html>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Test that uncaught exceptions in mochitests cause failures</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=670817">Mozilla Bug 670817</a>
<script>
ok(true, "a call to ok");
SimpleTest.expectUncaughtException();
throw "an uncaught exception";
</script>
</body>
</html>

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<title>Test that uncaught exceptions in mochitests cause failures</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=670817">Mozilla Bug 670817</a>
<script>
SimpleTest.waitForExplicitFinish();
ok(true, "a call to ok");
SimpleTest.executeSoon(function() {
SimpleTest.expectUncaughtException();
throw "an uncaught exception";
});
SimpleTest.executeSoon(function() {
SimpleTest.finish();
});
</script>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for exposing test suite information</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
ok(SimpleTest.harnessParameters, "Should have parameters.");
</script>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Test that service worker registrations not cleaned up in mochitests cause failures</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<script>
SimpleTest.waitForExplicitFinish();
SimpleTest.expectRegisteredServiceWorker();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, function() {
navigator.serviceWorker.register("empty.js", {scope: "scope"})
.then(function(registration) {
ok(registration, "Registration succeeded");
SimpleTest.finish();
});
});
</script>
</body>
</html>

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Test that service worker registrations not cleaned up in mochitests cause failures</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<script>
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, function() {
navigator.serviceWorker.getRegistration("scope")
.then(function(registration) {
ok(registration, "Registration successfully obtained");
return registration.unregister();
}).then(function() {
SimpleTest.finish();
});
});
</script>
</body>
</html>

View file

@ -0,0 +1,95 @@
<!--This test should be updated each time new functionality is added to SimpleTest-->
<!DOCTYPE HTML>
<html>
<head>
<title>Profiling test suite for SimpleTest</title>
<script type="text/javascript">
var start = new Date();
</script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript">
var loadTime = new Date();
</script>
</head>
<body>
<input id="textB"/>
<script class="testbody" type="text/javascript">
info("Profile::SimpleTestLoadTime: " + (loadTime - start));
var startTime = new Date();
SimpleTest.waitForExplicitFinish();
function starttest() {
SimpleTest.waitForFocus(
function() {
//test log
info("Logging some info")
//basic usage
ok(true, "test ok", "This should be true");
is(0, 0, "is() test failed");
isnot(0, 1, "isnot() test failed");
//todo tests
todo(false, "test todo", "todo() test should not pass");
todo_is(false, true, "test todo_is");
todo_isnot(true, true, "test todo_isnot");
//misc
SimpleTest.requestLongerTimeout(1);
//note: this test may alter runtimes as it waits
var check = false;
$('textB').focus();
SimpleTest.waitForClipboard("a",
function () {
SpecialPowers.clipboardCopyString("a");
},
function () {
check = true;
},
function () {
check = false;
}
);
is(check, true, "waitForClipboard should work");
//use helper functions
var div1 = createEl('div', {'id': 'somediv', 'display': 'block'}, "I am a div");
document.body.appendChild(div1);
var divObj = this.getElement('somediv');
is(divObj, div1, 'createEl did not create element as expected');
is($('somediv'), divObj, '$ helper did not get element as expected');
is(computedStyle(divObj, 'display'), 'block', 'computedStyle did not get right display value');
document.body.removeChild(div1);
/* note: expectChildProcessCrash is not being tested here, as it causes wildly variable
* run times. It is currently being tested in:
* dom/plugins/test/test_hanging.html and dom/plugins/test/test_crashing.html
*/
//note: this also adds a short wait period
SimpleTest.executeSoon(
function () {
//finish() calls a slew of SimpleTest functions
SimpleTest.finish();
//call this after finish so we can make sure it works and doesn't hang our process
var endTime = new Date();
info("Profile::SimpleTestRunTime: " + (endTime-startTime));
//expect and throw exception here. Otherwise, any code that follows the throw call will never be executed
SimpleTest.expectUncaughtException();
//make sure we catch this error
throw "i am an uncaught exception"
}
);
}
);
};
//use addLoadEvent
addLoadEvent(
function() {
starttest();
}
);
</script>
</body>
</html>

View file

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Profiling test suite for WindowSnapshot</title>
<script type="text/javascript">
var start = new Date();
</script>
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<script type="text/javascript">
var loadTime = new Date();
</script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="starttest()">
<script class="testbody" type="text/javascript">
info("\nProfile::WindowSnapshotLoadTime: " + (loadTime - start) + "\n");
function starttest() {
SimpleTest.waitForExplicitFinish();
var startTime = new Date();
var snap = snapshotWindow(window, false);
var snap2 = snapshotWindow(window, false);
is(compareSnapshots(snap, snap2, true)[0], true, "this should be true");
var div1 = createEl('div', {'id': 'somediv', 'display': 'block'}, "I am a div");
document.body.appendChild(div1);
snap2 = snapshotWindow(window, false);
is(compareSnapshots(snap, snap2, true)[0], false, "this should be false");
document.body.removeChild(div1);
var endTime = new Date();
info("\nProfile::WindowSnapshotRunTime: " + (endTime-startTime) + "\n");
SimpleTest.finish();
};
</script>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>SimpleTest.registerCleanupFunction test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
// Not a great example, since we have the pushPrefEnv API to cover
// this use case, but I want to be able to test that the cleanup
// function gets run, so setting and clearing a pref seems straightforward.
function do_cleanup1() {
SpecialPowers.clearUserPref("simpletest.cleanup.1");
info("do_cleanup1 run!");
}
function do_cleanup2() {
SpecialPowers.clearUserPref("simpletest.cleanup.2");
info("do_cleanup2 run!");
}
SpecialPowers.setBoolPref("simpletest.cleanup.1", true);
SpecialPowers.setBoolPref("simpletest.cleanup.2", true);
SimpleTest.registerCleanupFunction(do_cleanup1);
SimpleTest.registerCleanupFunction(do_cleanup2);
ok(true, "dummy check");
</script>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>SimpleTest.registerCleanupFunction test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
for (pref of [1, 2]) {
try {
SpecialPowers.getBoolPref("simpletest.cleanup." + pref);
ok(false, "Cleanup function should have unset pref");
}
catch(ex) {
ok(true, "Pref was not set");
}
}
</script>
</body>
</html>

View file

@ -0,0 +1,16 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>SimpleTest.expected = 'fail' test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
ok(false, "We expect this to fail");
</script>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>SimpleTest.expected = 'fail' test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
ok(true, "We expect this to pass");
ok(false, "We expect this to fail");
</script>
</body>
</html>

View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SimpleTest.waitForCondition test</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
var captureFailure = false;
var capturedFailures = [];
window.ok = function (cond, name, diag) {
if (!captureFailure) {
SimpleTest.ok(cond, name, diag);
} else {
if (cond) {
SimpleTest.ok(false, `Expect a failure with "${name}"`);
} else {
capturedFailures.push(name);
}
}
};
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("test behavior SimpleTest.waitForCondition");
addLoadEvent(testNormal);
function testNormal() {
var condition = false;
SimpleTest.waitForCondition(() => condition, () => {
ok(condition, "Should only be called when condition is true");
SimpleTest.executeSoon(testTimeout);
}, "Shouldn't timeout");
setTimeout(() => { condition = true; }, 1000);
}
function testTimeout() {
captureFailure = true;
SimpleTest.waitForCondition(() => false, () => {
captureFailure = false;
is(capturedFailures.length, 1, "Should captured one failure");
is(capturedFailures[0], "Should timeout",
"Should capture the failure passed in");
SimpleTest.executeSoon(() => SimpleTest.finish());
}, "Should timeout");
}
</script>
</body>
</html>

View file

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for mochitest SpawnTask.js sanity</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 1078657</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for sanity **/
SimpleTest.waitForExplicitFinish();
var externalGeneratorFunction = function* () {
return 8;
};
var nestedFunction = function* () {
return yield function* () {
return yield function* () {
return yield function* () {
return yield Promise.resolve(9);
}();
}();
}();
}
var variousTests = function* () {
var val1 = yield [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)];
is(val1.join(""), "123", "Array of promises -> Promise.all");
var val2 = yield Promise.resolve(2);
is(val2, 2, "Resolved promise yields value.");
var val3 = yield function* () { return 3; };
is(val3, 3, "Generator functions are spawned.");
//var val4 = yield function () { return 4; };
//is(val4, 4, "Plain functions run and return.");
var val5 = yield (function* () { return 5; }());
is(val5, 5, "Generators are spawned.");
try {
var val6 = yield Promise.reject(Error("error6"));
ok(false, "Shouldn't reach this line.");
} catch (error) {
is(error.message, "error6", "Rejected promise throws error.");
}
try {
var val7 = yield function* () { throw Error("error7"); };
ok(false, "Shouldn't reach this line.");
} catch (error) {
is(error.message, "error7", "Thrown error propagates.");
}
var val8 = yield externalGeneratorFunction();
is(val8, 8, "External generator also spawned.");
var val9 = yield nestedFunction();
is(val9, 9, "Nested generator functions work.");
return 10;
};
spawn_task(variousTests).then(function(result) {
is(result, 10, "spawn_task(...) returns promise");
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,69 @@
MochiKit is dual-licensed software. It is available under the terms of the
MIT License, or the Academic Free License version 2.1. The full text of
each license is included below.
MIT License
===========
Copyright (c) 2005 Bob Ippolito. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Academic Free License v. 2.1
============================
Copyright (c) 2005 Bob Ippolito. All rights reserved.
This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
Licensed under the Academic Free License version 2.1
1) Grant of Copyright License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license to do the following:
a) to reproduce the Original Work in copies;
b) to prepare derivative works ("Derivative Works") based upon the Original Work;
c) to distribute copies of the Original Work and Derivative Works to the public;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) Grant of Patent License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, to make, use, sell and offer for sale the Original Work and Derivative Works.
3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor hereby agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work, and by publishing the address of that information repository in a notice immediately following the copyright notice that applies to the Original Work.
4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior written permission of the Licensor. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor except as expressly stated herein. No patent license is granted to make, use, sell or offer to sell embodiments of any patent claims other than the licensed claims defined in Section 2. No right is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any Original Work that Licensor otherwise would have a right to license.
5) This section intentionally omitted.
6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately proceeding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to Original Work is granted hereunder except under this disclaimer.
8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to any person for any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to liability for death or personal injury resulting from Licensor's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.
9) Acceptance and Termination. If You distribute copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. Nothing else but this License (or another written agreement between Licensor and You) grants You permission to create Derivative Works based upon the Original Work or to exercise any of the rights granted in Section 1 herein, and any attempt to do so except under the terms of this License (or another written agreement between Licensor and You) is expressly prohibited by U.S. copyright law, the equivalent laws of other countries, and by international treaty. Therefore, by exercising any of the rights granted to You in Section 1 herein, You indicate Your acceptance of this License and all of its terms and conditions.
10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et seq., the equivalent laws of other countries, and international treaty. This section shall survive the termination of this License.
12) Attorneys Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
13) Miscellaneous. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. Permission is hereby granted to copy and distribute this license without modification. This license may not be modified without the express written permission of its copyright owner.

View file

@ -0,0 +1,682 @@
/***
MochiKit.Async 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('Async', ['Base']);
MochiKit.Async.NAME = "MochiKit.Async";
MochiKit.Async.VERSION = "1.4.2";
MochiKit.Async.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Async.toString = function () {
return this.__repr__();
};
/** @id MochiKit.Async.Deferred */
MochiKit.Async.Deferred = function (/* optional */ canceller) {
this.chain = [];
this.id = this._nextId();
this.fired = -1;
this.paused = 0;
this.results = [null, null];
this.canceller = canceller;
this.silentlyCancelled = false;
this.chained = false;
};
MochiKit.Async.Deferred.prototype = {
/** @id MochiKit.Async.Deferred.prototype.repr */
repr: function () {
var state;
if (this.fired == -1) {
state = 'unfired';
} else if (this.fired === 0) {
state = 'success';
} else {
state = 'error';
}
return 'Deferred(' + this.id + ', ' + state + ')';
},
toString: MochiKit.Base.forwardCall("repr"),
_nextId: MochiKit.Base.counter(),
/** @id MochiKit.Async.Deferred.prototype.cancel */
cancel: function () {
var self = MochiKit.Async;
if (this.fired == -1) {
if (this.canceller) {
this.canceller(this);
} else {
this.silentlyCancelled = true;
}
if (this.fired == -1) {
this.errback(new self.CancelledError(this));
}
} else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
this.results[0].cancel();
}
},
_resback: function (res) {
/***
The primitive that means either callback or errback
***/
this.fired = ((res instanceof Error) ? 1 : 0);
this.results[this.fired] = res;
this._fire();
},
_check: function () {
if (this.fired != -1) {
if (!this.silentlyCancelled) {
throw new MochiKit.Async.AlreadyCalledError(this);
}
this.silentlyCancelled = false;
return;
}
},
/** @id MochiKit.Async.Deferred.prototype.callback */
callback: function (res) {
this._check();
if (res instanceof MochiKit.Async.Deferred) {
throw new Error("Deferred instances can only be chained if they are the result of a callback");
}
this._resback(res);
},
/** @id MochiKit.Async.Deferred.prototype.errback */
errback: function (res) {
this._check();
var self = MochiKit.Async;
if (res instanceof self.Deferred) {
throw new Error("Deferred instances can only be chained if they are the result of a callback");
}
if (!(res instanceof Error)) {
res = new self.GenericError(res);
}
this._resback(res);
},
/** @id MochiKit.Async.Deferred.prototype.addBoth */
addBoth: function (fn) {
if (arguments.length > 1) {
fn = MochiKit.Base.partial.apply(null, arguments);
}
return this.addCallbacks(fn, fn);
},
/** @id MochiKit.Async.Deferred.prototype.addCallback */
addCallback: function (fn) {
if (arguments.length > 1) {
fn = MochiKit.Base.partial.apply(null, arguments);
}
return this.addCallbacks(fn, null);
},
/** @id MochiKit.Async.Deferred.prototype.addErrback */
addErrback: function (fn) {
if (arguments.length > 1) {
fn = MochiKit.Base.partial.apply(null, arguments);
}
return this.addCallbacks(null, fn);
},
/** @id MochiKit.Async.Deferred.prototype.addCallbacks */
addCallbacks: function (cb, eb) {
if (this.chained) {
throw new Error("Chained Deferreds can not be re-used");
}
this.chain.push([cb, eb]);
if (this.fired >= 0) {
this._fire();
}
return this;
},
_fire: function () {
/***
Used internally to exhaust the callback sequence when a result
is available.
***/
var chain = this.chain;
var fired = this.fired;
var res = this.results[fired];
var self = this;
var cb = null;
while (chain.length > 0 && this.paused === 0) {
// Array
var pair = chain.shift();
var f = pair[fired];
if (f === null) {
continue;
}
try {
res = f(res);
fired = ((res instanceof Error) ? 1 : 0);
if (res instanceof MochiKit.Async.Deferred) {
cb = function (res) {
self._resback(res);
self.paused--;
if ((self.paused === 0) && (self.fired >= 0)) {
self._fire();
}
};
this.paused++;
}
} catch (err) {
fired = 1;
if (!(err instanceof Error)) {
err = new MochiKit.Async.GenericError(err);
}
res = err;
}
}
this.fired = fired;
this.results[fired] = res;
if (cb && this.paused) {
// this is for "tail recursion" in case the dependent deferred
// is already fired
res.addBoth(cb);
res.chained = true;
}
}
};
MochiKit.Base.update(MochiKit.Async, {
/** @id MochiKit.Async.evalJSONRequest */
evalJSONRequest: function (req) {
return MochiKit.Base.evalJSON(req.responseText);
},
/** @id MochiKit.Async.succeed */
succeed: function (/* optional */result) {
var d = new MochiKit.Async.Deferred();
d.callback.apply(d, arguments);
return d;
},
/** @id MochiKit.Async.fail */
fail: function (/* optional */result) {
var d = new MochiKit.Async.Deferred();
d.errback.apply(d, arguments);
return d;
},
/** @id MochiKit.Async.getXMLHttpRequest */
getXMLHttpRequest: function () {
var self = arguments.callee;
if (!self.XMLHttpRequest) {
var tryThese = [
function () { return new XMLHttpRequest(); },
function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
function () {
throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
}
];
for (var i = 0; i < tryThese.length; i++) {
var func = tryThese[i];
try {
self.XMLHttpRequest = func;
return func();
} catch (e) {
// pass
}
}
}
return self.XMLHttpRequest();
},
_xhr_onreadystatechange: function (d) {
// MochiKit.Logging.logDebug('this.readyState', this.readyState);
var m = MochiKit.Base;
if (this.readyState == 4) {
// IE SUCKS
try {
this.onreadystatechange = null;
} catch (e) {
try {
this.onreadystatechange = m.noop;
} catch (e) {
}
}
var status = null;
try {
status = this.status;
if (!status && m.isNotEmpty(this.responseText)) {
// 0 or undefined seems to mean cached or local
status = 304;
}
} catch (e) {
// pass
// MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
}
// 200 is OK, 201 is CREATED, 204 is NO CONTENT
// 304 is NOT MODIFIED, 1223 is apparently a bug in IE
if (status == 200 || status == 201 || status == 204 ||
status == 304 || status == 1223) {
d.callback(this);
} else {
var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
if (err.number) {
// XXX: This seems to happen on page change
d.errback(err);
} else {
// XXX: this seems to happen when the server is unreachable
d.errback(err);
}
}
}
},
_xhr_canceller: function (req) {
// IE SUCKS
try {
req.onreadystatechange = null;
} catch (e) {
try {
req.onreadystatechange = MochiKit.Base.noop;
} catch (e) {
}
}
req.abort();
},
/** @id MochiKit.Async.sendXMLHttpRequest */
sendXMLHttpRequest: function (req, /* optional */ sendContent) {
if (typeof(sendContent) == "undefined" || sendContent === null) {
sendContent = "";
}
var m = MochiKit.Base;
var self = MochiKit.Async;
var d = new self.Deferred(m.partial(self._xhr_canceller, req));
try {
req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
req, d);
req.send(sendContent);
} catch (e) {
try {
req.onreadystatechange = null;
} catch (ignore) {
// pass
}
d.errback(e);
}
return d;
},
/** @id MochiKit.Async.doXHR */
doXHR: function (url, opts) {
/*
Work around a Firefox bug by dealing with XHR during
the next event loop iteration. Maybe it's this one:
https://bugzilla.mozilla.org/show_bug.cgi?id=249843
*/
var self = MochiKit.Async;
return self.callLater(0, self._doXHR, url, opts);
},
_doXHR: function (url, opts) {
var m = MochiKit.Base;
opts = m.update({
method: 'GET',
sendContent: ''
/*
queryString: undefined,
username: undefined,
password: undefined,
headers: undefined,
mimeType: undefined
*/
}, opts);
var self = MochiKit.Async;
var req = self.getXMLHttpRequest();
if (opts.queryString) {
var qs = m.queryString(opts.queryString);
if (qs) {
url += "?" + qs;
}
}
// Safari will send undefined:undefined, so we have to check.
// We can't use apply, since the function is native.
if ('username' in opts) {
req.open(opts.method, url, true, opts.username, opts.password);
} else {
req.open(opts.method, url, true);
}
if (req.overrideMimeType && opts.mimeType) {
req.overrideMimeType(opts.mimeType);
}
req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
if (opts.headers) {
var headers = opts.headers;
if (!m.isArrayLike(headers)) {
headers = m.items(headers);
}
for (var i = 0; i < headers.length; i++) {
var header = headers[i];
var name = header[0];
var value = header[1];
req.setRequestHeader(name, value);
}
}
return self.sendXMLHttpRequest(req, opts.sendContent);
},
_buildURL: function (url/*, ...*/) {
if (arguments.length > 1) {
var m = MochiKit.Base;
var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
if (qs) {
return url + "?" + qs;
}
}
return url;
},
/** @id MochiKit.Async.doSimpleXMLHttpRequest */
doSimpleXMLHttpRequest: function (url/*, ...*/) {
var self = MochiKit.Async;
url = self._buildURL.apply(self, arguments);
return self.doXHR(url);
},
/** @id MochiKit.Async.loadJSONDoc */
loadJSONDoc: function (url/*, ...*/) {
var self = MochiKit.Async;
url = self._buildURL.apply(self, arguments);
var d = self.doXHR(url, {
'mimeType': 'text/plain',
'headers': [['Accept', 'application/json']]
});
d = d.addCallback(self.evalJSONRequest);
return d;
},
/** @id MochiKit.Async.wait */
wait: function (seconds, /* optional */value) {
var d = new MochiKit.Async.Deferred();
var m = MochiKit.Base;
if (typeof(value) != 'undefined') {
d.addCallback(function () { return value; });
}
var timeout = setTimeout(
m.bind("callback", d),
Math.floor(seconds * 1000));
d.canceller = function () {
try {
clearTimeout(timeout);
} catch (e) {
// pass
}
};
return d;
},
/** @id MochiKit.Async.callLater */
callLater: function (seconds, func) {
var m = MochiKit.Base;
var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
return MochiKit.Async.wait(seconds).addCallback(
function (res) { return pfunc(); }
);
}
});
/** @id MochiKit.Async.DeferredLock */
MochiKit.Async.DeferredLock = function () {
this.waiting = [];
this.locked = false;
this.id = this._nextId();
};
MochiKit.Async.DeferredLock.prototype = {
__class__: MochiKit.Async.DeferredLock,
/** @id MochiKit.Async.DeferredLock.prototype.acquire */
acquire: function () {
var d = new MochiKit.Async.Deferred();
if (this.locked) {
this.waiting.push(d);
} else {
this.locked = true;
d.callback(this);
}
return d;
},
/** @id MochiKit.Async.DeferredLock.prototype.release */
release: function () {
if (!this.locked) {
throw TypeError("Tried to release an unlocked DeferredLock");
}
this.locked = false;
if (this.waiting.length > 0) {
this.locked = true;
this.waiting.shift().callback(this);
}
},
_nextId: MochiKit.Base.counter(),
repr: function () {
var state;
if (this.locked) {
state = 'locked, ' + this.waiting.length + ' waiting';
} else {
state = 'unlocked';
}
return 'DeferredLock(' + this.id + ', ' + state + ')';
},
toString: MochiKit.Base.forwardCall("repr")
};
/** @id MochiKit.Async.DeferredList */
MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
// call parent constructor
MochiKit.Async.Deferred.apply(this, [canceller]);
this.list = list;
var resultList = [];
this.resultList = resultList;
this.finishedCount = 0;
this.fireOnOneCallback = fireOnOneCallback;
this.fireOnOneErrback = fireOnOneErrback;
this.consumeErrors = consumeErrors;
var cb = MochiKit.Base.bind(this._cbDeferred, this);
for (var i = 0; i < list.length; i++) {
var d = list[i];
resultList.push(undefined);
d.addCallback(cb, i, true);
d.addErrback(cb, i, false);
}
if (list.length === 0 && !fireOnOneCallback) {
this.callback(this.resultList);
}
};
MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();
MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
this.resultList[index] = [succeeded, result];
this.finishedCount += 1;
if (this.fired == -1) {
if (succeeded && this.fireOnOneCallback) {
this.callback([index, result]);
} else if (!succeeded && this.fireOnOneErrback) {
this.errback(result);
} else if (this.finishedCount == this.list.length) {
this.callback(this.resultList);
}
}
if (!succeeded && this.consumeErrors) {
result = null;
}
return result;
};
/** @id MochiKit.Async.gatherResults */
MochiKit.Async.gatherResults = function (deferredList) {
var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
d.addCallback(function (results) {
var ret = [];
for (var i = 0; i < results.length; i++) {
ret.push(results[i][1]);
}
return ret;
});
return d;
};
/** @id MochiKit.Async.maybeDeferred */
MochiKit.Async.maybeDeferred = function (func) {
var self = MochiKit.Async;
var result;
try {
var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
if (r instanceof self.Deferred) {
result = r;
} else if (r instanceof Error) {
result = self.fail(r);
} else {
result = self.succeed(r);
}
} catch (e) {
result = self.fail(e);
}
return result;
};
MochiKit.Async.EXPORT = [
"AlreadyCalledError",
"CancelledError",
"BrowserComplianceError",
"GenericError",
"XMLHttpRequestError",
"Deferred",
"succeed",
"fail",
"getXMLHttpRequest",
"doSimpleXMLHttpRequest",
"loadJSONDoc",
"wait",
"callLater",
"sendXMLHttpRequest",
"DeferredLock",
"DeferredList",
"gatherResults",
"maybeDeferred",
"doXHR"
];
MochiKit.Async.EXPORT_OK = [
"evalJSONRequest"
];
MochiKit.Async.__new__ = function () {
var m = MochiKit.Base;
var ne = m.partial(m._newNamedError, this);
ne("AlreadyCalledError",
/** @id MochiKit.Async.AlreadyCalledError */
function (deferred) {
/***
Raised by the Deferred if callback or errback happens
after it was already fired.
***/
this.deferred = deferred;
}
);
ne("CancelledError",
/** @id MochiKit.Async.CancelledError */
function (deferred) {
/***
Raised by the Deferred cancellation mechanism.
***/
this.deferred = deferred;
}
);
ne("BrowserComplianceError",
/** @id MochiKit.Async.BrowserComplianceError */
function (msg) {
/***
Raised when the JavaScript runtime is not capable of performing
the given function. Technically, this should really never be
raised because a non-conforming JavaScript runtime probably
isn't going to support exceptions in the first place.
***/
this.message = msg;
}
);
ne("GenericError",
/** @id MochiKit.Async.GenericError */
function (msg) {
this.message = msg;
}
);
ne("XMLHttpRequestError",
/** @id MochiKit.Async.XMLHttpRequestError */
function (req, msg) {
/***
Raised when an XMLHttpRequest does not complete for any reason.
***/
this.req = req;
this.message = msg;
try {
// Strange but true that this can raise in some cases.
this.number = req.status;
} catch (e) {
// pass
}
}
);
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
};
MochiKit.Async.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Async);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,863 @@
/***
MochiKit.Color 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito and others. All rights Reserved.
***/
MochiKit.Base._deps('Color', ['Base', 'DOM', 'Style']);
MochiKit.Color.NAME = "MochiKit.Color";
MochiKit.Color.VERSION = "1.4.2";
MochiKit.Color.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Color.toString = function () {
return this.__repr__();
};
/** @id MochiKit.Color.Color */
MochiKit.Color.Color = function (red, green, blue, alpha) {
if (typeof(alpha) == 'undefined' || alpha === null) {
alpha = 1.0;
}
this.rgb = {
r: red,
g: green,
b: blue,
a: alpha
};
};
// Prototype methods
MochiKit.Color.Color.prototype = {
__class__: MochiKit.Color.Color,
/** @id MochiKit.Color.Color.prototype.colorWithAlpha */
colorWithAlpha: function (alpha) {
var rgb = this.rgb;
var m = MochiKit.Color;
return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
},
/** @id MochiKit.Color.Color.prototype.colorWithHue */
colorWithHue: function (hue) {
// get an HSL model, and set the new hue...
var hsl = this.asHSL();
hsl.h = hue;
var m = MochiKit.Color;
// convert back to RGB...
return m.Color.fromHSL(hsl);
},
/** @id MochiKit.Color.Color.prototype.colorWithSaturation */
colorWithSaturation: function (saturation) {
// get an HSL model, and set the new hue...
var hsl = this.asHSL();
hsl.s = saturation;
var m = MochiKit.Color;
// convert back to RGB...
return m.Color.fromHSL(hsl);
},
/** @id MochiKit.Color.Color.prototype.colorWithLightness */
colorWithLightness: function (lightness) {
// get an HSL model, and set the new hue...
var hsl = this.asHSL();
hsl.l = lightness;
var m = MochiKit.Color;
// convert back to RGB...
return m.Color.fromHSL(hsl);
},
/** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
darkerColorWithLevel: function (level) {
var hsl = this.asHSL();
hsl.l = Math.max(hsl.l - level, 0);
var m = MochiKit.Color;
return m.Color.fromHSL(hsl);
},
/** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
lighterColorWithLevel: function (level) {
var hsl = this.asHSL();
hsl.l = Math.min(hsl.l + level, 1);
var m = MochiKit.Color;
return m.Color.fromHSL(hsl);
},
/** @id MochiKit.Color.Color.prototype.blendedColor */
blendedColor: function (other, /* optional */ fraction) {
if (typeof(fraction) == 'undefined' || fraction === null) {
fraction = 0.5;
}
var sf = 1.0 - fraction;
var s = this.rgb;
var d = other.rgb;
var df = fraction;
return MochiKit.Color.Color.fromRGB(
(s.r * sf) + (d.r * df),
(s.g * sf) + (d.g * df),
(s.b * sf) + (d.b * df),
(s.a * sf) + (d.a * df)
);
},
/** @id MochiKit.Color.Color.prototype.compareRGB */
compareRGB: function (other) {
var a = this.asRGB();
var b = other.asRGB();
return MochiKit.Base.compare(
[a.r, a.g, a.b, a.a],
[b.r, b.g, b.b, b.a]
);
},
/** @id MochiKit.Color.Color.prototype.isLight */
isLight: function () {
return this.asHSL().b > 0.5;
},
/** @id MochiKit.Color.Color.prototype.isDark */
isDark: function () {
return (!this.isLight());
},
/** @id MochiKit.Color.Color.prototype.toHSLString */
toHSLString: function () {
var c = this.asHSL();
var ccc = MochiKit.Color.clampColorComponent;
var rval = this._hslString;
if (!rval) {
var mid = (
ccc(c.h, 360).toFixed(0)
+ "," + ccc(c.s, 100).toPrecision(4) + "%"
+ "," + ccc(c.l, 100).toPrecision(4) + "%"
);
var a = c.a;
if (a >= 1) {
a = 1;
rval = "hsl(" + mid + ")";
} else {
if (a <= 0) {
a = 0;
}
rval = "hsla(" + mid + "," + a + ")";
}
this._hslString = rval;
}
return rval;
},
/** @id MochiKit.Color.Color.prototype.toRGBString */
toRGBString: function () {
var c = this.rgb;
var ccc = MochiKit.Color.clampColorComponent;
var rval = this._rgbString;
if (!rval) {
var mid = (
ccc(c.r, 255).toFixed(0)
+ "," + ccc(c.g, 255).toFixed(0)
+ "," + ccc(c.b, 255).toFixed(0)
);
if (c.a != 1) {
rval = "rgba(" + mid + "," + c.a + ")";
} else {
rval = "rgb(" + mid + ")";
}
this._rgbString = rval;
}
return rval;
},
/** @id MochiKit.Color.Color.prototype.asRGB */
asRGB: function () {
return MochiKit.Base.clone(this.rgb);
},
/** @id MochiKit.Color.Color.prototype.toHexString */
toHexString: function () {
var m = MochiKit.Color;
var c = this.rgb;
var ccc = MochiKit.Color.clampColorComponent;
var rval = this._hexString;
if (!rval) {
rval = ("#" +
m.toColorPart(ccc(c.r, 255)) +
m.toColorPart(ccc(c.g, 255)) +
m.toColorPart(ccc(c.b, 255))
);
this._hexString = rval;
}
return rval;
},
/** @id MochiKit.Color.Color.prototype.asHSV */
asHSV: function () {
var hsv = this.hsv;
var c = this.rgb;
if (typeof(hsv) == 'undefined' || hsv === null) {
hsv = MochiKit.Color.rgbToHSV(this.rgb);
this.hsv = hsv;
}
return MochiKit.Base.clone(hsv);
},
/** @id MochiKit.Color.Color.prototype.asHSL */
asHSL: function () {
var hsl = this.hsl;
var c = this.rgb;
if (typeof(hsl) == 'undefined' || hsl === null) {
hsl = MochiKit.Color.rgbToHSL(this.rgb);
this.hsl = hsl;
}
return MochiKit.Base.clone(hsl);
},
/** @id MochiKit.Color.Color.prototype.toString */
toString: function () {
return this.toRGBString();
},
/** @id MochiKit.Color.Color.prototype.repr */
repr: function () {
var c = this.rgb;
var col = [c.r, c.g, c.b, c.a];
return this.__class__.NAME + "(" + col.join(", ") + ")";
}
};
// Constructor methods
MochiKit.Base.update(MochiKit.Color.Color, {
/** @id MochiKit.Color.Color.fromRGB */
fromRGB: function (red, green, blue, alpha) {
// designated initializer
var Color = MochiKit.Color.Color;
if (arguments.length == 1) {
var rgb = red;
red = rgb.r;
green = rgb.g;
blue = rgb.b;
if (typeof(rgb.a) == 'undefined') {
alpha = undefined;
} else {
alpha = rgb.a;
}
}
return new Color(red, green, blue, alpha);
},
/** @id MochiKit.Color.Color.fromHSL */
fromHSL: function (hue, saturation, lightness, alpha) {
var m = MochiKit.Color;
return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
},
/** @id MochiKit.Color.Color.fromHSV */
fromHSV: function (hue, saturation, value, alpha) {
var m = MochiKit.Color;
return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
},
/** @id MochiKit.Color.Color.fromName */
fromName: function (name) {
var Color = MochiKit.Color.Color;
// Opera 9 seems to "quote" named colors(?!)
if (name.charAt(0) == '"') {
name = name.substr(1, name.length - 2);
}
var htmlColor = Color._namedColors[name.toLowerCase()];
if (typeof(htmlColor) == 'string') {
return Color.fromHexString(htmlColor);
} else if (name == "transparent") {
return Color.transparentColor();
}
return null;
},
/** @id MochiKit.Color.Color.fromString */
fromString: function (colorString) {
var self = MochiKit.Color.Color;
var three = colorString.substr(0, 3);
if (three == "rgb") {
return self.fromRGBString(colorString);
} else if (three == "hsl") {
return self.fromHSLString(colorString);
} else if (colorString.charAt(0) == "#") {
return self.fromHexString(colorString);
}
return self.fromName(colorString);
},
/** @id MochiKit.Color.Color.fromHexString */
fromHexString: function (hexCode) {
if (hexCode.charAt(0) == '#') {
hexCode = hexCode.substring(1);
}
var components = [];
var i, hex;
if (hexCode.length == 3) {
for (i = 0; i < 3; i++) {
hex = hexCode.substr(i, 1);
components.push(parseInt(hex + hex, 16) / 255.0);
}
} else {
for (i = 0; i < 6; i += 2) {
hex = hexCode.substr(i, 2);
components.push(parseInt(hex, 16) / 255.0);
}
}
var Color = MochiKit.Color.Color;
return Color.fromRGB.apply(Color, components);
},
_fromColorString: function (pre, method, scales, colorCode) {
// parses either HSL or RGB
if (colorCode.indexOf(pre) === 0) {
colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
}
var colorChunks = colorCode.split(/\s*,\s*/);
var colorFloats = [];
for (var i = 0; i < colorChunks.length; i++) {
var c = colorChunks[i];
var val;
var three = c.substring(c.length - 3);
if (c.charAt(c.length - 1) == '%') {
val = 0.01 * parseFloat(c.substring(0, c.length - 1));
} else if (three == "deg") {
val = parseFloat(c) / 360.0;
} else if (three == "rad") {
val = parseFloat(c) / (Math.PI * 2);
} else {
val = scales[i] * parseFloat(c);
}
colorFloats.push(val);
}
return this[method].apply(this, colorFloats);
},
/** @id MochiKit.Color.Color.fromComputedStyle */
fromComputedStyle: function (elem, style) {
var d = MochiKit.DOM;
var cls = MochiKit.Color.Color;
for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
if (!actualColor) {
continue;
}
var color = cls.fromString(actualColor);
if (!color) {
break;
}
if (color.asRGB().a > 0) {
return color;
}
}
return null;
},
/** @id MochiKit.Color.Color.fromBackground */
fromBackground: function (elem) {
var cls = MochiKit.Color.Color;
return cls.fromComputedStyle(
elem, "backgroundColor", "background-color") || cls.whiteColor();
},
/** @id MochiKit.Color.Color.fromText */
fromText: function (elem) {
var cls = MochiKit.Color.Color;
return cls.fromComputedStyle(
elem, "color", "color") || cls.blackColor();
},
/** @id MochiKit.Color.Color.namedColors */
namedColors: function () {
return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
}
});
// Module level functions
MochiKit.Base.update(MochiKit.Color, {
/** @id MochiKit.Color.clampColorComponent */
clampColorComponent: function (v, scale) {
v *= scale;
if (v < 0) {
return 0;
} else if (v > scale) {
return scale;
} else {
return v;
}
},
_hslValue: function (n1, n2, hue) {
if (hue > 6.0) {
hue -= 6.0;
} else if (hue < 0.0) {
hue += 6.0;
}
var val;
if (hue < 1.0) {
val = n1 + (n2 - n1) * hue;
} else if (hue < 3.0) {
val = n2;
} else if (hue < 4.0) {
val = n1 + (n2 - n1) * (4.0 - hue);
} else {
val = n1;
}
return val;
},
/** @id MochiKit.Color.hsvToRGB */
hsvToRGB: function (hue, saturation, value, alpha) {
if (arguments.length == 1) {
var hsv = hue;
hue = hsv.h;
saturation = hsv.s;
value = hsv.v;
alpha = hsv.a;
}
var red;
var green;
var blue;
if (saturation === 0) {
red = value;
green = value;
blue = value;
} else {
var i = Math.floor(hue * 6);
var f = (hue * 6) - i;
var p = value * (1 - saturation);
var q = value * (1 - (saturation * f));
var t = value * (1 - (saturation * (1 - f)));
switch (i) {
case 1: red = q; green = value; blue = p; break;
case 2: red = p; green = value; blue = t; break;
case 3: red = p; green = q; blue = value; break;
case 4: red = t; green = p; blue = value; break;
case 5: red = value; green = p; blue = q; break;
case 6: // fall through
case 0: red = value; green = t; blue = p; break;
}
}
return {
r: red,
g: green,
b: blue,
a: alpha
};
},
/** @id MochiKit.Color.hslToRGB */
hslToRGB: function (hue, saturation, lightness, alpha) {
if (arguments.length == 1) {
var hsl = hue;
hue = hsl.h;
saturation = hsl.s;
lightness = hsl.l;
alpha = hsl.a;
}
var red;
var green;
var blue;
if (saturation === 0) {
red = lightness;
green = lightness;
blue = lightness;
} else {
var m2;
if (lightness <= 0.5) {
m2 = lightness * (1.0 + saturation);
} else {
m2 = lightness + saturation - (lightness * saturation);
}
var m1 = (2.0 * lightness) - m2;
var f = MochiKit.Color._hslValue;
var h6 = hue * 6.0;
red = f(m1, m2, h6 + 2);
green = f(m1, m2, h6);
blue = f(m1, m2, h6 - 2);
}
return {
r: red,
g: green,
b: blue,
a: alpha
};
},
/** @id MochiKit.Color.rgbToHSV */
rgbToHSV: function (red, green, blue, alpha) {
if (arguments.length == 1) {
var rgb = red;
red = rgb.r;
green = rgb.g;
blue = rgb.b;
alpha = rgb.a;
}
var max = Math.max(Math.max(red, green), blue);
var min = Math.min(Math.min(red, green), blue);
var hue;
var saturation;
var value = max;
if (min == max) {
hue = 0;
saturation = 0;
} else {
var delta = (max - min);
saturation = delta / max;
if (red == max) {
hue = (green - blue) / delta;
} else if (green == max) {
hue = 2 + ((blue - red) / delta);
} else {
hue = 4 + ((red - green) / delta);
}
hue /= 6;
if (hue < 0) {
hue += 1;
}
if (hue > 1) {
hue -= 1;
}
}
return {
h: hue,
s: saturation,
v: value,
a: alpha
};
},
/** @id MochiKit.Color.rgbToHSL */
rgbToHSL: function (red, green, blue, alpha) {
if (arguments.length == 1) {
var rgb = red;
red = rgb.r;
green = rgb.g;
blue = rgb.b;
alpha = rgb.a;
}
var max = Math.max(red, Math.max(green, blue));
var min = Math.min(red, Math.min(green, blue));
var hue;
var saturation;
var lightness = (max + min) / 2.0;
var delta = max - min;
if (delta === 0) {
hue = 0;
saturation = 0;
} else {
if (lightness <= 0.5) {
saturation = delta / (max + min);
} else {
saturation = delta / (2 - max - min);
}
if (red == max) {
hue = (green - blue) / delta;
} else if (green == max) {
hue = 2 + ((blue - red) / delta);
} else {
hue = 4 + ((red - green) / delta);
}
hue /= 6;
if (hue < 0) {
hue += 1;
}
if (hue > 1) {
hue -= 1;
}
}
return {
h: hue,
s: saturation,
l: lightness,
a: alpha
};
},
/** @id MochiKit.Color.toColorPart */
toColorPart: function (num) {
num = Math.round(num);
var digits = num.toString(16);
if (num < 16) {
return '0' + digits;
}
return digits;
},
__new__: function () {
var m = MochiKit.Base;
/** @id MochiKit.Color.fromRGBString */
this.Color.fromRGBString = m.bind(
this.Color._fromColorString, this.Color, "rgb", "fromRGB",
[1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
);
/** @id MochiKit.Color.fromHSLString */
this.Color.fromHSLString = m.bind(
this.Color._fromColorString, this.Color, "hsl", "fromHSL",
[1.0/360.0, 0.01, 0.01, 1]
);
var third = 1.0 / 3.0;
/** @id MochiKit.Color.colors */
var colors = {
// NSColor colors plus transparent
/** @id MochiKit.Color.blackColor */
black: [0, 0, 0],
/** @id MochiKit.Color.blueColor */
blue: [0, 0, 1],
/** @id MochiKit.Color.brownColor */
brown: [0.6, 0.4, 0.2],
/** @id MochiKit.Color.cyanColor */
cyan: [0, 1, 1],
/** @id MochiKit.Color.darkGrayColor */
darkGray: [third, third, third],
/** @id MochiKit.Color.grayColor */
gray: [0.5, 0.5, 0.5],
/** @id MochiKit.Color.greenColor */
green: [0, 1, 0],
/** @id MochiKit.Color.lightGrayColor */
lightGray: [2 * third, 2 * third, 2 * third],
/** @id MochiKit.Color.magentaColor */
magenta: [1, 0, 1],
/** @id MochiKit.Color.orangeColor */
orange: [1, 0.5, 0],
/** @id MochiKit.Color.purpleColor */
purple: [0.5, 0, 0.5],
/** @id MochiKit.Color.redColor */
red: [1, 0, 0],
/** @id MochiKit.Color.transparentColor */
transparent: [0, 0, 0, 0],
/** @id MochiKit.Color.whiteColor */
white: [1, 1, 1],
/** @id MochiKit.Color.yellowColor */
yellow: [1, 1, 0]
};
var makeColor = function (name, r, g, b, a) {
var rval = this.fromRGB(r, g, b, a);
this[name] = function () { return rval; };
return rval;
};
for (var k in colors) {
var name = k + "Color";
var bindArgs = m.concat(
[makeColor, this.Color, name],
colors[k]
);
this.Color[name] = m.bind.apply(null, bindArgs);
}
var isColor = function () {
for (var i = 0; i < arguments.length; i++) {
if (!(arguments[i] instanceof MochiKit.Color.Color)) {
return false;
}
}
return true;
};
var compareColor = function (a, b) {
return a.compareRGB(b);
};
m.nameFunctions(this);
m.registerComparator(this.Color.NAME, isColor, compareColor);
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": m.concat(this.EXPORT, this.EXPORT_OK)
};
}
});
MochiKit.Color.EXPORT = [
"Color"
];
MochiKit.Color.EXPORT_OK = [
"clampColorComponent",
"rgbToHSL",
"hslToRGB",
"rgbToHSV",
"hsvToRGB",
"toColorPart"
];
MochiKit.Color.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Color);
// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
MochiKit.Color.Color._namedColors = {
aliceblue: "#f0f8ff",
antiquewhite: "#faebd7",
aqua: "#00ffff",
aquamarine: "#7fffd4",
azure: "#f0ffff",
beige: "#f5f5dc",
bisque: "#ffe4c4",
black: "#000000",
blanchedalmond: "#ffebcd",
blue: "#0000ff",
blueviolet: "#8a2be2",
brown: "#a52a2a",
burlywood: "#deb887",
cadetblue: "#5f9ea0",
chartreuse: "#7fff00",
chocolate: "#d2691e",
coral: "#ff7f50",
cornflowerblue: "#6495ed",
cornsilk: "#fff8dc",
crimson: "#dc143c",
cyan: "#00ffff",
darkblue: "#00008b",
darkcyan: "#008b8b",
darkgoldenrod: "#b8860b",
darkgray: "#a9a9a9",
darkgreen: "#006400",
darkgrey: "#a9a9a9",
darkkhaki: "#bdb76b",
darkmagenta: "#8b008b",
darkolivegreen: "#556b2f",
darkorange: "#ff8c00",
darkorchid: "#9932cc",
darkred: "#8b0000",
darksalmon: "#e9967a",
darkseagreen: "#8fbc8f",
darkslateblue: "#483d8b",
darkslategray: "#2f4f4f",
darkslategrey: "#2f4f4f",
darkturquoise: "#00ced1",
darkviolet: "#9400d3",
deeppink: "#ff1493",
deepskyblue: "#00bfff",
dimgray: "#696969",
dimgrey: "#696969",
dodgerblue: "#1e90ff",
firebrick: "#b22222",
floralwhite: "#fffaf0",
forestgreen: "#228b22",
fuchsia: "#ff00ff",
gainsboro: "#dcdcdc",
ghostwhite: "#f8f8ff",
gold: "#ffd700",
goldenrod: "#daa520",
gray: "#808080",
green: "#008000",
greenyellow: "#adff2f",
grey: "#808080",
honeydew: "#f0fff0",
hotpink: "#ff69b4",
indianred: "#cd5c5c",
indigo: "#4b0082",
ivory: "#fffff0",
khaki: "#f0e68c",
lavender: "#e6e6fa",
lavenderblush: "#fff0f5",
lawngreen: "#7cfc00",
lemonchiffon: "#fffacd",
lightblue: "#add8e6",
lightcoral: "#f08080",
lightcyan: "#e0ffff",
lightgoldenrodyellow: "#fafad2",
lightgray: "#d3d3d3",
lightgreen: "#90ee90",
lightgrey: "#d3d3d3",
lightpink: "#ffb6c1",
lightsalmon: "#ffa07a",
lightseagreen: "#20b2aa",
lightskyblue: "#87cefa",
lightslategray: "#778899",
lightslategrey: "#778899",
lightsteelblue: "#b0c4de",
lightyellow: "#ffffe0",
lime: "#00ff00",
limegreen: "#32cd32",
linen: "#faf0e6",
magenta: "#ff00ff",
maroon: "#800000",
mediumaquamarine: "#66cdaa",
mediumblue: "#0000cd",
mediumorchid: "#ba55d3",
mediumpurple: "#9370db",
mediumseagreen: "#3cb371",
mediumslateblue: "#7b68ee",
mediumspringgreen: "#00fa9a",
mediumturquoise: "#48d1cc",
mediumvioletred: "#c71585",
midnightblue: "#191970",
mintcream: "#f5fffa",
mistyrose: "#ffe4e1",
moccasin: "#ffe4b5",
navajowhite: "#ffdead",
navy: "#000080",
oldlace: "#fdf5e6",
olive: "#808000",
olivedrab: "#6b8e23",
orange: "#ffa500",
orangered: "#ff4500",
orchid: "#da70d6",
palegoldenrod: "#eee8aa",
palegreen: "#98fb98",
paleturquoise: "#afeeee",
palevioletred: "#db7093",
papayawhip: "#ffefd5",
peachpuff: "#ffdab9",
peru: "#cd853f",
pink: "#ffc0cb",
plum: "#dda0dd",
powderblue: "#b0e0e6",
purple: "#800080",
red: "#ff0000",
rosybrown: "#bc8f8f",
royalblue: "#4169e1",
saddlebrown: "#8b4513",
salmon: "#fa8072",
sandybrown: "#f4a460",
seagreen: "#2e8b57",
seashell: "#fff5ee",
sienna: "#a0522d",
silver: "#c0c0c0",
skyblue: "#87ceeb",
slateblue: "#6a5acd",
slategray: "#708090",
slategrey: "#708090",
snow: "#fffafa",
springgreen: "#00ff7f",
steelblue: "#4682b4",
tan: "#d2b48c",
teal: "#008080",
thistle: "#d8bfd8",
tomato: "#ff6347",
turquoise: "#40e0d0",
violet: "#ee82ee",
wheat: "#f5deb3",
white: "#ffffff",
whitesmoke: "#f5f5f5",
yellow: "#ffff00",
yellowgreen: "#9acd32"
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,222 @@
/***
MochiKit.DateTime 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('DateTime', ['Base']);
MochiKit.DateTime.NAME = "MochiKit.DateTime";
MochiKit.DateTime.VERSION = "1.4.2";
MochiKit.DateTime.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.DateTime.toString = function () {
return this.__repr__();
};
/** @id MochiKit.DateTime.isoDate */
MochiKit.DateTime.isoDate = function (str) {
str = str + "";
if (typeof(str) != "string" || str.length === 0) {
return null;
}
var iso = str.split('-');
if (iso.length === 0) {
return null;
}
var date = new Date(iso[0], iso[1] - 1, iso[2]);
date.setFullYear(iso[0]);
date.setMonth(iso[1] - 1);
date.setDate(iso[2]);
return date;
};
MochiKit.DateTime._isoRegexp = /(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
/** @id MochiKit.DateTime.isoTimestamp */
MochiKit.DateTime.isoTimestamp = function (str) {
str = str + "";
if (typeof(str) != "string" || str.length === 0) {
return null;
}
var res = str.match(MochiKit.DateTime._isoRegexp);
if (typeof(res) == "undefined" || res === null) {
return null;
}
var year, month, day, hour, min, sec, msec;
year = parseInt(res[1], 10);
if (typeof(res[2]) == "undefined" || res[2] === '') {
return new Date(year);
}
month = parseInt(res[2], 10) - 1;
day = parseInt(res[3], 10);
if (typeof(res[4]) == "undefined" || res[4] === '') {
return new Date(year, month, day);
}
hour = parseInt(res[4], 10);
min = parseInt(res[5], 10);
sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
if (typeof(res[7]) != "undefined" && res[7] !== '') {
msec = Math.round(1000.0 * parseFloat("0." + res[7]));
} else {
msec = 0;
}
if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
return new Date(year, month, day, hour, min, sec, msec);
}
var ofs;
if (typeof(res[9]) != "undefined" && res[9] !== '') {
ofs = parseInt(res[10], 10) * 3600000;
if (typeof(res[11]) != "undefined" && res[11] !== '') {
ofs += parseInt(res[11], 10) * 60000;
}
if (res[9] == "-") {
ofs = -ofs;
}
} else {
ofs = 0;
}
return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
};
/** @id MochiKit.DateTime.toISOTime */
MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
if (typeof(date) == "undefined" || date === null) {
return null;
}
var hh = date.getHours();
var mm = date.getMinutes();
var ss = date.getSeconds();
var lst = [
((realISO && (hh < 10)) ? "0" + hh : hh),
((mm < 10) ? "0" + mm : mm),
((ss < 10) ? "0" + ss : ss)
];
return lst.join(":");
};
/** @id MochiKit.DateTime.toISOTimeStamp */
MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
if (typeof(date) == "undefined" || date === null) {
return null;
}
var sep = realISO ? "T" : " ";
var foot = realISO ? "Z" : "";
if (realISO) {
date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
}
return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot;
};
/** @id MochiKit.DateTime.toISODate */
MochiKit.DateTime.toISODate = function (date) {
if (typeof(date) == "undefined" || date === null) {
return null;
}
var _padTwo = MochiKit.DateTime._padTwo;
var _padFour = MochiKit.DateTime._padFour;
return [
_padFour(date.getFullYear()),
_padTwo(date.getMonth() + 1),
_padTwo(date.getDate())
].join("-");
};
/** @id MochiKit.DateTime.americanDate */
MochiKit.DateTime.americanDate = function (d) {
d = d + "";
if (typeof(d) != "string" || d.length === 0) {
return null;
}
var a = d.split('/');
return new Date(a[2], a[0] - 1, a[1]);
};
MochiKit.DateTime._padTwo = function (n) {
return (n > 9) ? n : "0" + n;
};
MochiKit.DateTime._padFour = function(n) {
switch(n.toString().length) {
case 1: return "000" + n; break;
case 2: return "00" + n; break;
case 3: return "0" + n; break;
case 4:
default:
return n;
}
};
/** @id MochiKit.DateTime.toPaddedAmericanDate */
MochiKit.DateTime.toPaddedAmericanDate = function (d) {
if (typeof(d) == "undefined" || d === null) {
return null;
}
var _padTwo = MochiKit.DateTime._padTwo;
return [
_padTwo(d.getMonth() + 1),
_padTwo(d.getDate()),
d.getFullYear()
].join('/');
};
/** @id MochiKit.DateTime.toAmericanDate */
MochiKit.DateTime.toAmericanDate = function (d) {
if (typeof(d) == "undefined" || d === null) {
return null;
}
return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
};
MochiKit.DateTime.EXPORT = [
"isoDate",
"isoTimestamp",
"toISOTime",
"toISOTimestamp",
"toISODate",
"americanDate",
"toPaddedAmericanDate",
"toAmericanDate"
];
MochiKit.DateTime.EXPORT_OK = [];
MochiKit.DateTime.EXPORT_TAGS = {
":common": MochiKit.DateTime.EXPORT,
":all": MochiKit.DateTime.EXPORT
};
MochiKit.DateTime.__new__ = function () {
// MochiKit.Base.nameFunctions(this);
var base = this.NAME + ".";
for (var k in this) {
var o = this[k];
if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
try {
o.NAME = base + k;
} catch (e) {
// pass
}
}
}
};
MochiKit.DateTime.__new__();
if (typeof(MochiKit.Base) != "undefined") {
MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
} else {
(function (globals, module) {
if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
|| (MochiKit.__export__ === false)) {
var all = module.EXPORT_TAGS[":all"];
for (var i = 0; i < all.length; i++) {
globals[all[i]] = module[all[i]];
}
}
})(this, MochiKit.DateTime);
}

View file

@ -0,0 +1,793 @@
/***
MochiKit.DragAndDrop 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
Mochi-ized By Thomas Herve (_firstname_@nimail.org)
***/
MochiKit.Base._deps('DragAndDrop', ['Base', 'Iter', 'DOM', 'Signal', 'Visual', 'Position']);
MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop';
MochiKit.DragAndDrop.VERSION = '1.4.2';
MochiKit.DragAndDrop.__repr__ = function () {
return '[' + this.NAME + ' ' + this.VERSION + ']';
};
MochiKit.DragAndDrop.toString = function () {
return this.__repr__();
};
MochiKit.DragAndDrop.EXPORT = [
"Droppable",
"Draggable"
];
MochiKit.DragAndDrop.EXPORT_OK = [
"Droppables",
"Draggables"
];
MochiKit.DragAndDrop.Droppables = {
/***
Manage all droppables. Shouldn't be used, use the Droppable object instead.
***/
drops: [],
remove: function (element) {
this.drops = MochiKit.Base.filter(function (d) {
return d.element != MochiKit.DOM.getElement(element);
}, this.drops);
},
register: function (drop) {
this.drops.push(drop);
},
unregister: function (drop) {
this.drops = MochiKit.Base.filter(function (d) {
return d != drop;
}, this.drops);
},
prepare: function (element) {
MochiKit.Base.map(function (drop) {
if (drop.isAccepted(element)) {
if (drop.options.activeclass) {
MochiKit.DOM.addElementClass(drop.element,
drop.options.activeclass);
}
drop.options.onactive(drop.element, element);
}
}, this.drops);
},
findDeepestChild: function (drops) {
deepest = drops[0];
for (i = 1; i < drops.length; ++i) {
if (MochiKit.DOM.isChildNode(drops[i].element, deepest.element)) {
deepest = drops[i];
}
}
return deepest;
},
show: function (point, element) {
if (!this.drops.length) {
return;
}
var affected = [];
if (this.last_active) {
this.last_active.deactivate();
}
MochiKit.Iter.forEach(this.drops, function (drop) {
if (drop.isAffected(point, element)) {
affected.push(drop);
}
});
if (affected.length > 0) {
drop = this.findDeepestChild(affected);
MochiKit.Position.within(drop.element, point.page.x, point.page.y);
drop.options.onhover(element, drop.element,
MochiKit.Position.overlap(drop.options.overlap, drop.element));
drop.activate();
}
},
fire: function (event, element) {
if (!this.last_active) {
return;
}
MochiKit.Position.prepare();
if (this.last_active.isAffected(event.mouse(), element)) {
this.last_active.options.ondrop(element,
this.last_active.element, event);
}
},
reset: function (element) {
MochiKit.Base.map(function (drop) {
if (drop.options.activeclass) {
MochiKit.DOM.removeElementClass(drop.element,
drop.options.activeclass);
}
drop.options.ondesactive(drop.element, element);
}, this.drops);
if (this.last_active) {
this.last_active.deactivate();
}
}
};
/** @id MochiKit.DragAndDrop.Droppable */
MochiKit.DragAndDrop.Droppable = function (element, options) {
var cls = arguments.callee;
if (!(this instanceof cls)) {
return new cls(element, options);
}
this.__init__(element, options);
};
MochiKit.DragAndDrop.Droppable.prototype = {
/***
A droppable object. Simple use is to create giving an element:
new MochiKit.DragAndDrop.Droppable('myelement');
Generally you'll want to define the 'ondrop' function and maybe the
'accept' option to filter draggables.
***/
__class__: MochiKit.DragAndDrop.Droppable,
__init__: function (element, /* optional */options) {
var d = MochiKit.DOM;
var b = MochiKit.Base;
this.element = d.getElement(element);
this.options = b.update({
/** @id MochiKit.DragAndDrop.greedy */
greedy: true,
/** @id MochiKit.DragAndDrop.hoverclass */
hoverclass: null,
/** @id MochiKit.DragAndDrop.activeclass */
activeclass: null,
/** @id MochiKit.DragAndDrop.hoverfunc */
hoverfunc: b.noop,
/** @id MochiKit.DragAndDrop.accept */
accept: null,
/** @id MochiKit.DragAndDrop.onactive */
onactive: b.noop,
/** @id MochiKit.DragAndDrop.ondesactive */
ondesactive: b.noop,
/** @id MochiKit.DragAndDrop.onhover */
onhover: b.noop,
/** @id MochiKit.DragAndDrop.ondrop */
ondrop: b.noop,
/** @id MochiKit.DragAndDrop.containment */
containment: [],
tree: false
}, options);
// cache containers
this.options._containers = [];
b.map(MochiKit.Base.bind(function (c) {
this.options._containers.push(d.getElement(c));
}, this), this.options.containment);
MochiKit.Style.makePositioned(this.element); // fix IE
MochiKit.DragAndDrop.Droppables.register(this);
},
/** @id MochiKit.DragAndDrop.isContained */
isContained: function (element) {
if (this.options._containers.length) {
var containmentNode;
if (this.options.tree) {
containmentNode = element.treeNode;
} else {
containmentNode = element.parentNode;
}
return MochiKit.Iter.some(this.options._containers, function (c) {
return containmentNode == c;
});
} else {
return true;
}
},
/** @id MochiKit.DragAndDrop.isAccepted */
isAccepted: function (element) {
return ((!this.options.accept) || MochiKit.Iter.some(
this.options.accept, function (c) {
return MochiKit.DOM.hasElementClass(element, c);
}));
},
/** @id MochiKit.DragAndDrop.isAffected */
isAffected: function (point, element) {
return ((this.element != element) &&
this.isContained(element) &&
this.isAccepted(element) &&
MochiKit.Position.within(this.element, point.page.x,
point.page.y));
},
/** @id MochiKit.DragAndDrop.deactivate */
deactivate: function () {
/***
A droppable is deactivate when a draggable has been over it and left.
***/
if (this.options.hoverclass) {
MochiKit.DOM.removeElementClass(this.element,
this.options.hoverclass);
}
this.options.hoverfunc(this.element, false);
MochiKit.DragAndDrop.Droppables.last_active = null;
},
/** @id MochiKit.DragAndDrop.activate */
activate: function () {
/***
A droppable is active when a draggable is over it.
***/
if (this.options.hoverclass) {
MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
}
this.options.hoverfunc(this.element, true);
MochiKit.DragAndDrop.Droppables.last_active = this;
},
/** @id MochiKit.DragAndDrop.destroy */
destroy: function () {
/***
Delete this droppable.
***/
MochiKit.DragAndDrop.Droppables.unregister(this);
},
/** @id MochiKit.DragAndDrop.repr */
repr: function () {
return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
}
};
MochiKit.DragAndDrop.Draggables = {
/***
Manage draggables elements. Not intended to direct use.
***/
drags: [],
register: function (draggable) {
if (this.drags.length === 0) {
var conn = MochiKit.Signal.connect;
this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
this.eventMouseMove = conn(document, 'onmousemove', this,
this.updateDrag);
this.eventKeypress = conn(document, 'onkeypress', this,
this.keyPress);
}
this.drags.push(draggable);
},
unregister: function (draggable) {
this.drags = MochiKit.Base.filter(function (d) {
return d != draggable;
}, this.drags);
if (this.drags.length === 0) {
var disc = MochiKit.Signal.disconnect;
disc(this.eventMouseUp);
disc(this.eventMouseMove);
disc(this.eventKeypress);
}
},
activate: function (draggable) {
// allows keypress events if window is not currently focused
// fails for Safari
window.focus();
this.activeDraggable = draggable;
},
deactivate: function () {
this.activeDraggable = null;
},
updateDrag: function (event) {
if (!this.activeDraggable) {
return;
}
var pointer = event.mouse();
// Mozilla-based browsers fire successive mousemove events with
// the same coordinates, prevent needless redrawing (moz bug?)
if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) ==
MochiKit.Base.repr(pointer.page))) {
return;
}
this._lastPointer = pointer;
this.activeDraggable.updateDrag(event, pointer);
},
endDrag: function (event) {
if (!this.activeDraggable) {
return;
}
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},
keyPress: function (event) {
if (this.activeDraggable) {
this.activeDraggable.keyPress(event);
}
},
notify: function (eventName, draggable, event) {
MochiKit.Signal.signal(this, eventName, draggable, event);
}
};
/** @id MochiKit.DragAndDrop.Draggable */
MochiKit.DragAndDrop.Draggable = function (element, options) {
var cls = arguments.callee;
if (!(this instanceof cls)) {
return new cls(element, options);
}
this.__init__(element, options);
};
MochiKit.DragAndDrop.Draggable.prototype = {
/***
A draggable object. Simple instantiate :
new MochiKit.DragAndDrop.Draggable('myelement');
***/
__class__ : MochiKit.DragAndDrop.Draggable,
__init__: function (element, /* optional */options) {
var v = MochiKit.Visual;
var b = MochiKit.Base;
options = b.update({
/** @id MochiKit.DragAndDrop.handle */
handle: false,
/** @id MochiKit.DragAndDrop.starteffect */
starteffect: function (innerelement) {
this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0;
new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
},
/** @id MochiKit.DragAndDrop.reverteffect */
reverteffect: function (innerelement, top_offset, left_offset) {
var dur = Math.sqrt(Math.abs(top_offset^2) +
Math.abs(left_offset^2))*0.02;
return new v.Move(innerelement,
{x: -left_offset, y: -top_offset, duration: dur});
},
/** @id MochiKit.DragAndDrop.endeffect */
endeffect: function (innerelement) {
new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
},
/** @id MochiKit.DragAndDrop.onchange */
onchange: b.noop,
/** @id MochiKit.DragAndDrop.zindex */
zindex: 1000,
/** @id MochiKit.DragAndDrop.revert */
revert: false,
/** @id MochiKit.DragAndDrop.scroll */
scroll: false,
/** @id MochiKit.DragAndDrop.scrollSensitivity */
scrollSensitivity: 20,
/** @id MochiKit.DragAndDrop.scrollSpeed */
scrollSpeed: 15,
// false, or xy or [x, y] or function (x, y){return [x, y];}
/** @id MochiKit.DragAndDrop.snap */
snap: false
}, options);
var d = MochiKit.DOM;
this.element = d.getElement(element);
if (options.handle && (typeof(options.handle) == 'string')) {
this.handle = d.getFirstElementByTagAndClassName(null,
options.handle, this.element);
}
if (!this.handle) {
this.handle = d.getElement(options.handle);
}
if (!this.handle) {
this.handle = this.element;
}
if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
options.scroll = d.getElement(options.scroll);
this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
}
MochiKit.Style.makePositioned(this.element); // fix IE
this.delta = this.currentDelta();
this.options = options;
this.dragging = false;
this.eventMouseDown = MochiKit.Signal.connect(this.handle,
'onmousedown', this, this.initDrag);
MochiKit.DragAndDrop.Draggables.register(this);
},
/** @id MochiKit.DragAndDrop.destroy */
destroy: function () {
MochiKit.Signal.disconnect(this.eventMouseDown);
MochiKit.DragAndDrop.Draggables.unregister(this);
},
/** @id MochiKit.DragAndDrop.currentDelta */
currentDelta: function () {
var s = MochiKit.Style.getStyle;
return [
parseInt(s(this.element, 'left') || '0'),
parseInt(s(this.element, 'top') || '0')];
},
/** @id MochiKit.DragAndDrop.initDrag */
initDrag: function (event) {
if (!event.mouse().button.left) {
return;
}
// abort on form elements, fixes a Firefox issue
var src = event.target();
var tagName = (src.tagName || '').toUpperCase();
if (tagName === 'INPUT' || tagName === 'SELECT' ||
tagName === 'OPTION' || tagName === 'BUTTON' ||
tagName === 'TEXTAREA') {
return;
}
if (this._revert) {
this._revert.cancel();
this._revert = null;
}
var pointer = event.mouse();
var pos = MochiKit.Position.cumulativeOffset(this.element);
this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y];
MochiKit.DragAndDrop.Draggables.activate(this);
event.stop();
},
/** @id MochiKit.DragAndDrop.startDrag */
startDrag: function (event) {
this.dragging = true;
if (this.options.selectclass) {
MochiKit.DOM.addElementClass(this.element,
this.options.selectclass);
}
if (this.options.zindex) {
this.originalZ = parseInt(MochiKit.Style.getStyle(this.element,
'z-index') || '0');
this.element.style.zIndex = this.options.zindex;
}
if (this.options.ghosting) {
this._clone = this.element.cloneNode(true);
this.ghostPosition = MochiKit.Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
if (this.options.scroll) {
if (this.options.scroll == window) {
var where = this._getWindowScroll(this.options.scroll);
this.originalScrollLeft = where.left;
this.originalScrollTop = where.top;
} else {
this.originalScrollLeft = this.options.scroll.scrollLeft;
this.originalScrollTop = this.options.scroll.scrollTop;
}
}
MochiKit.DragAndDrop.Droppables.prepare(this.element);
MochiKit.DragAndDrop.Draggables.notify('start', this, event);
if (this.options.starteffect) {
this.options.starteffect(this.element);
}
},
/** @id MochiKit.DragAndDrop.updateDrag */
updateDrag: function (event, pointer) {
if (!this.dragging) {
this.startDrag(event);
}
MochiKit.Position.prepare();
MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
this.draw(pointer);
this.options.onchange(this);
if (this.options.scroll) {
this.stopScrolling();
var p, q;
if (this.options.scroll == window) {
var s = this._getWindowScroll(this.options.scroll);
p = new MochiKit.Style.Coordinates(s.left, s.top);
q = new MochiKit.Style.Coordinates(s.left + s.width,
s.top + s.height);
} else {
p = MochiKit.Position.page(this.options.scroll);
p.x += this.options.scroll.scrollLeft;
p.y += this.options.scroll.scrollTop;
p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
p.y + this.options.scroll.offsetHeight);
}
var speed = [0, 0];
if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
} else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
}
if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
} else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
}
this.startScrolling(speed);
}
// fix AppleWebKit rendering
if (/AppleWebKit/.test(navigator.appVersion)) {
window.scrollBy(0, 0);
}
event.stop();
},
/** @id MochiKit.DragAndDrop.finishDrag */
finishDrag: function (event, success) {
var dr = MochiKit.DragAndDrop;
this.dragging = false;
if (this.options.selectclass) {
MochiKit.DOM.removeElementClass(this.element,
this.options.selectclass);
}
if (this.options.ghosting) {
// XXX: from a user point of view, it would be better to remove
// the node only *after* the MochiKit.Visual.Move end when used
// with revert.
MochiKit.Position.relativize(this.element, this.ghostPosition);
MochiKit.DOM.removeElement(this._clone);
this._clone = null;
}
if (success) {
dr.Droppables.fire(event, this.element);
}
dr.Draggables.notify('end', this, event);
var revert = this.options.revert;
if (revert && typeof(revert) == 'function') {
revert = revert(this.element);
}
var d = this.currentDelta();
if (revert && this.options.reverteffect) {
this._revert = this.options.reverteffect(this.element,
d[1] - this.delta[1], d[0] - this.delta[0]);
} else {
this.delta = d;
}
if (this.options.zindex) {
this.element.style.zIndex = this.originalZ;
}
if (this.options.endeffect) {
this.options.endeffect(this.element);
}
dr.Draggables.deactivate();
dr.Droppables.reset(this.element);
},
/** @id MochiKit.DragAndDrop.keyPress */
keyPress: function (event) {
if (event.key().string != "KEY_ESCAPE") {
return;
}
this.finishDrag(event, false);
event.stop();
},
/** @id MochiKit.DragAndDrop.endDrag */
endDrag: function (event) {
if (!this.dragging) {
return;
}
this.stopScrolling();
this.finishDrag(event, true);
event.stop();
},
/** @id MochiKit.DragAndDrop.draw */
draw: function (point) {
var pos = MochiKit.Position.cumulativeOffset(this.element);
var d = this.currentDelta();
pos.x -= d[0];
pos.y -= d[1];
if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
}
var p = [point.page.x - pos.x - this.offset[0],
point.page.y - pos.y - this.offset[1]];
if (this.options.snap) {
if (typeof(this.options.snap) == 'function') {
p = this.options.snap(p[0], p[1]);
} else {
if (this.options.snap instanceof Array) {
var i = -1;
p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
i += 1;
return Math.round(v/this.options.snap[i]) *
this.options.snap[i];
}, this), p);
} else {
p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
return Math.round(v/this.options.snap) *
this.options.snap;
}, this), p);
}
}
}
var style = this.element.style;
if ((!this.options.constraint) ||
(this.options.constraint == 'horizontal')) {
style.left = p[0] + 'px';
}
if ((!this.options.constraint) ||
(this.options.constraint == 'vertical')) {
style.top = p[1] + 'px';
}
if (style.visibility == 'hidden') {
style.visibility = ''; // fix gecko rendering
}
},
/** @id MochiKit.DragAndDrop.stopScrolling */
stopScrolling: function () {
if (this.scrollInterval) {
clearInterval(this.scrollInterval);
this.scrollInterval = null;
MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
}
},
/** @id MochiKit.DragAndDrop.startScrolling */
startScrolling: function (speed) {
if (!speed[0] && !speed[1]) {
return;
}
this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
speed[1] * this.options.scrollSpeed];
this.lastScrolled = new Date();
this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
},
/** @id MochiKit.DragAndDrop.scroll */
scroll: function () {
var current = new Date();
var delta = current - this.lastScrolled;
this.lastScrolled = current;
if (this.options.scroll == window) {
var s = this._getWindowScroll(this.options.scroll);
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
var dm = delta / 1000;
this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0],
s.top + dm * this.scrollSpeed[1]);
}
} else {
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}
var d = MochiKit.DragAndDrop;
MochiKit.Position.prepare();
d.Droppables.show(d.Draggables._lastPointer, this.element);
d.Draggables.notify('drag', this);
if (this._isScrollChild) {
d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
if (d.Draggables._lastScrollPointer.x < 0) {
d.Draggables._lastScrollPointer.x = 0;
}
if (d.Draggables._lastScrollPointer.y < 0) {
d.Draggables._lastScrollPointer.y = 0;
}
this.draw(d.Draggables._lastScrollPointer);
}
this.options.onchange(this);
},
_getWindowScroll: function (win) {
var vp, w, h;
MochiKit.DOM.withWindow(win, function () {
vp = MochiKit.Style.getViewportPosition(win.document);
});
if (win.innerWidth) {
w = win.innerWidth;
h = win.innerHeight;
} else if (win.document.documentElement && win.document.documentElement.clientWidth) {
w = win.document.documentElement.clientWidth;
h = win.document.documentElement.clientHeight;
} else {
w = win.document.body.offsetWidth;
h = win.document.body.offsetHeight;
}
return {top: vp.y, left: vp.x, width: w, height: h};
},
/** @id MochiKit.DragAndDrop.repr */
repr: function () {
return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
}
};
MochiKit.DragAndDrop.__new__ = function () {
MochiKit.Base.nameFunctions(this);
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
};
};
MochiKit.DragAndDrop.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);

View file

@ -0,0 +1,304 @@
/***
MochiKit.Format 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('Format', ['Base']);
MochiKit.Format.NAME = "MochiKit.Format";
MochiKit.Format.VERSION = "1.4.2";
MochiKit.Format.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Format.toString = function () {
return this.__repr__();
};
MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
return function (num) {
num = parseFloat(num);
if (typeof(num) == "undefined" || num === null || isNaN(num)) {
return placeholder;
}
var curheader = header;
var curfooter = footer;
if (num < 0) {
num = -num;
} else {
curheader = curheader.replace(/-/, "");
}
var me = arguments.callee;
var fmt = MochiKit.Format.formatLocale(locale);
if (isPercent) {
num = num * 100.0;
curfooter = fmt.percent + curfooter;
}
num = MochiKit.Format.roundToFixed(num, precision);
var parts = num.split(/\./);
var whole = parts[0];
var frac = (parts.length == 1) ? "" : parts[1];
var res = "";
while (whole.length < leadingZeros) {
whole = "0" + whole;
}
if (separatorAt) {
while (whole.length > separatorAt) {
var i = whole.length - separatorAt;
//res = res + fmt.separator + whole.substring(i, whole.length);
res = fmt.separator + whole.substring(i, whole.length) + res;
whole = whole.substring(0, i);
}
}
res = whole + res;
if (precision > 0) {
while (frac.length < trailingZeros) {
frac = frac + "0";
}
res = res + fmt.decimal + frac;
}
return curheader + res + curfooter;
};
};
/** @id MochiKit.Format.numberFormatter */
MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
// http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
// | 0 | leading or trailing zeros
// | # | just the number
// | , | separator
// | . | decimal separator
// | % | Multiply by 100 and format as percent
if (typeof(placeholder) == "undefined") {
placeholder = "";
}
var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
if (!match) {
throw TypeError("Invalid pattern");
}
var header = pattern.substr(0, match.index);
var footer = pattern.substr(match.index + match[0].length);
if (header.search(/-/) == -1) {
header = header + "-";
}
var whole = match[1];
var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
var isPercent = (typeof(match[3]) == "string" && match[3] != "");
var tmp = whole.split(/,/);
var separatorAt;
if (typeof(locale) == "undefined") {
locale = "default";
}
if (tmp.length == 1) {
separatorAt = null;
} else {
separatorAt = tmp[1].length;
}
var leadingZeros = whole.length - whole.replace(/0/g, "").length;
var trailingZeros = frac.length - frac.replace(/0/g, "").length;
var precision = frac.length;
var rval = MochiKit.Format._numberFormatter(
placeholder, header, footer, locale, isPercent, precision,
leadingZeros, separatorAt, trailingZeros
);
var m = MochiKit.Base;
if (m) {
var fn = arguments.callee;
var args = m.concat(arguments);
rval.repr = function () {
return [
self.NAME,
"(",
map(m.repr, args).join(", "),
")"
].join("");
};
}
return rval;
};
/** @id MochiKit.Format.formatLocale */
MochiKit.Format.formatLocale = function (locale) {
if (typeof(locale) == "undefined" || locale === null) {
locale = "default";
}
if (typeof(locale) == "string") {
var rval = MochiKit.Format.LOCALE[locale];
if (typeof(rval) == "string") {
rval = arguments.callee(rval);
MochiKit.Format.LOCALE[locale] = rval;
}
return rval;
} else {
return locale;
}
};
/** @id MochiKit.Format.twoDigitAverage */
MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
if (denominator) {
var res = numerator / denominator;
if (!isNaN(res)) {
return MochiKit.Format.twoDigitFloat(res);
}
}
return "0";
};
/** @id MochiKit.Format.twoDigitFloat */
MochiKit.Format.twoDigitFloat = function (aNumber) {
var res = roundToFixed(aNumber, 2);
if (res.indexOf(".00") > 0) {
return res.substring(0, res.length - 3);
} else if (res.charAt(res.length - 1) == "0") {
return res.substring(0, res.length - 1);
} else {
return res;
}
};
/** @id MochiKit.Format.lstrip */
MochiKit.Format.lstrip = function (str, /* optional */chars) {
str = str + "";
if (typeof(str) != "string") {
return null;
}
if (!chars) {
return str.replace(/^\s+/, "");
} else {
return str.replace(new RegExp("^[" + chars + "]+"), "");
}
};
/** @id MochiKit.Format.rstrip */
MochiKit.Format.rstrip = function (str, /* optional */chars) {
str = str + "";
if (typeof(str) != "string") {
return null;
}
if (!chars) {
return str.replace(/\s+$/, "");
} else {
return str.replace(new RegExp("[" + chars + "]+$"), "");
}
};
/** @id MochiKit.Format.strip */
MochiKit.Format.strip = function (str, /* optional */chars) {
var self = MochiKit.Format;
return self.rstrip(self.lstrip(str, chars), chars);
};
/** @id MochiKit.Format.truncToFixed */
MochiKit.Format.truncToFixed = function (aNumber, precision) {
var res = Math.floor(aNumber).toFixed(0);
if (aNumber < 0) {
res = Math.ceil(aNumber).toFixed(0);
if (res.charAt(0) != "-" && precision > 0) {
res = "-" + res;
}
}
if (res.indexOf("e") < 0 && precision > 0) {
var tail = aNumber.toString();
if (tail.indexOf("e") > 0) {
tail = ".";
} else if (tail.indexOf(".") < 0) {
tail = ".";
} else {
tail = tail.substring(tail.indexOf("."));
}
if (tail.length - 1 > precision) {
tail = tail.substring(0, precision + 1);
}
while (tail.length - 1 < precision) {
tail += "0";
}
res += tail;
}
return res;
};
/** @id MochiKit.Format.roundToFixed */
MochiKit.Format.roundToFixed = function (aNumber, precision) {
var upper = Math.abs(aNumber) + 0.5 * Math.pow(10, -precision);
var res = MochiKit.Format.truncToFixed(upper, precision);
if (aNumber < 0) {
res = "-" + res;
}
return res;
};
/** @id MochiKit.Format.percentFormat */
MochiKit.Format.percentFormat = function (aNumber) {
return MochiKit.Format.twoDigitFloat(100 * aNumber) + '%';
};
MochiKit.Format.EXPORT = [
"truncToFixed",
"roundToFixed",
"numberFormatter",
"formatLocale",
"twoDigitAverage",
"twoDigitFloat",
"percentFormat",
"lstrip",
"rstrip",
"strip"
];
MochiKit.Format.LOCALE = {
en_US: {separator: ",", decimal: ".", percent: "%"},
de_DE: {separator: ".", decimal: ",", percent: "%"},
pt_BR: {separator: ".", decimal: ",", percent: "%"},
fr_FR: {separator: " ", decimal: ",", percent: "%"},
"default": "en_US"
};
MochiKit.Format.EXPORT_OK = [];
MochiKit.Format.EXPORT_TAGS = {
':all': MochiKit.Format.EXPORT,
':common': MochiKit.Format.EXPORT
};
MochiKit.Format.__new__ = function () {
// MochiKit.Base.nameFunctions(this);
var base = this.NAME + ".";
var k, v, o;
for (k in this.LOCALE) {
o = this.LOCALE[k];
if (typeof(o) == "object") {
o.repr = function () { return this.NAME; };
o.NAME = base + "LOCALE." + k;
}
}
for (k in this) {
o = this[k];
if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
try {
o.NAME = base + k;
} catch (e) {
// pass
}
}
}
};
MochiKit.Format.__new__();
if (typeof(MochiKit.Base) != "undefined") {
MochiKit.Base._exportSymbols(this, MochiKit.Format);
} else {
(function (globals, module) {
if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
|| (MochiKit.__export__ === false)) {
var all = module.EXPORT_TAGS[":all"];
for (var i = 0; i < all.length; i++) {
globals[all[i]] = module[all[i]];
}
}
})(this, MochiKit.Format);
}

View file

@ -0,0 +1,844 @@
/***
MochiKit.Iter 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('Iter', ['Base']);
MochiKit.Iter.NAME = "MochiKit.Iter";
MochiKit.Iter.VERSION = "1.4.2";
MochiKit.Base.update(MochiKit.Iter, {
__repr__: function () {
return "[" + this.NAME + " " + this.VERSION + "]";
},
toString: function () {
return this.__repr__();
},
/** @id MochiKit.Iter.registerIteratorFactory */
registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
},
/** @id MochiKit.Iter.isIterable */
isIterable: function(o) {
return o != null &&
(typeof(o.next) == "function" || typeof(o.iter) == "function");
},
/** @id MochiKit.Iter.iter */
iter: function (iterable, /* optional */ sentinel) {
var self = MochiKit.Iter;
if (arguments.length == 2) {
return self.takewhile(
function (a) { return a != sentinel; },
iterable
);
}
if (typeof(iterable.next) == 'function') {
return iterable;
} else if (typeof(iterable.iter) == 'function') {
return iterable.iter();
/*
} else if (typeof(iterable.__iterator__) == 'function') {
//
// XXX: We can't support JavaScript 1.7 __iterator__ directly
// because of Object.prototype.__iterator__
//
return iterable.__iterator__();
*/
}
try {
return self.iteratorRegistry.match(iterable);
} catch (e) {
var m = MochiKit.Base;
if (e == m.NotFound) {
e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
}
throw e;
}
},
/** @id MochiKit.Iter.count */
count: function (n) {
if (!n) {
n = 0;
}
var m = MochiKit.Base;
return {
repr: function () { return "count(" + n + ")"; },
toString: m.forwardCall("repr"),
next: m.counter(n)
};
},
/** @id MochiKit.Iter.cycle */
cycle: function (p) {
var self = MochiKit.Iter;
var m = MochiKit.Base;
var lst = [];
var iterator = self.iter(p);
return {
repr: function () { return "cycle(...)"; },
toString: m.forwardCall("repr"),
next: function () {
try {
var rval = iterator.next();
lst.push(rval);
return rval;
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
if (lst.length === 0) {
this.next = function () {
throw self.StopIteration;
};
} else {
var i = -1;
this.next = function () {
i = (i + 1) % lst.length;
return lst[i];
};
}
return this.next();
}
}
};
},
/** @id MochiKit.Iter.repeat */
repeat: function (elem, /* optional */n) {
var m = MochiKit.Base;
if (typeof(n) == 'undefined') {
return {
repr: function () {
return "repeat(" + m.repr(elem) + ")";
},
toString: m.forwardCall("repr"),
next: function () {
return elem;
}
};
}
return {
repr: function () {
return "repeat(" + m.repr(elem) + ", " + n + ")";
},
toString: m.forwardCall("repr"),
next: function () {
if (n <= 0) {
throw MochiKit.Iter.StopIteration;
}
n -= 1;
return elem;
}
};
},
/** @id MochiKit.Iter.next */
next: function (iterator) {
return iterator.next();
},
/** @id MochiKit.Iter.izip */
izip: function (p, q/*, ...*/) {
var m = MochiKit.Base;
var self = MochiKit.Iter;
var next = self.next;
var iterables = m.map(self.iter, arguments);
return {
repr: function () { return "izip(...)"; },
toString: m.forwardCall("repr"),
next: function () { return m.map(next, iterables); }
};
},
/** @id MochiKit.Iter.ifilter */
ifilter: function (pred, seq) {
var m = MochiKit.Base;
seq = MochiKit.Iter.iter(seq);
if (pred === null) {
pred = m.operator.truth;
}
return {
repr: function () { return "ifilter(...)"; },
toString: m.forwardCall("repr"),
next: function () {
while (true) {
var rval = seq.next();
if (pred(rval)) {
return rval;
}
}
// mozilla warnings aren't too bright
return undefined;
}
};
},
/** @id MochiKit.Iter.ifilterfalse */
ifilterfalse: function (pred, seq) {
var m = MochiKit.Base;
seq = MochiKit.Iter.iter(seq);
if (pred === null) {
pred = m.operator.truth;
}
return {
repr: function () { return "ifilterfalse(...)"; },
toString: m.forwardCall("repr"),
next: function () {
while (true) {
var rval = seq.next();
if (!pred(rval)) {
return rval;
}
}
// mozilla warnings aren't too bright
return undefined;
}
};
},
/** @id MochiKit.Iter.islice */
islice: function (seq/*, [start,] stop[, step] */) {
var self = MochiKit.Iter;
var m = MochiKit.Base;
seq = self.iter(seq);
var start = 0;
var stop = 0;
var step = 1;
var i = -1;
if (arguments.length == 2) {
stop = arguments[1];
} else if (arguments.length == 3) {
start = arguments[1];
stop = arguments[2];
} else {
start = arguments[1];
stop = arguments[2];
step = arguments[3];
}
return {
repr: function () {
return "islice(" + ["...", start, stop, step].join(", ") + ")";
},
toString: m.forwardCall("repr"),
next: function () {
var rval;
while (i < start) {
rval = seq.next();
i++;
}
if (start >= stop) {
throw self.StopIteration;
}
start += step;
return rval;
}
};
},
/** @id MochiKit.Iter.imap */
imap: function (fun, p, q/*, ...*/) {
var m = MochiKit.Base;
var self = MochiKit.Iter;
var iterables = m.map(self.iter, m.extend(null, arguments, 1));
var map = m.map;
var next = self.next;
return {
repr: function () { return "imap(...)"; },
toString: m.forwardCall("repr"),
next: function () {
return fun.apply(this, map(next, iterables));
}
};
},
/** @id MochiKit.Iter.applymap */
applymap: function (fun, seq, self) {
seq = MochiKit.Iter.iter(seq);
var m = MochiKit.Base;
return {
repr: function () { return "applymap(...)"; },
toString: m.forwardCall("repr"),
next: function () {
return fun.apply(self, seq.next());
}
};
},
/** @id MochiKit.Iter.chain */
chain: function (p, q/*, ...*/) {
// dumb fast path
var self = MochiKit.Iter;
var m = MochiKit.Base;
if (arguments.length == 1) {
return self.iter(arguments[0]);
}
var argiter = m.map(self.iter, arguments);
return {
repr: function () { return "chain(...)"; },
toString: m.forwardCall("repr"),
next: function () {
while (argiter.length > 1) {
try {
var result = argiter[0].next();
return result;
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
argiter.shift();
var result = argiter[0].next();
return result;
}
}
if (argiter.length == 1) {
// optimize last element
var arg = argiter.shift();
this.next = m.bind("next", arg);
return this.next();
}
throw self.StopIteration;
}
};
},
/** @id MochiKit.Iter.takewhile */
takewhile: function (pred, seq) {
var self = MochiKit.Iter;
seq = self.iter(seq);
return {
repr: function () { return "takewhile(...)"; },
toString: MochiKit.Base.forwardCall("repr"),
next: function () {
var rval = seq.next();
if (!pred(rval)) {
this.next = function () {
throw self.StopIteration;
};
this.next();
}
return rval;
}
};
},
/** @id MochiKit.Iter.dropwhile */
dropwhile: function (pred, seq) {
seq = MochiKit.Iter.iter(seq);
var m = MochiKit.Base;
var bind = m.bind;
return {
"repr": function () { return "dropwhile(...)"; },
"toString": m.forwardCall("repr"),
"next": function () {
while (true) {
var rval = seq.next();
if (!pred(rval)) {
break;
}
}
this.next = bind("next", seq);
return rval;
}
};
},
_tee: function (ident, sync, iterable) {
sync.pos[ident] = -1;
var m = MochiKit.Base;
var listMin = m.listMin;
return {
repr: function () { return "tee(" + ident + ", ...)"; },
toString: m.forwardCall("repr"),
next: function () {
var rval;
var i = sync.pos[ident];
if (i == sync.max) {
rval = iterable.next();
sync.deque.push(rval);
sync.max += 1;
sync.pos[ident] += 1;
} else {
rval = sync.deque[i - sync.min];
sync.pos[ident] += 1;
if (i == sync.min && listMin(sync.pos) != sync.min) {
sync.min += 1;
sync.deque.shift();
}
}
return rval;
}
};
},
/** @id MochiKit.Iter.tee */
tee: function (iterable, n/* = 2 */) {
var rval = [];
var sync = {
"pos": [],
"deque": [],
"max": -1,
"min": -1
};
if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
n = 2;
}
var self = MochiKit.Iter;
iterable = self.iter(iterable);
var _tee = self._tee;
for (var i = 0; i < n; i++) {
rval.push(_tee(i, sync, iterable));
}
return rval;
},
/** @id MochiKit.Iter.list */
list: function (iterable) {
// Fast-path for Array and Array-like
var rval;
if (iterable instanceof Array) {
return iterable.slice();
}
// this is necessary to avoid a Safari crash
if (typeof(iterable) == "function" &&
!(iterable instanceof Function) &&
typeof(iterable.length) == 'number') {
rval = [];
for (var i = 0; i < iterable.length; i++) {
rval.push(iterable[i]);
}
return rval;
}
var self = MochiKit.Iter;
iterable = self.iter(iterable);
var rval = [];
var a_val;
try {
while (true) {
a_val = iterable.next();
rval.push(a_val);
}
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
return rval;
}
// mozilla warnings aren't too bright
return undefined;
},
/** @id MochiKit.Iter.reduce */
reduce: function (fn, iterable, /* optional */initial) {
var i = 0;
var x = initial;
var self = MochiKit.Iter;
iterable = self.iter(iterable);
if (arguments.length < 3) {
try {
x = iterable.next();
} catch (e) {
if (e == self.StopIteration) {
e = new TypeError("reduce() of empty sequence with no initial value");
}
throw e;
}
i++;
}
try {
while (true) {
x = fn(x, iterable.next());
}
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
}
return x;
},
/** @id MochiKit.Iter.range */
range: function (/* [start,] stop[, step] */) {
var start = 0;
var stop = 0;
var step = 1;
if (arguments.length == 1) {
stop = arguments[0];
} else if (arguments.length == 2) {
start = arguments[0];
stop = arguments[1];
} else if (arguments.length == 3) {
start = arguments[0];
stop = arguments[1];
step = arguments[2];
} else {
throw new TypeError("range() takes 1, 2, or 3 arguments!");
}
if (step === 0) {
throw new TypeError("range() step must not be 0");
}
return {
next: function () {
if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
throw MochiKit.Iter.StopIteration;
}
var rval = start;
start += step;
return rval;
},
repr: function () {
return "range(" + [start, stop, step].join(", ") + ")";
},
toString: MochiKit.Base.forwardCall("repr")
};
},
/** @id MochiKit.Iter.sum */
sum: function (iterable, start/* = 0 */) {
if (typeof(start) == "undefined" || start === null) {
start = 0;
}
var x = start;
var self = MochiKit.Iter;
iterable = self.iter(iterable);
try {
while (true) {
x += iterable.next();
}
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
}
return x;
},
/** @id MochiKit.Iter.exhaust */
exhaust: function (iterable) {
var self = MochiKit.Iter;
iterable = self.iter(iterable);
try {
while (true) {
iterable.next();
}
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
}
},
/** @id MochiKit.Iter.forEach */
forEach: function (iterable, func, /* optional */obj) {
var m = MochiKit.Base;
var self = MochiKit.Iter;
if (arguments.length > 2) {
func = m.bind(func, obj);
}
// fast path for array
if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
try {
for (var i = 0; i < iterable.length; i++) {
func(iterable[i]);
}
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
}
} else {
self.exhaust(self.imap(func, iterable));
}
},
/** @id MochiKit.Iter.every */
every: function (iterable, func) {
var self = MochiKit.Iter;
try {
self.ifilterfalse(func, iterable).next();
return false;
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
return true;
}
},
/** @id MochiKit.Iter.sorted */
sorted: function (iterable, /* optional */cmp) {
var rval = MochiKit.Iter.list(iterable);
if (arguments.length == 1) {
cmp = MochiKit.Base.compare;
}
rval.sort(cmp);
return rval;
},
/** @id MochiKit.Iter.reversed */
reversed: function (iterable) {
var rval = MochiKit.Iter.list(iterable);
rval.reverse();
return rval;
},
/** @id MochiKit.Iter.some */
some: function (iterable, func) {
var self = MochiKit.Iter;
try {
self.ifilter(func, iterable).next();
return true;
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
return false;
}
},
/** @id MochiKit.Iter.iextend */
iextend: function (lst, iterable) {
var m = MochiKit.Base;
var self = MochiKit.Iter;
if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
// fast-path for array-like
for (var i = 0; i < iterable.length; i++) {
lst.push(iterable[i]);
}
} else {
iterable = self.iter(iterable);
try {
while (true) {
lst.push(iterable.next());
}
} catch (e) {
if (e != self.StopIteration) {
throw e;
}
}
}
return lst;
},
/** @id MochiKit.Iter.groupby */
groupby: function(iterable, /* optional */ keyfunc) {
var m = MochiKit.Base;
var self = MochiKit.Iter;
if (arguments.length < 2) {
keyfunc = m.operator.identity;
}
iterable = self.iter(iterable);
// shared
var pk = undefined;
var k = undefined;
var v;
function fetch() {
v = iterable.next();
k = keyfunc(v);
};
function eat() {
var ret = v;
v = undefined;
return ret;
};
var first = true;
var compare = m.compare;
return {
repr: function () { return "groupby(...)"; },
next: function() {
// iterator-next
// iterate until meet next group
while (compare(k, pk) === 0) {
fetch();
if (first) {
first = false;
break;
}
}
pk = k;
return [k, {
next: function() {
// subiterator-next
if (v == undefined) { // Is there something to eat?
fetch();
}
if (compare(k, pk) !== 0) {
throw self.StopIteration;
}
return eat();
}
}];
}
};
},
/** @id MochiKit.Iter.groupby_as_array */
groupby_as_array: function (iterable, /* optional */ keyfunc) {
var m = MochiKit.Base;
var self = MochiKit.Iter;
if (arguments.length < 2) {
keyfunc = m.operator.identity;
}
iterable = self.iter(iterable);
var result = [];
var first = true;
var prev_key;
var compare = m.compare;
while (true) {
try {
var value = iterable.next();
var key = keyfunc(value);
} catch (e) {
if (e == self.StopIteration) {
break;
}
throw e;
}
if (first || compare(key, prev_key) !== 0) {
var values = [];
result.push([key, values]);
}
values.push(value);
first = false;
prev_key = key;
}
return result;
},
/** @id MochiKit.Iter.arrayLikeIter */
arrayLikeIter: function (iterable) {
var i = 0;
return {
repr: function () { return "arrayLikeIter(...)"; },
toString: MochiKit.Base.forwardCall("repr"),
next: function () {
if (i >= iterable.length) {
throw MochiKit.Iter.StopIteration;
}
return iterable[i++];
}
};
},
/** @id MochiKit.Iter.hasIterateNext */
hasIterateNext: function (iterable) {
return (iterable && typeof(iterable.iterateNext) == "function");
},
/** @id MochiKit.Iter.iterateNextIter */
iterateNextIter: function (iterable) {
return {
repr: function () { return "iterateNextIter(...)"; },
toString: MochiKit.Base.forwardCall("repr"),
next: function () {
var rval = iterable.iterateNext();
if (rval === null || rval === undefined) {
throw MochiKit.Iter.StopIteration;
}
return rval;
}
};
}
});
MochiKit.Iter.EXPORT_OK = [
"iteratorRegistry",
"arrayLikeIter",
"hasIterateNext",
"iterateNextIter"
];
MochiKit.Iter.EXPORT = [
"StopIteration",
"registerIteratorFactory",
"iter",
"count",
"cycle",
"repeat",
"next",
"izip",
"ifilter",
"ifilterfalse",
"islice",
"imap",
"applymap",
"chain",
"takewhile",
"dropwhile",
"tee",
"list",
"reduce",
"range",
"sum",
"exhaust",
"forEach",
"every",
"sorted",
"reversed",
"some",
"iextend",
"groupby",
"groupby_as_array"
];
MochiKit.Iter.__new__ = function () {
var m = MochiKit.Base;
// Re-use StopIteration if exists (e.g. SpiderMonkey)
if (typeof(StopIteration) != "undefined") {
this.StopIteration = StopIteration;
} else {
/** @id MochiKit.Iter.StopIteration */
this.StopIteration = new m.NamedError("StopIteration");
}
this.iteratorRegistry = new m.AdapterRegistry();
// Register the iterator factory for arrays
this.registerIteratorFactory(
"arrayLike",
m.isArrayLike,
this.arrayLikeIter
);
this.registerIteratorFactory(
"iterateNext",
this.hasIterateNext,
this.iterateNextIter
);
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
};
MochiKit.Iter.__new__();
//
// XXX: Internet Explorer blows
//
if (MochiKit.__export__) {
reduce = MochiKit.Iter.reduce;
}
MochiKit.Base._exportSymbols(this, MochiKit.Iter);

View file

@ -0,0 +1,315 @@
/***
MochiKit.Logging 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('Logging', ['Base']);
MochiKit.Logging.NAME = "MochiKit.Logging";
MochiKit.Logging.VERSION = "1.4.2";
MochiKit.Logging.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Logging.toString = function () {
return this.__repr__();
};
MochiKit.Logging.EXPORT = [
"LogLevel",
"LogMessage",
"Logger",
"alertListener",
"logger",
"log",
"logError",
"logDebug",
"logFatal",
"logWarning"
];
MochiKit.Logging.EXPORT_OK = [
"logLevelAtLeast",
"isLogMessage",
"compareLogMessage"
];
/** @id MochiKit.Logging.LogMessage */
MochiKit.Logging.LogMessage = function (num, level, info) {
this.num = num;
this.level = level;
this.info = info;
this.timestamp = new Date();
};
MochiKit.Logging.LogMessage.prototype = {
/** @id MochiKit.Logging.LogMessage.prototype.repr */
repr: function () {
var m = MochiKit.Base;
return 'LogMessage(' +
m.map(
m.repr,
[this.num, this.level, this.info]
).join(', ') + ')';
},
/** @id MochiKit.Logging.LogMessage.prototype.toString */
toString: MochiKit.Base.forwardCall("repr")
};
MochiKit.Base.update(MochiKit.Logging, {
/** @id MochiKit.Logging.logLevelAtLeast */
logLevelAtLeast: function (minLevel) {
var self = MochiKit.Logging;
if (typeof(minLevel) == 'string') {
minLevel = self.LogLevel[minLevel];
}
return function (msg) {
var msgLevel = msg.level;
if (typeof(msgLevel) == 'string') {
msgLevel = self.LogLevel[msgLevel];
}
return msgLevel >= minLevel;
};
},
/** @id MochiKit.Logging.isLogMessage */
isLogMessage: function (/* ... */) {
var LogMessage = MochiKit.Logging.LogMessage;
for (var i = 0; i < arguments.length; i++) {
if (!(arguments[i] instanceof LogMessage)) {
return false;
}
}
return true;
},
/** @id MochiKit.Logging.compareLogMessage */
compareLogMessage: function (a, b) {
return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
},
/** @id MochiKit.Logging.alertListener */
alertListener: function (msg) {
alert(
"num: " + msg.num +
"\nlevel: " + msg.level +
"\ninfo: " + msg.info.join(" ")
);
}
});
/** @id MochiKit.Logging.Logger */
MochiKit.Logging.Logger = function (/* optional */maxSize) {
this.counter = 0;
if (typeof(maxSize) == 'undefined' || maxSize === null) {
maxSize = -1;
}
this.maxSize = maxSize;
this._messages = [];
this.listeners = {};
this.useNativeConsole = false;
};
MochiKit.Logging.Logger.prototype = {
/** @id MochiKit.Logging.Logger.prototype.clear */
clear: function () {
this._messages.splice(0, this._messages.length);
},
/** @id MochiKit.Logging.Logger.prototype.logToConsole */
logToConsole: function (msg) {
if (typeof(window) != "undefined" && window.console
&& window.console.log) {
// Safari and FireBug 0.4
// Percent replacement is a workaround for cute Safari crashing bug
window.console.log(msg.replace(/%/g, '\uFF05'));
} else if (typeof(opera) != "undefined" && opera.postError) {
// Opera
opera.postError(msg);
} else if (typeof(printfire) == "function") {
// FireBug 0.3 and earlier
printfire(msg);
} else if (typeof(Debug) != "undefined" && Debug.writeln) {
// IE Web Development Helper (?)
// http://www.nikhilk.net/Entry.aspx?id=93
Debug.writeln(msg);
} else if (typeof(debug) != "undefined" && debug.trace) {
// Atlas framework (?)
// http://www.nikhilk.net/Entry.aspx?id=93
debug.trace(msg);
}
},
/** @id MochiKit.Logging.Logger.prototype.dispatchListeners */
dispatchListeners: function (msg) {
for (var k in this.listeners) {
var pair = this.listeners[k];
if (pair.ident != k || (pair[0] && !pair[0](msg))) {
continue;
}
pair[1](msg);
}
},
/** @id MochiKit.Logging.Logger.prototype.addListener */
addListener: function (ident, filter, listener) {
if (typeof(filter) == 'string') {
filter = MochiKit.Logging.logLevelAtLeast(filter);
}
var entry = [filter, listener];
entry.ident = ident;
this.listeners[ident] = entry;
},
/** @id MochiKit.Logging.Logger.prototype.removeListener */
removeListener: function (ident) {
delete this.listeners[ident];
},
/** @id MochiKit.Logging.Logger.prototype.baseLog */
baseLog: function (level, message/*, ...*/) {
if (typeof(level) == "number") {
if (level >= MochiKit.Logging.LogLevel.FATAL) {
level = 'FATAL';
} else if (level >= MochiKit.Logging.LogLevel.ERROR) {
level = 'ERROR';
} else if (level >= MochiKit.Logging.LogLevel.WARNING) {
level = 'WARNING';
} else if (level >= MochiKit.Logging.LogLevel.INFO) {
level = 'INFO';
} else {
level = 'DEBUG';
}
}
var msg = new MochiKit.Logging.LogMessage(
this.counter,
level,
MochiKit.Base.extend(null, arguments, 1)
);
this._messages.push(msg);
this.dispatchListeners(msg);
if (this.useNativeConsole) {
this.logToConsole(msg.level + ": " + msg.info.join(" "));
}
this.counter += 1;
while (this.maxSize >= 0 && this._messages.length > this.maxSize) {
this._messages.shift();
}
},
/** @id MochiKit.Logging.Logger.prototype.getMessages */
getMessages: function (howMany) {
var firstMsg = 0;
if (!(typeof(howMany) == 'undefined' || howMany === null)) {
firstMsg = Math.max(0, this._messages.length - howMany);
}
return this._messages.slice(firstMsg);
},
/** @id MochiKit.Logging.Logger.prototype.getMessageText */
getMessageText: function (howMany) {
if (typeof(howMany) == 'undefined' || howMany === null) {
howMany = 30;
}
var messages = this.getMessages(howMany);
if (messages.length) {
var lst = map(function (m) {
return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
}, messages);
lst.unshift('LAST ' + messages.length + ' MESSAGES:');
return lst.join('');
}
return '';
},
/** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */
debuggingBookmarklet: function (inline) {
if (typeof(MochiKit.LoggingPane) == "undefined") {
alert(this.getMessageText());
} else {
MochiKit.LoggingPane.createLoggingPane(inline || false);
}
}
};
MochiKit.Logging.__new__ = function () {
this.LogLevel = {
ERROR: 40,
FATAL: 50,
WARNING: 30,
INFO: 20,
DEBUG: 10
};
var m = MochiKit.Base;
m.registerComparator("LogMessage",
this.isLogMessage,
this.compareLogMessage
);
var partial = m.partial;
var Logger = this.Logger;
var baseLog = Logger.prototype.baseLog;
m.update(this.Logger.prototype, {
debug: partial(baseLog, 'DEBUG'),
log: partial(baseLog, 'INFO'),
error: partial(baseLog, 'ERROR'),
fatal: partial(baseLog, 'FATAL'),
warning: partial(baseLog, 'WARNING')
});
// indirectly find logger so it can be replaced
var self = this;
var connectLog = function (name) {
return function () {
self.logger[name].apply(self.logger, arguments);
};
};
/** @id MochiKit.Logging.log */
this.log = connectLog('log');
/** @id MochiKit.Logging.logError */
this.logError = connectLog('error');
/** @id MochiKit.Logging.logDebug */
this.logDebug = connectLog('debug');
/** @id MochiKit.Logging.logFatal */
this.logFatal = connectLog('fatal');
/** @id MochiKit.Logging.logWarning */
this.logWarning = connectLog('warning');
this.logger = new Logger();
this.logger.useNativeConsole = true;
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
};
if (typeof(printfire) == "undefined" &&
typeof(document) != "undefined" && document.createEvent &&
typeof(dispatchEvent) != "undefined") {
// FireBug really should be less lame about this global function
printfire = function () {
printfire.args = arguments;
var ev = document.createEvent("Events");
ev.initEvent("printfire", false, true);
dispatchEvent(ev);
};
}
MochiKit.Logging.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Logging);

View file

@ -0,0 +1,353 @@
/***
MochiKit.LoggingPane 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('LoggingPane', ['Base', 'Logging']);
MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane";
MochiKit.LoggingPane.VERSION = "1.4.2";
MochiKit.LoggingPane.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.LoggingPane.toString = function () {
return this.__repr__();
};
/** @id MochiKit.LoggingPane.createLoggingPane */
MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
var m = MochiKit.LoggingPane;
inline = !(!inline);
if (m._loggingPane && m._loggingPane.inline != inline) {
m._loggingPane.closePane();
m._loggingPane = null;
}
if (!m._loggingPane || m._loggingPane.closed) {
m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
}
return m._loggingPane;
};
/** @id MochiKit.LoggingPane.LoggingPane */
MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
/* Use a div if inline, pop up a window if not */
/* Create the elements */
if (typeof(logger) == "undefined" || logger === null) {
logger = MochiKit.Logging.logger;
}
this.logger = logger;
var update = MochiKit.Base.update;
var updatetree = MochiKit.Base.updatetree;
var bind = MochiKit.Base.bind;
var clone = MochiKit.Base.clone;
var win = window;
var uid = "_MochiKit_LoggingPane";
if (typeof(MochiKit.DOM) != "undefined") {
win = MochiKit.DOM.currentWindow();
}
if (!inline) {
// name the popup with the base URL for uniqueness
var url = win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g, "_");
var name = uid + "_" + url;
var nwin = win.open("", name, "dependent,resizable,height=200");
if (!nwin) {
alert("Not able to open debugging window due to pop-up blocking.");
return undefined;
}
nwin.document.write(
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
+ '"http://www.w3.org/TR/html4/loose.dtd">'
+ '<html><head><title>[MochiKit.LoggingPane]</title></head>'
+ '<body></body></html>'
);
nwin.document.close();
nwin.document.title += ' ' + win.document.title;
win = nwin;
}
var doc = win.document;
this.doc = doc;
// Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
var debugPane = doc.getElementById(uid);
var existing_pane = !!debugPane;
if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
debugPane.loggingPane.logger = this.logger;
debugPane.loggingPane.buildAndApplyFilter();
return debugPane.loggingPane;
}
if (existing_pane) {
// clear any existing contents
var child;
while ((child = debugPane.firstChild)) {
debugPane.removeChild(child);
}
} else {
debugPane = doc.createElement("div");
debugPane.id = uid;
}
debugPane.loggingPane = this;
var levelFilterField = doc.createElement("input");
var infoFilterField = doc.createElement("input");
var filterButton = doc.createElement("button");
var loadButton = doc.createElement("button");
var clearButton = doc.createElement("button");
var closeButton = doc.createElement("button");
var logPaneArea = doc.createElement("div");
var logPane = doc.createElement("div");
/* Set up the functions */
var listenerId = uid + "_Listener";
this.colorTable = clone(this.colorTable);
var messages = [];
var messageFilter = null;
/** @id MochiKit.LoggingPane.messageLevel */
var messageLevel = function (msg) {
var level = msg.level;
if (typeof(level) == "number") {
level = MochiKit.Logging.LogLevel[level];
}
return level;
};
/** @id MochiKit.LoggingPane.messageText */
var messageText = function (msg) {
return msg.info.join(" ");
};
/** @id MochiKit.LoggingPane.addMessageText */
var addMessageText = bind(function (msg) {
var level = messageLevel(msg);
var text = messageText(msg);
var c = this.colorTable[level];
var p = doc.createElement("span");
p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
p.style.cssText = "margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: " + c;
p.appendChild(doc.createTextNode(level + ": " + text));
logPane.appendChild(p);
logPane.appendChild(doc.createElement("br"));
if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
logPaneArea.scrollTop = 0;
} else {
logPaneArea.scrollTop = logPaneArea.scrollHeight;
}
}, this);
/** @id MochiKit.LoggingPane.addMessage */
var addMessage = function (msg) {
messages[messages.length] = msg;
addMessageText(msg);
};
/** @id MochiKit.LoggingPane.buildMessageFilter */
var buildMessageFilter = function () {
var levelre, infore;
try {
/* Catch any exceptions that might arise due to invalid regexes */
levelre = new RegExp(levelFilterField.value);
infore = new RegExp(infoFilterField.value);
} catch(e) {
/* If there was an error with the regexes, do no filtering */
logDebug("Error in filter regex: " + e.message);
return null;
}
return function (msg) {
return (
levelre.test(messageLevel(msg)) &&
infore.test(messageText(msg))
);
};
};
/** @id MochiKit.LoggingPane.clearMessagePane */
var clearMessagePane = function () {
while (logPane.firstChild) {
logPane.removeChild(logPane.firstChild);
}
};
/** @id MochiKit.LoggingPane.clearMessages */
var clearMessages = function () {
messages = [];
clearMessagePane();
};
/** @id MochiKit.LoggingPane.closePane */
var closePane = bind(function () {
if (this.closed) {
return;
}
this.closed = true;
if (MochiKit.LoggingPane._loggingPane == this) {
MochiKit.LoggingPane._loggingPane = null;
}
this.logger.removeListener(listenerId);
try {
try {
debugPane.loggingPane = null;
} catch(e) { logFatal("Bookmarklet was closed incorrectly."); }
if (inline) {
debugPane.parentNode.removeChild(debugPane);
} else {
this.win.close();
}
} catch(e) {}
}, this);
/** @id MochiKit.LoggingPane.filterMessages */
var filterMessages = function () {
clearMessagePane();
for (var i = 0; i < messages.length; i++) {
var msg = messages[i];
if (messageFilter === null || messageFilter(msg)) {
addMessageText(msg);
}
}
};
this.buildAndApplyFilter = function () {
messageFilter = buildMessageFilter();
filterMessages();
this.logger.removeListener(listenerId);
this.logger.addListener(listenerId, messageFilter, addMessage);
};
/** @id MochiKit.LoggingPane.loadMessages */
var loadMessages = bind(function () {
messages = this.logger.getMessages();
filterMessages();
}, this);
/** @id MochiKit.LoggingPane.filterOnEnter */
var filterOnEnter = bind(function (event) {
event = event || window.event;
key = event.which || event.keyCode;
if (key == 13) {
this.buildAndApplyFilter();
}
}, this);
/* Create the debug pane */
var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
if (inline) {
style += "; height: 10em; border-top: 2px solid black";
} else {
style += "; height: 100%;";
}
debugPane.style.cssText = style;
if (!existing_pane) {
doc.body.appendChild(debugPane);
}
/* Create the filter fields */
style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
updatetree(levelFilterField, {
"value": "FATAL|ERROR|WARNING|INFO|DEBUG",
"onkeypress": filterOnEnter,
"style": style
});
debugPane.appendChild(levelFilterField);
updatetree(infoFilterField, {
"value": ".*",
"onkeypress": filterOnEnter,
"style": style
});
debugPane.appendChild(infoFilterField);
/* Create the buttons */
style = "width: 8%; display:inline; font: " + this.logFont;
filterButton.appendChild(doc.createTextNode("Filter"));
filterButton.onclick = bind("buildAndApplyFilter", this);
filterButton.style.cssText = style;
debugPane.appendChild(filterButton);
loadButton.appendChild(doc.createTextNode("Load"));
loadButton.onclick = loadMessages;
loadButton.style.cssText = style;
debugPane.appendChild(loadButton);
clearButton.appendChild(doc.createTextNode("Clear"));
clearButton.onclick = clearMessages;
clearButton.style.cssText = style;
debugPane.appendChild(clearButton);
closeButton.appendChild(doc.createTextNode("Close"));
closeButton.onclick = closePane;
closeButton.style.cssText = style;
debugPane.appendChild(closeButton);
/* Create the logging pane */
logPaneArea.style.cssText = "overflow: auto; width: 100%";
logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
logPaneArea.appendChild(logPane);
debugPane.appendChild(logPaneArea);
this.buildAndApplyFilter();
loadMessages();
if (inline) {
this.win = undefined;
} else {
this.win = win;
}
this.inline = inline;
this.closePane = closePane;
this.closed = false;
return this;
};
MochiKit.LoggingPane.LoggingPane.prototype = {
"logFont": "8pt Verdana,sans-serif",
"colorTable": {
"ERROR": "red",
"FATAL": "darkred",
"WARNING": "blue",
"INFO": "black",
"DEBUG": "green"
}
};
MochiKit.LoggingPane.EXPORT_OK = [
"LoggingPane"
];
MochiKit.LoggingPane.EXPORT = [
"createLoggingPane"
];
MochiKit.LoggingPane.__new__ = function () {
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
};
MochiKit.Base.nameFunctions(this);
MochiKit.LoggingPane._loggingPane = null;
};
MochiKit.LoggingPane.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);

View file

@ -0,0 +1,188 @@
/***
MochiKit.MochiKit 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
if (typeof(MochiKit) == 'undefined') {
MochiKit = {};
}
if (typeof(MochiKit.MochiKit) == 'undefined') {
/** @id MochiKit.MochiKit */
MochiKit.MochiKit = {};
}
MochiKit.MochiKit.NAME = "MochiKit.MochiKit";
MochiKit.MochiKit.VERSION = "1.4.2";
MochiKit.MochiKit.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
/** @id MochiKit.MochiKit.toString */
MochiKit.MochiKit.toString = function () {
return this.__repr__();
};
/** @id MochiKit.MochiKit.SUBMODULES */
MochiKit.MochiKit.SUBMODULES = [
"Base",
"Iter",
"Logging",
"DateTime",
"Format",
"Async",
"DOM",
"Selector",
"Style",
"LoggingPane",
"Color",
"Signal",
"Position",
"Visual",
"DragAndDrop",
"Sortable"
];
if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') {
if (typeof(dojo) != 'undefined') {
dojo.provide('MochiKit.MochiKit');
(function (lst) {
for (var i = 0; i < lst.length; i++) {
dojo.require("MochiKit." + lst[i]);
}
})(MochiKit.MochiKit.SUBMODULES);
}
if (typeof(JSAN) != 'undefined') {
(function (lst) {
for (var i = 0; i < lst.length; i++) {
JSAN.use("MochiKit." + lst[i], []);
}
})(MochiKit.MochiKit.SUBMODULES);
}
(function () {
var extend = MochiKit.Base.extend;
var self = MochiKit.MochiKit;
var modules = self.SUBMODULES;
var EXPORT = [];
var EXPORT_OK = [];
var EXPORT_TAGS = {};
var i, k, m, all;
for (i = 0; i < modules.length; i++) {
m = MochiKit[modules[i]];
extend(EXPORT, m.EXPORT);
extend(EXPORT_OK, m.EXPORT_OK);
for (k in m.EXPORT_TAGS) {
EXPORT_TAGS[k] = extend(EXPORT_TAGS[k], m.EXPORT_TAGS[k]);
}
all = m.EXPORT_TAGS[":all"];
if (!all) {
all = extend(null, m.EXPORT, m.EXPORT_OK);
}
var j;
for (j = 0; j < all.length; j++) {
k = all[j];
self[k] = m[k];
}
}
self.EXPORT = EXPORT;
self.EXPORT_OK = EXPORT_OK;
self.EXPORT_TAGS = EXPORT_TAGS;
}());
} else {
if (typeof(MochiKit.__compat__) == 'undefined') {
MochiKit.__compat__ = true;
}
(function () {
if (typeof(document) == "undefined") {
return;
}
var scripts = document.getElementsByTagName("script");
var kXHTMLNSURI = "http://www.w3.org/1999/xhtml";
var kSVGNSURI = "http://www.w3.org/2000/svg";
var kXLINKNSURI = "http://www.w3.org/1999/xlink";
var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var base = null;
var baseElem = null;
var allScripts = {};
var i;
var src;
for (i = 0; i < scripts.length; i++) {
src = null;
switch (scripts[i].namespaceURI) {
case kSVGNSURI:
src = scripts[i].getAttributeNS(kXLINKNSURI, "href");
break;
/*
case null: // HTML
case '': // HTML
case kXHTMLNSURI:
case kXULNSURI:
*/
default:
src = scripts[i].getAttribute("src");
break;
}
if (!src) {
continue;
}
allScripts[src] = true;
if (src.match(/MochiKit.js(\?.*)?$/)) {
base = src.substring(0, src.lastIndexOf('MochiKit.js'));
baseElem = scripts[i];
}
}
if (base === null) {
return;
}
var modules = MochiKit.MochiKit.SUBMODULES;
for (var i = 0; i < modules.length; i++) {
if (MochiKit[modules[i]]) {
continue;
}
var uri = base + modules[i] + '.js';
if (uri in allScripts) {
continue;
}
if (baseElem.namespaceURI == kSVGNSURI ||
baseElem.namespaceURI == kXULNSURI) {
// SVG, XUL
/*
SVG does not support document.write, so if Safari wants to
support SVG tests it should fix its deferred loading bug
(see following below).
*/
var s = document.createElementNS(baseElem.namespaceURI, 'script');
s.setAttribute("id", "MochiKit_" + base + modules[i]);
if (baseElem.namespaceURI == kSVGNSURI) {
s.setAttributeNS(kXLINKNSURI, 'href', uri);
} else {
s.setAttribute('src', uri);
}
s.setAttribute("type", "application/x-javascript");
baseElem.parentNode.appendChild(s);
} else {
// HTML, XHTML
/*
DOM can not be used here because Safari does
deferred loading of scripts unless they are
in the document or inserted with document.write
This is not XHTML compliant. If you want XHTML
compliance then you must use the packed version of MochiKit
or include each script individually (basically unroll
these document.write calls into your XHTML source)
*/
document.write('<' + baseElem.nodeName + ' src="' + uri +
'" type="text/javascript"></script>');
}
};
})();
}

View file

@ -0,0 +1,115 @@
/***
MochiKit.MockDOM 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
if (typeof(MochiKit) == "undefined") {
MochiKit = {};
}
if (typeof(MochiKit.MockDOM) == "undefined") {
MochiKit.MockDOM = {};
}
MochiKit.MockDOM.NAME = "MochiKit.MockDOM";
MochiKit.MockDOM.VERSION = "1.4.2";
MochiKit.MockDOM.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
/** @id MochiKit.MockDOM.toString */
MochiKit.MockDOM.toString = function () {
return this.__repr__();
};
/** @id MochiKit.MockDOM.createDocument */
MochiKit.MockDOM.createDocument = function () {
var doc = new MochiKit.MockDOM.MockElement("DOCUMENT");
doc.body = doc.createElement("BODY");
doc.appendChild(doc.body);
return doc;
};
/** @id MochiKit.MockDOM.MockElement */
MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) {
this.tagName = this.nodeName = name.toUpperCase();
this.ownerDocument = ownerDocument || null;
if (name == "DOCUMENT") {
this.nodeType = 9;
this.childNodes = [];
} else if (typeof(data) == "string") {
this.nodeValue = data;
this.nodeType = 3;
} else {
this.nodeType = 1;
this.childNodes = [];
}
if (name.substring(0, 1) == "<") {
var nameattr = name.substring(
name.indexOf('"') + 1, name.lastIndexOf('"'));
name = name.substring(1, name.indexOf(" "));
this.tagName = this.nodeName = name.toUpperCase();
this.setAttribute("name", nameattr);
}
};
MochiKit.MockDOM.MockElement.prototype = {
/** @id MochiKit.MockDOM.MockElement.prototype.createElement */
createElement: function (tagName) {
return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument);
},
/** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */
createTextNode: function (text) {
return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument);
},
/** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */
setAttribute: function (name, value) {
this[name] = value;
},
/** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */
getAttribute: function (name) {
return this[name];
},
/** @id MochiKit.MockDOM.MockElement.prototype.appendChild */
appendChild: function (child) {
this.childNodes.push(child);
},
/** @id MochiKit.MockDOM.MockElement.prototype.toString */
toString: function () {
return "MockElement(" + this.tagName + ")";
},
/** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */
getElementsByTagName: function (tagName) {
var foundElements = [];
MochiKit.Base.nodeWalk(this, function(node){
if (tagName == '*' || tagName == node.tagName) {
foundElements.push(node);
return node.childNodes;
}
});
return foundElements;
}
};
/** @id MochiKit.MockDOM.EXPORT_OK */
MochiKit.MockDOM.EXPORT_OK = [
"mockElement",
"createDocument"
];
/** @id MochiKit.MockDOM.EXPORT */
MochiKit.MockDOM.EXPORT = [
"document"
];
MochiKit.MockDOM.__new__ = function () {
this.document = this.createDocument();
};
MochiKit.MockDOM.__new__();

View file

@ -0,0 +1,236 @@
/***
MochiKit.Position 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005-2006 Bob Ippolito and others. All rights Reserved.
***/
MochiKit.Base._deps('Position', ['Base', 'DOM', 'Style']);
MochiKit.Position.NAME = 'MochiKit.Position';
MochiKit.Position.VERSION = '1.4.2';
MochiKit.Position.__repr__ = function () {
return '[' + this.NAME + ' ' + this.VERSION + ']';
};
MochiKit.Position.toString = function () {
return this.__repr__();
};
MochiKit.Position.EXPORT_OK = [];
MochiKit.Position.EXPORT = [
];
MochiKit.Base.update(MochiKit.Position, {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
// scrollable elements
includeScrollOffsets: false,
/** @id MochiKit.Position.prepare */
prepare: function () {
var deltaX = window.pageXOffset
|| document.documentElement.scrollLeft
|| document.body.scrollLeft
|| 0;
var deltaY = window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop
|| 0;
this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
},
/** @id MochiKit.Position.cumulativeOffset */
cumulativeOffset: function (element) {
var valueT = 0;
var valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
return new MochiKit.Style.Coordinates(valueL, valueT);
},
/** @id MochiKit.Position.realOffset */
realOffset: function (element) {
var valueT = 0;
var valueL = 0;
do {
valueT += element.scrollTop || 0;
valueL += element.scrollLeft || 0;
element = element.parentNode;
} while (element);
return new MochiKit.Style.Coordinates(valueL, valueT);
},
/** @id MochiKit.Position.within */
within: function (element, x, y) {
if (this.includeScrollOffsets) {
return this.withinIncludingScrolloffsets(element, x, y);
}
this.xcomp = x;
this.ycomp = y;
this.offset = this.cumulativeOffset(element);
if (element.style.position == "fixed") {
this.offset.x += this.windowOffset.x;
this.offset.y += this.windowOffset.y;
}
return (y >= this.offset.y &&
y < this.offset.y + element.offsetHeight &&
x >= this.offset.x &&
x < this.offset.x + element.offsetWidth);
},
/** @id MochiKit.Position.withinIncludingScrolloffsets */
withinIncludingScrolloffsets: function (element, x, y) {
var offsetcache = this.realOffset(element);
this.xcomp = x + offsetcache.x - this.windowOffset.x;
this.ycomp = y + offsetcache.y - this.windowOffset.y;
this.offset = this.cumulativeOffset(element);
return (this.ycomp >= this.offset.y &&
this.ycomp < this.offset.y + element.offsetHeight &&
this.xcomp >= this.offset.x &&
this.xcomp < this.offset.x + element.offsetWidth);
},
// within must be called directly before
/** @id MochiKit.Position.overlap */
overlap: function (mode, element) {
if (!mode) {
return 0;
}
if (mode == 'vertical') {
return ((this.offset.y + element.offsetHeight) - this.ycomp) /
element.offsetHeight;
}
if (mode == 'horizontal') {
return ((this.offset.x + element.offsetWidth) - this.xcomp) /
element.offsetWidth;
}
},
/** @id MochiKit.Position.absolutize */
absolutize: function (element) {
element = MochiKit.DOM.getElement(element);
if (element.style.position == 'absolute') {
return;
}
MochiKit.Position.prepare();
var offsets = MochiKit.Position.positionedOffset(element);
var width = element.clientWidth;
var height = element.clientHeight;
var oldStyle = {
'position': element.style.position,
'left': offsets.x - parseFloat(element.style.left || 0),
'top': offsets.y - parseFloat(element.style.top || 0),
'width': element.style.width,
'height': element.style.height
};
element.style.position = 'absolute';
element.style.top = offsets.y + 'px';
element.style.left = offsets.x + 'px';
element.style.width = width + 'px';
element.style.height = height + 'px';
return oldStyle;
},
/** @id MochiKit.Position.positionedOffset */
positionedOffset: function (element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
if (element) {
p = MochiKit.Style.getStyle(element, 'position');
if (p == 'relative' || p == 'absolute') {
break;
}
}
} while (element);
return new MochiKit.Style.Coordinates(valueL, valueT);
},
/** @id MochiKit.Position.relativize */
relativize: function (element, oldPos) {
element = MochiKit.DOM.getElement(element);
if (element.style.position == 'relative') {
return;
}
MochiKit.Position.prepare();
var top = parseFloat(element.style.top || 0) -
(oldPos['top'] || 0);
var left = parseFloat(element.style.left || 0) -
(oldPos['left'] || 0);
element.style.position = oldPos['position'];
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.width = oldPos['width'];
element.style.height = oldPos['height'];
},
/** @id MochiKit.Position.clone */
clone: function (source, target) {
source = MochiKit.DOM.getElement(source);
target = MochiKit.DOM.getElement(target);
target.style.position = 'absolute';
var offsets = this.cumulativeOffset(source);
target.style.top = offsets.y + 'px';
target.style.left = offsets.x + 'px';
target.style.width = source.offsetWidth + 'px';
target.style.height = source.offsetHeight + 'px';
},
/** @id MochiKit.Position.page */
page: function (forElement) {
var valueT = 0;
var valueL = 0;
var element = forElement;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
// Safari fix
if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
break;
}
} while (element = element.offsetParent);
element = forElement;
do {
valueT -= element.scrollTop || 0;
valueL -= element.scrollLeft || 0;
} while (element = element.parentNode);
return new MochiKit.Style.Coordinates(valueL, valueT);
}
});
MochiKit.Position.__new__ = function (win) {
var m = MochiKit.Base;
this.EXPORT_TAGS = {
':common': this.EXPORT,
':all': m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
};
MochiKit.Position.__new__(this);
MochiKit.Base._exportSymbols(this, MochiKit.Position);

View file

@ -0,0 +1,415 @@
/***
MochiKit.Selector 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito and others. All rights Reserved.
***/
MochiKit.Base._deps('Selector', ['Base', 'DOM', 'Iter']);
MochiKit.Selector.NAME = "MochiKit.Selector";
MochiKit.Selector.VERSION = "1.4.2";
MochiKit.Selector.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Selector.toString = function () {
return this.__repr__();
};
MochiKit.Selector.EXPORT = [
"Selector",
"findChildElements",
"findDocElements",
"$$"
];
MochiKit.Selector.EXPORT_OK = [
];
MochiKit.Selector.Selector = function (expression) {
this.params = {classNames: [], pseudoClassNames: []};
this.expression = expression.toString().replace(/(^\s+|\s+$)/g, '');
this.parseExpression();
this.compileMatcher();
};
MochiKit.Selector.Selector.prototype = {
/***
Selector class: convenient object to make CSS selections.
***/
__class__: MochiKit.Selector.Selector,
/** @id MochiKit.Selector.Selector.prototype.parseExpression */
parseExpression: function () {
function abort(message) {
throw 'Parse error in selector: ' + message;
}
if (this.expression == '') {
abort('empty expression');
}
var repr = MochiKit.Base.repr;
var params = this.params;
var expr = this.expression;
var match, modifier, clause, rest;
while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
params.attributes = params.attributes || [];
params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
expr = match[1];
}
if (expr == '*') {
return this.params.wildcard = true;
}
while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) {
modifier = match[1];
clause = match[2];
rest = match[3];
switch (modifier) {
case '#':
params.id = clause;
break;
case '.':
params.classNames.push(clause);
break;
case ':':
params.pseudoClassNames.push(clause);
break;
case '':
case undefined:
params.tagName = clause.toUpperCase();
break;
default:
abort(repr(expr));
}
expr = rest;
}
if (expr.length > 0) {
abort(repr(expr));
}
},
/** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */
buildMatchExpression: function () {
var repr = MochiKit.Base.repr;
var params = this.params;
var conditions = [];
var clause, i;
function childElements(element) {
return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)";
}
if (params.wildcard) {
conditions.push('true');
}
if (clause = params.id) {
conditions.push('element.id == ' + repr(clause));
}
if (clause = params.tagName) {
conditions.push('element.tagName.toUpperCase() == ' + repr(clause));
}
if ((clause = params.classNames).length > 0) {
for (i = 0; i < clause.length; i++) {
conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')');
}
}
if ((clause = params.pseudoClassNames).length > 0) {
for (i = 0; i < clause.length; i++) {
var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/);
var pseudoClass = match[1];
var pseudoClassArgument = match[2];
switch (pseudoClass) {
case 'root':
conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break;
case 'nth-child':
case 'nth-last-child':
case 'nth-of-type':
case 'nth-last-of-type':
match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
if (!match) {
throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument;
}
var a, b;
if (match[0] == 'odd') {
a = 2;
b = 1;
} else if (match[0] == 'even') {
a = 2;
b = 0;
} else {
a = match[2] && parseInt(match) || null;
b = parseInt(match[3]);
}
conditions.push('this.nthChild(element,' + a + ',' + b
+ ',' + !!pseudoClass.match('^nth-last') // Reverse
+ ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName
+ ')');
break;
case 'first-child':
conditions.push('this.nthChild(element, null, 1)');
break;
case 'last-child':
conditions.push('this.nthChild(element, null, 1, true)');
break;
case 'first-of-type':
conditions.push('this.nthChild(element, null, 1, false, true)');
break;
case 'last-of-type':
conditions.push('this.nthChild(element, null, 1, true, true)');
break;
case 'only-child':
conditions.push(childElements('element.parentNode') + '.length == 1');
break;
case 'only-of-type':
conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1');
break;
case 'empty':
conditions.push('element.childNodes.length == 0');
break;
case 'enabled':
conditions.push('(this.isUIElement(element) && element.disabled === false)');
break;
case 'disabled':
conditions.push('(this.isUIElement(element) && element.disabled === true)');
break;
case 'checked':
conditions.push('(this.isUIElement(element) && element.checked === true)');
break;
case 'not':
var subselector = new MochiKit.Selector.Selector(pseudoClassArgument);
conditions.push('!( ' + subselector.buildMatchExpression() + ')')
break;
}
}
}
if (clause = params.attributes) {
MochiKit.Base.map(function (attribute) {
var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')';
var splitValueBy = function (delimiter) {
return value + '.split(' + repr(delimiter) + ')';
}
conditions.push(value + ' != null');
switch (attribute.operator) {
case '=':
conditions.push(value + ' == ' + repr(attribute.value));
break;
case '~=':
conditions.push('MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1');
break;
case '^=':
conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value));
break;
case '$=':
conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value));
break;
case '*=':
conditions.push(value + '.match(' + repr(attribute.value) + ')');
break;
case '|=':
conditions.push(splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase()));
break;
case '!=':
conditions.push(value + ' != ' + repr(attribute.value));
break;
case '':
case undefined:
// Condition already added above
break;
default:
throw 'Unknown operator ' + attribute.operator + ' in selector';
}
}, clause);
}
return conditions.join(' && ');
},
/** @id MochiKit.Selector.Selector.prototype.compileMatcher */
compileMatcher: function () {
var code = 'return (!element.tagName) ? false : ' +
this.buildMatchExpression() + ';';
this.match = new Function('element', code);
},
/** @id MochiKit.Selector.Selector.prototype.nthChild */
nthChild: function (element, a, b, reverse, sametag){
var siblings = MochiKit.Base.filter(function (node) {
return node.nodeType == 1;
}, element.parentNode.childNodes);
if (sametag) {
siblings = MochiKit.Base.filter(function (node) {
return node.tagName == element.tagName;
}, siblings);
}
if (reverse) {
siblings = MochiKit.Iter.reversed(siblings);
}
if (a) {
var actualIndex = MochiKit.Base.findIdentical(siblings, element);
return ((actualIndex + 1 - b) / a) % 1 == 0;
} else {
return b == MochiKit.Base.findIdentical(siblings, element) + 1;
}
},
/** @id MochiKit.Selector.Selector.prototype.isUIElement */
isUIElement: function (element) {
return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'],
element.tagName.toLowerCase()) > -1;
},
/** @id MochiKit.Selector.Selector.prototype.findElements */
findElements: function (scope, axis) {
var element;
if (axis == undefined) {
axis = "";
}
function inScope(element, scope) {
if (axis == "") {
return MochiKit.DOM.isChildNode(element, scope);
} else if (axis == ">") {
return element.parentNode === scope;
} else if (axis == "+") {
return element === nextSiblingElement(scope);
} else if (axis == "~") {
var sibling = scope;
while (sibling = nextSiblingElement(sibling)) {
if (element === sibling) {
return true;
}
}
return false;
} else {
throw "Invalid axis: " + axis;
}
}
if (element = MochiKit.DOM.getElement(this.params.id)) {
if (this.match(element)) {
if (!scope || inScope(element, scope)) {
return [element];
}
}
}
function nextSiblingElement(node) {
node = node.nextSibling;
while (node && node.nodeType != 1) {
node = node.nextSibling;
}
return node;
}
if (axis == "") {
scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*');
} else if (axis == ">") {
if (!scope) {
throw "> combinator not allowed without preceding expression";
}
scope = MochiKit.Base.filter(function (node) {
return node.nodeType == 1;
}, scope.childNodes);
} else if (axis == "+") {
if (!scope) {
throw "+ combinator not allowed without preceding expression";
}
scope = nextSiblingElement(scope) && [nextSiblingElement(scope)];
} else if (axis == "~") {
if (!scope) {
throw "~ combinator not allowed without preceding expression";
}
var newscope = [];
while (nextSiblingElement(scope)) {
scope = nextSiblingElement(scope);
newscope.push(scope);
}
scope = newscope;
}
if (!scope) {
return [];
}
var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) {
return this.match(scopeElt);
}, this), scope);
return results;
},
/** @id MochiKit.Selector.Selector.prototype.repr */
repr: function () {
return 'Selector(' + this.expression + ')';
},
toString: MochiKit.Base.forwardCall("repr")
};
MochiKit.Base.update(MochiKit.Selector, {
/** @id MochiKit.Selector.findChildElements */
findChildElements: function (element, expressions) {
var uniq = function(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (MochiKit.Base.findIdentical(res, arr[i]) < 0) {
res.push(arr[i]);
}
}
return res;
};
return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) {
var nextScope = "";
var reducer = function (results, expr) {
if (match = expr.match(/^[>+~]$/)) {
nextScope = match[0];
return results;
} else {
var selector = new MochiKit.Selector.Selector(expr);
var elements = MochiKit.Iter.reduce(function (elements, result) {
return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope));
}, results, []);
nextScope = "";
return elements;
}
};
var exprs = expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/);
return uniq(MochiKit.Iter.reduce(reducer, exprs, [null]));
}, expressions));
},
findDocElements: function () {
return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments);
},
__new__: function () {
var m = MochiKit.Base;
this.$$ = this.findDocElements;
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
}
});
MochiKit.Selector.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Selector);

View file

@ -0,0 +1,897 @@
/***
MochiKit.Signal 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('Signal', ['Base', 'DOM', 'Style']);
MochiKit.Signal.NAME = 'MochiKit.Signal';
MochiKit.Signal.VERSION = '1.4.2';
MochiKit.Signal._observers = [];
/** @id MochiKit.Signal.Event */
MochiKit.Signal.Event = function (src, e) {
this._event = e || window.event;
this._src = src;
};
MochiKit.Base.update(MochiKit.Signal.Event.prototype, {
__repr__: function () {
var repr = MochiKit.Base.repr;
var str = '{event(): ' + repr(this.event()) +
', src(): ' + repr(this.src()) +
', type(): ' + repr(this.type()) +
', target(): ' + repr(this.target());
if (this.type() &&
this.type().indexOf('key') === 0 ||
this.type().indexOf('mouse') === 0 ||
this.type().indexOf('click') != -1 ||
this.type() == 'contextmenu') {
str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) +
', ctrl: ' + repr(this.modifier().ctrl) +
', meta: ' + repr(this.modifier().meta) +
', shift: ' + repr(this.modifier().shift) +
', any: ' + repr(this.modifier().any) + '}';
}
if (this.type() && this.type().indexOf('key') === 0) {
str += ', key(): {code: ' + repr(this.key().code) +
', string: ' + repr(this.key().string) + '}';
}
if (this.type() && (
this.type().indexOf('mouse') === 0 ||
this.type().indexOf('click') != -1 ||
this.type() == 'contextmenu')) {
str += ', mouse(): {page: ' + repr(this.mouse().page) +
', client: ' + repr(this.mouse().client);
if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
str += ', button: {left: ' + repr(this.mouse().button.left) +
', middle: ' + repr(this.mouse().button.middle) +
', right: ' + repr(this.mouse().button.right) + '}';
}
if (this.type() == 'mousewheel') {
str += ', wheel: ' + repr(this.mouse().wheel);
}
str += '}';
}
if (this.type() == 'mouseover' || this.type() == 'mouseout' ||
this.type() == 'mouseenter' || this.type() == 'mouseleave') {
str += ', relatedTarget(): ' + repr(this.relatedTarget());
}
str += '}';
return str;
},
/** @id MochiKit.Signal.Event.prototype.toString */
toString: function () {
return this.__repr__();
},
/** @id MochiKit.Signal.Event.prototype.src */
src: function () {
return this._src;
},
/** @id MochiKit.Signal.Event.prototype.event */
event: function () {
return this._event;
},
/** @id MochiKit.Signal.Event.prototype.type */
type: function () {
if (this._event.type === "DOMMouseScroll") {
return "mousewheel";
} else {
return this._event.type || undefined;
}
},
/** @id MochiKit.Signal.Event.prototype.target */
target: function () {
return this._event.target || this._event.srcElement;
},
_relatedTarget: null,
/** @id MochiKit.Signal.Event.prototype.relatedTarget */
relatedTarget: function () {
if (this._relatedTarget !== null) {
return this._relatedTarget;
}
var elem = null;
if (this.type() == 'mouseover' || this.type() == 'mouseenter') {
elem = (this._event.relatedTarget ||
this._event.fromElement);
} else if (this.type() == 'mouseout' || this.type() == 'mouseleave') {
elem = (this._event.relatedTarget ||
this._event.toElement);
}
try {
if (elem !== null && elem.nodeType !== null) {
this._relatedTarget = elem;
return elem;
}
} catch (ignore) {
// Firefox 3 throws a permission denied error when accessing
// any property on XUL elements (e.g. scrollbars)...
}
return undefined;
},
_modifier: null,
/** @id MochiKit.Signal.Event.prototype.modifier */
modifier: function () {
if (this._modifier !== null) {
return this._modifier;
}
var m = {};
m.alt = this._event.altKey;
m.ctrl = this._event.ctrlKey;
m.meta = this._event.metaKey || false; // IE and Opera punt here
m.shift = this._event.shiftKey;
m.any = m.alt || m.ctrl || m.shift || m.meta;
this._modifier = m;
return m;
},
_key: null,
/** @id MochiKit.Signal.Event.prototype.key */
key: function () {
if (this._key !== null) {
return this._key;
}
var k = {};
if (this.type() && this.type().indexOf('key') === 0) {
/*
If you're looking for a special key, look for it in keydown or
keyup, but never keypress. If you're looking for a Unicode
chracter, look for it with keypress, but never keyup or
keydown.
Notes:
FF key event behavior:
key event charCode keyCode
DOWN ku,kd 0 40
DOWN kp 0 40
ESC ku,kd 0 27
ESC kp 0 27
a ku,kd 0 65
a kp 97 0
shift+a ku,kd 0 65
shift+a kp 65 0
1 ku,kd 0 49
1 kp 49 0
shift+1 ku,kd 0 0
shift+1 kp 33 0
IE key event behavior:
(IE doesn't fire keypress events for special keys.)
key event keyCode
DOWN ku,kd 40
DOWN kp undefined
ESC ku,kd 27
ESC kp 27
a ku,kd 65
a kp 97
shift+a ku,kd 65
shift+a kp 65
1 ku,kd 49
1 kp 49
shift+1 ku,kd 49
shift+1 kp 33
Safari key event behavior:
(Safari sets charCode and keyCode to something crazy for
special keys.)
key event charCode keyCode
DOWN ku,kd 63233 40
DOWN kp 63233 63233
ESC ku,kd 27 27
ESC kp 27 27
a ku,kd 97 65
a kp 97 97
shift+a ku,kd 65 65
shift+a kp 65 65
1 ku,kd 49 49
1 kp 49 49
shift+1 ku,kd 33 49
shift+1 kp 33 33
*/
/* look for special keys here */
if (this.type() == 'keydown' || this.type() == 'keyup') {
k.code = this._event.keyCode;
k.string = (MochiKit.Signal._specialKeys[k.code] ||
'KEY_UNKNOWN');
this._key = k;
return k;
/* look for characters here */
} else if (this.type() == 'keypress') {
/*
Special key behavior:
IE: does not fire keypress events for special keys
FF: sets charCode to 0, and sets the correct keyCode
Safari: sets keyCode and charCode to something stupid
*/
k.code = 0;
k.string = '';
if (typeof(this._event.charCode) != 'undefined' &&
this._event.charCode !== 0 &&
!MochiKit.Signal._specialMacKeys[this._event.charCode]) {
k.code = this._event.charCode;
k.string = String.fromCharCode(k.code);
} else if (this._event.keyCode &&
typeof(this._event.charCode) == 'undefined') { // IE
k.code = this._event.keyCode;
k.string = String.fromCharCode(k.code);
}
this._key = k;
return k;
}
}
return undefined;
},
_mouse: null,
/** @id MochiKit.Signal.Event.prototype.mouse */
mouse: function () {
if (this._mouse !== null) {
return this._mouse;
}
var m = {};
var e = this._event;
if (this.type() && (
this.type().indexOf('mouse') === 0 ||
this.type().indexOf('click') != -1 ||
this.type() == 'contextmenu')) {
m.client = new MochiKit.Style.Coordinates(0, 0);
if (e.clientX || e.clientY) {
m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX;
m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY;
}
m.page = new MochiKit.Style.Coordinates(0, 0);
if (e.pageX || e.pageY) {
m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
} else {
/*
The IE shortcut can be off by two. We fix it. See:
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
This is similar to the method used in
MochiKit.Style.getElementPosition().
*/
var de = MochiKit.DOM._document.documentElement;
var b = MochiKit.DOM._document.body;
m.page.x = e.clientX +
(de.scrollLeft || b.scrollLeft) -
(de.clientLeft || 0);
m.page.y = e.clientY +
(de.scrollTop || b.scrollTop) -
(de.clientTop || 0);
}
if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
m.button = {};
m.button.left = false;
m.button.right = false;
m.button.middle = false;
/* we could check e.button, but which is more consistent */
if (e.which) {
m.button.left = (e.which == 1);
m.button.middle = (e.which == 2);
m.button.right = (e.which == 3);
/*
Mac browsers and right click:
- Safari doesn't fire any click events on a right
click:
http://bugs.webkit.org/show_bug.cgi?id=6595
- Firefox fires the event, and sets ctrlKey = true
- Opera fires the event, and sets metaKey = true
oncontextmenu is fired on right clicks between
browsers and across platforms.
*/
} else {
m.button.left = !!(e.button & 1);
m.button.right = !!(e.button & 2);
m.button.middle = !!(e.button & 4);
}
}
if (this.type() == 'mousewheel') {
m.wheel = new MochiKit.Style.Coordinates(0, 0);
if (e.wheelDeltaX || e.wheelDeltaY) {
m.wheel.x = e.wheelDeltaX / -40 || 0;
m.wheel.y = e.wheelDeltaY / -40 || 0;
} else if (e.wheelDelta) {
m.wheel.y = e.wheelDelta / -40;
} else {
m.wheel.y = e.detail || 0;
}
}
this._mouse = m;
return m;
}
return undefined;
},
/** @id MochiKit.Signal.Event.prototype.stop */
stop: function () {
this.stopPropagation();
this.preventDefault();
},
/** @id MochiKit.Signal.Event.prototype.stopPropagation */
stopPropagation: function () {
if (this._event.stopPropagation) {
this._event.stopPropagation();
} else {
this._event.cancelBubble = true;
}
},
/** @id MochiKit.Signal.Event.prototype.preventDefault */
preventDefault: function () {
if (this._event.preventDefault) {
this._event.preventDefault();
} else if (this._confirmUnload === null) {
this._event.returnValue = false;
}
},
_confirmUnload: null,
/** @id MochiKit.Signal.Event.prototype.confirmUnload */
confirmUnload: function (msg) {
if (this.type() == 'beforeunload') {
this._confirmUnload = msg;
this._event.returnValue = msg;
}
}
});
/* Safari sets keyCode to these special values onkeypress. */
MochiKit.Signal._specialMacKeys = {
3: 'KEY_ENTER',
63289: 'KEY_NUM_PAD_CLEAR',
63276: 'KEY_PAGE_UP',
63277: 'KEY_PAGE_DOWN',
63275: 'KEY_END',
63273: 'KEY_HOME',
63234: 'KEY_ARROW_LEFT',
63232: 'KEY_ARROW_UP',
63235: 'KEY_ARROW_RIGHT',
63233: 'KEY_ARROW_DOWN',
63302: 'KEY_INSERT',
63272: 'KEY_DELETE'
};
/* for KEY_F1 - KEY_F12 */
(function () {
var _specialMacKeys = MochiKit.Signal._specialMacKeys;
for (i = 63236; i <= 63242; i++) {
// no F0
_specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
}
})();
/* Standard keyboard key codes. */
MochiKit.Signal._specialKeys = {
8: 'KEY_BACKSPACE',
9: 'KEY_TAB',
12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
13: 'KEY_ENTER',
16: 'KEY_SHIFT',
17: 'KEY_CTRL',
18: 'KEY_ALT',
19: 'KEY_PAUSE',
20: 'KEY_CAPS_LOCK',
27: 'KEY_ESCAPE',
32: 'KEY_SPACEBAR',
33: 'KEY_PAGE_UP',
34: 'KEY_PAGE_DOWN',
35: 'KEY_END',
36: 'KEY_HOME',
37: 'KEY_ARROW_LEFT',
38: 'KEY_ARROW_UP',
39: 'KEY_ARROW_RIGHT',
40: 'KEY_ARROW_DOWN',
44: 'KEY_PRINT_SCREEN',
45: 'KEY_INSERT',
46: 'KEY_DELETE',
59: 'KEY_SEMICOLON', // weird, for Safari and IE only
91: 'KEY_WINDOWS_LEFT',
92: 'KEY_WINDOWS_RIGHT',
93: 'KEY_SELECT',
106: 'KEY_NUM_PAD_ASTERISK',
107: 'KEY_NUM_PAD_PLUS_SIGN',
109: 'KEY_NUM_PAD_HYPHEN-MINUS',
110: 'KEY_NUM_PAD_FULL_STOP',
111: 'KEY_NUM_PAD_SOLIDUS',
144: 'KEY_NUM_LOCK',
145: 'KEY_SCROLL_LOCK',
186: 'KEY_SEMICOLON',
187: 'KEY_EQUALS_SIGN',
188: 'KEY_COMMA',
189: 'KEY_HYPHEN-MINUS',
190: 'KEY_FULL_STOP',
191: 'KEY_SOLIDUS',
192: 'KEY_GRAVE_ACCENT',
219: 'KEY_LEFT_SQUARE_BRACKET',
220: 'KEY_REVERSE_SOLIDUS',
221: 'KEY_RIGHT_SQUARE_BRACKET',
222: 'KEY_APOSTROPHE'
// undefined: 'KEY_UNKNOWN'
};
(function () {
/* for KEY_0 - KEY_9 */
var _specialKeys = MochiKit.Signal._specialKeys;
for (var i = 48; i <= 57; i++) {
_specialKeys[i] = 'KEY_' + (i - 48);
}
/* for KEY_A - KEY_Z */
for (i = 65; i <= 90; i++) {
_specialKeys[i] = 'KEY_' + String.fromCharCode(i);
}
/* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
for (i = 96; i <= 105; i++) {
_specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
}
/* for KEY_F1 - KEY_F12 */
for (i = 112; i <= 123; i++) {
// no F0
_specialKeys[i] = 'KEY_F' + (i - 112 + 1);
}
})();
/* Internal object to keep track of created signals. */
MochiKit.Signal.Ident = function (ident) {
this.source = ident.source;
this.signal = ident.signal;
this.listener = ident.listener;
this.isDOM = ident.isDOM;
this.objOrFunc = ident.objOrFunc;
this.funcOrStr = ident.funcOrStr;
this.connected = ident.connected;
};
MochiKit.Signal.Ident.prototype = {};
MochiKit.Base.update(MochiKit.Signal, {
__repr__: function () {
return '[' + this.NAME + ' ' + this.VERSION + ']';
},
toString: function () {
return this.__repr__();
},
_unloadCache: function () {
var self = MochiKit.Signal;
var observers = self._observers;
for (var i = 0; i < observers.length; i++) {
if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') {
self._disconnect(observers[i]);
}
}
},
_listener: function (src, sig, func, obj, isDOM) {
var self = MochiKit.Signal;
var E = self.Event;
if (!isDOM) {
/* We don't want to re-bind already bound methods */
if (typeof(func.im_self) == 'undefined') {
return MochiKit.Base.bindLate(func, obj);
} else {
return func;
}
}
obj = obj || src;
if (typeof(func) == "string") {
if (sig === 'onload' || sig === 'onunload') {
return function (nativeEvent) {
obj[func].apply(obj, [new E(src, nativeEvent)]);
var ident = new MochiKit.Signal.Ident({
source: src, signal: sig, objOrFunc: obj, funcOrStr: func});
MochiKit.Signal._disconnect(ident);
};
} else {
return function (nativeEvent) {
obj[func].apply(obj, [new E(src, nativeEvent)]);
};
}
} else {
if (sig === 'onload' || sig === 'onunload') {
return function (nativeEvent) {
func.apply(obj, [new E(src, nativeEvent)]);
var ident = new MochiKit.Signal.Ident({
source: src, signal: sig, objOrFunc: func});
MochiKit.Signal._disconnect(ident);
};
} else {
return function (nativeEvent) {
func.apply(obj, [new E(src, nativeEvent)]);
};
}
}
},
_browserAlreadyHasMouseEnterAndLeave: function () {
return /MSIE/.test(navigator.userAgent);
},
_browserLacksMouseWheelEvent: function () {
return /Gecko\//.test(navigator.userAgent);
},
_mouseEnterListener: function (src, sig, func, obj) {
var E = MochiKit.Signal.Event;
return function (nativeEvent) {
var e = new E(src, nativeEvent);
try {
e.relatedTarget().nodeName;
} catch (err) {
/* probably hit a permission denied error; possibly one of
* firefox's screwy anonymous DIVs inside an input element.
* Allow this event to propogate up.
*/
return;
}
e.stop();
if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) {
/* We've moved between our node and a child. Ignore. */
return;
}
e.type = function () { return sig; };
if (typeof(func) == "string") {
return obj[func].apply(obj, [e]);
} else {
return func.apply(obj, [e]);
}
};
},
_getDestPair: function (objOrFunc, funcOrStr) {
var obj = null;
var func = null;
if (typeof(funcOrStr) != 'undefined') {
obj = objOrFunc;
func = funcOrStr;
if (typeof(funcOrStr) == 'string') {
if (typeof(objOrFunc[funcOrStr]) != "function") {
throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
}
} else if (typeof(funcOrStr) != 'function') {
throw new Error("'funcOrStr' must be a function or string");
}
} else if (typeof(objOrFunc) != "function") {
throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
} else {
func = objOrFunc;
}
return [obj, func];
},
/** @id MochiKit.Signal.connect */
connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
src = MochiKit.DOM.getElement(src);
var self = MochiKit.Signal;
if (typeof(sig) != 'string') {
throw new Error("'sig' must be a string");
}
var destPair = self._getDestPair(objOrFunc, funcOrStr);
var obj = destPair[0];
var func = destPair[1];
if (typeof(obj) == 'undefined' || obj === null) {
obj = src;
}
var isDOM = !!(src.addEventListener || src.attachEvent);
if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave")
&& !self._browserAlreadyHasMouseEnterAndLeave()) {
var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
if (sig === "onmouseenter") {
sig = "onmouseover";
} else {
sig = "onmouseout";
}
} else if (isDOM && sig == "onmousewheel" && self._browserLacksMouseWheelEvent()) {
var listener = self._listener(src, sig, func, obj, isDOM);
sig = "onDOMMouseScroll";
} else {
var listener = self._listener(src, sig, func, obj, isDOM);
}
if (src.addEventListener) {
src.addEventListener(sig.substr(2), listener, false);
} else if (src.attachEvent) {
src.attachEvent(sig, listener); // useCapture unsupported
}
var ident = new MochiKit.Signal.Ident({
source: src,
signal: sig,
listener: listener,
isDOM: isDOM,
objOrFunc: objOrFunc,
funcOrStr: funcOrStr,
connected: true
});
self._observers.push(ident);
if (!isDOM && typeof(src.__connect__) == 'function') {
var args = MochiKit.Base.extend([ident], arguments, 1);
src.__connect__.apply(src, args);
}
return ident;
},
_disconnect: function (ident) {
// already disconnected
if (!ident.connected) {
return;
}
ident.connected = false;
var src = ident.source;
var sig = ident.signal;
var listener = ident.listener;
// check isDOM
if (!ident.isDOM) {
if (typeof(src.__disconnect__) == 'function') {
src.__disconnect__(ident, sig, ident.objOrFunc, ident.funcOrStr);
}
return;
}
if (src.removeEventListener) {
src.removeEventListener(sig.substr(2), listener, false);
} else if (src.detachEvent) {
src.detachEvent(sig, listener); // useCapture unsupported
} else {
throw new Error("'src' must be a DOM element");
}
},
/** @id MochiKit.Signal.disconnect */
disconnect: function (ident) {
var self = MochiKit.Signal;
var observers = self._observers;
var m = MochiKit.Base;
if (arguments.length > 1) {
// compatibility API
var src = MochiKit.DOM.getElement(arguments[0]);
var sig = arguments[1];
var obj = arguments[2];
var func = arguments[3];
for (var i = observers.length - 1; i >= 0; i--) {
var o = observers[i];
if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) {
self._disconnect(o);
if (!self._lock) {
observers.splice(i, 1);
} else {
self._dirty = true;
}
return true;
}
}
} else {
var idx = m.findIdentical(observers, ident);
if (idx >= 0) {
self._disconnect(ident);
if (!self._lock) {
observers.splice(idx, 1);
} else {
self._dirty = true;
}
return true;
}
}
return false;
},
/** @id MochiKit.Signal.disconnectAllTo */
disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) {
var self = MochiKit.Signal;
var observers = self._observers;
var disconnect = self._disconnect;
var locked = self._lock;
var dirty = self._dirty;
if (typeof(funcOrStr) === 'undefined') {
funcOrStr = null;
}
for (var i = observers.length - 1; i >= 0; i--) {
var ident = observers[i];
if (ident.objOrFunc === objOrFunc &&
(funcOrStr === null || ident.funcOrStr === funcOrStr)) {
disconnect(ident);
if (locked) {
dirty = true;
} else {
observers.splice(i, 1);
}
}
}
self._dirty = dirty;
},
/** @id MochiKit.Signal.disconnectAll */
disconnectAll: function (src/* optional */, sig) {
src = MochiKit.DOM.getElement(src);
var m = MochiKit.Base;
var signals = m.flattenArguments(m.extend(null, arguments, 1));
var self = MochiKit.Signal;
var disconnect = self._disconnect;
var observers = self._observers;
var i, ident;
var locked = self._lock;
var dirty = self._dirty;
if (signals.length === 0) {
// disconnect all
for (i = observers.length - 1; i >= 0; i--) {
ident = observers[i];
if (ident.source === src) {
disconnect(ident);
if (!locked) {
observers.splice(i, 1);
} else {
dirty = true;
}
}
}
} else {
var sigs = {};
for (i = 0; i < signals.length; i++) {
sigs[signals[i]] = true;
}
for (i = observers.length - 1; i >= 0; i--) {
ident = observers[i];
if (ident.source === src && ident.signal in sigs) {
disconnect(ident);
if (!locked) {
observers.splice(i, 1);
} else {
dirty = true;
}
}
}
}
self._dirty = dirty;
},
/** @id MochiKit.Signal.signal */
signal: function (src, sig) {
var self = MochiKit.Signal;
var observers = self._observers;
src = MochiKit.DOM.getElement(src);
var args = MochiKit.Base.extend(null, arguments, 2);
var errors = [];
self._lock = true;
for (var i = 0; i < observers.length; i++) {
var ident = observers[i];
if (ident.source === src && ident.signal === sig &&
ident.connected) {
try {
ident.listener.apply(src, args);
} catch (e) {
errors.push(e);
}
}
}
self._lock = false;
if (self._dirty) {
self._dirty = false;
for (var i = observers.length - 1; i >= 0; i--) {
if (!observers[i].connected) {
observers.splice(i, 1);
}
}
}
if (errors.length == 1) {
throw errors[0];
} else if (errors.length > 1) {
var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
e.errors = errors;
throw e;
}
}
});
MochiKit.Signal.EXPORT_OK = [];
MochiKit.Signal.EXPORT = [
'connect',
'disconnect',
'signal',
'disconnectAll',
'disconnectAllTo'
];
MochiKit.Signal.__new__ = function (win) {
var m = MochiKit.Base;
this._document = document;
this._window = win;
this._lock = false;
this._dirty = false;
try {
this.connect(window, 'onunload', this._unloadCache);
} catch (e) {
// pass: might not be a browser
}
this.EXPORT_TAGS = {
':common': this.EXPORT,
':all': m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
};
MochiKit.Signal.__new__(this);
//
// XXX: Internet Explorer blows
//
if (MochiKit.__export__) {
connect = MochiKit.Signal.connect;
disconnect = MochiKit.Signal.disconnect;
disconnectAll = MochiKit.Signal.disconnectAll;
signal = MochiKit.Signal.signal;
}
MochiKit.Base._exportSymbols(this, MochiKit.Signal);

View file

@ -0,0 +1,589 @@
/***
Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
Mochi-ized By Thomas Herve (_firstname_@nimail.org)
See scriptaculous.js for full license.
***/
MochiKit.Base._deps('Sortable', ['Base', 'Iter', 'DOM', 'Position', 'DragAndDrop']);
MochiKit.Sortable.NAME = 'MochiKit.Sortable';
MochiKit.Sortable.VERSION = '1.4.2';
MochiKit.Sortable.__repr__ = function () {
return '[' + this.NAME + ' ' + this.VERSION + ']';
};
MochiKit.Sortable.toString = function () {
return this.__repr__();
};
MochiKit.Sortable.EXPORT = [
];
MochiKit.Sortable.EXPORT_OK = [
];
MochiKit.Base.update(MochiKit.Sortable, {
/***
Manage sortables. Mainly use the create function to add a sortable.
***/
sortables: {},
_findRootElement: function (element) {
while (element.tagName.toUpperCase() != "BODY") {
if (element.id && MochiKit.Sortable.sortables[element.id]) {
return element;
}
element = element.parentNode;
}
},
_createElementId: function(element) {
if (element.id == null || element.id == "") {
var d = MochiKit.DOM;
var id;
var count = 1;
while (d.getElement(id = "sortable" + count) != null) {
count += 1;
}
d.setNodeAttribute(element, "id", id);
}
},
/** @id MochiKit.Sortable.options */
options: function (element) {
element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
if (!element) {
return;
}
return MochiKit.Sortable.sortables[element.id];
},
/** @id MochiKit.Sortable.destroy */
destroy: function (element){
var s = MochiKit.Sortable.options(element);
var b = MochiKit.Base;
var d = MochiKit.DragAndDrop;
if (s) {
MochiKit.Signal.disconnect(s.startHandle);
MochiKit.Signal.disconnect(s.endHandle);
b.map(function (dr) {
d.Droppables.remove(dr);
}, s.droppables);
b.map(function (dr) {
dr.destroy();
}, s.draggables);
delete MochiKit.Sortable.sortables[s.element.id];
}
},
/** @id MochiKit.Sortable.create */
create: function (element, options) {
element = MochiKit.DOM.getElement(element);
var self = MochiKit.Sortable;
self._createElementId(element);
/** @id MochiKit.Sortable.options */
options = MochiKit.Base.update({
/** @id MochiKit.Sortable.element */
element: element,
/** @id MochiKit.Sortable.tag */
tag: 'li', // assumes li children, override with tag: 'tagname'
/** @id MochiKit.Sortable.dropOnEmpty */
dropOnEmpty: false,
/** @id MochiKit.Sortable.tree */
tree: false,
/** @id MochiKit.Sortable.treeTag */
treeTag: 'ul',
/** @id MochiKit.Sortable.overlap */
overlap: 'vertical', // one of 'vertical', 'horizontal'
/** @id MochiKit.Sortable.constraint */
constraint: 'vertical', // one of 'vertical', 'horizontal', false
// also takes array of elements (or ids); or false
/** @id MochiKit.Sortable.containment */
containment: [element],
/** @id MochiKit.Sortable.handle */
handle: false, // or a CSS class
/** @id MochiKit.Sortable.only */
only: false,
/** @id MochiKit.Sortable.hoverclass */
hoverclass: null,
/** @id MochiKit.Sortable.ghosting */
ghosting: false,
/** @id MochiKit.Sortable.scroll */
scroll: false,
/** @id MochiKit.Sortable.scrollSensitivity */
scrollSensitivity: 20,
/** @id MochiKit.Sortable.scrollSpeed */
scrollSpeed: 15,
/** @id MochiKit.Sortable.format */
format: /^[^_]*_(.*)$/,
/** @id MochiKit.Sortable.onChange */
onChange: MochiKit.Base.noop,
/** @id MochiKit.Sortable.onUpdate */
onUpdate: MochiKit.Base.noop,
/** @id MochiKit.Sortable.accept */
accept: null
}, options);
// clear any old sortable with same element
self.destroy(element);
// build options for the draggables
var options_for_draggable = {
revert: true,
ghosting: options.ghosting,
scroll: options.scroll,
scrollSensitivity: options.scrollSensitivity,
scrollSpeed: options.scrollSpeed,
constraint: options.constraint,
handle: options.handle
};
if (options.starteffect) {
options_for_draggable.starteffect = options.starteffect;
}
if (options.reverteffect) {
options_for_draggable.reverteffect = options.reverteffect;
} else if (options.ghosting) {
options_for_draggable.reverteffect = function (innerelement) {
innerelement.style.top = 0;
innerelement.style.left = 0;
};
}
if (options.endeffect) {
options_for_draggable.endeffect = options.endeffect;
}
if (options.zindex) {
options_for_draggable.zindex = options.zindex;
}
// build options for the droppables
var options_for_droppable = {
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass,
onhover: self.onHover,
tree: options.tree,
accept: options.accept
}
var options_for_tree = {
onhover: self.onEmptyHover,
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass,
accept: options.accept
}
// fix for gecko engine
MochiKit.DOM.removeEmptyTextNodes(element);
options.draggables = [];
options.droppables = [];
// drop on empty handling
if (options.dropOnEmpty || options.tree) {
new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
options.droppables.push(element);
}
MochiKit.Base.map(function (e) {
// handles are per-draggable
var handle = options.handle ?
MochiKit.DOM.getFirstElementByTagAndClassName(null,
options.handle, e) : e;
options.draggables.push(
new MochiKit.DragAndDrop.Draggable(e,
MochiKit.Base.update(options_for_draggable,
{handle: handle})));
new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
if (options.tree) {
e.treeNode = element;
}
options.droppables.push(e);
}, (self.findElements(element, options) || []));
if (options.tree) {
MochiKit.Base.map(function (e) {
new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
e.treeNode = element;
options.droppables.push(e);
}, (self.findTreeElements(element, options) || []));
}
// keep reference
self.sortables[element.id] = options;
options.lastValue = self.serialize(element);
options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
MochiKit.Base.partial(self.onStart, element));
options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
MochiKit.Base.partial(self.onEnd, element));
},
/** @id MochiKit.Sortable.onStart */
onStart: function (element, draggable) {
var self = MochiKit.Sortable;
var options = self.options(element);
options.lastValue = self.serialize(options.element);
},
/** @id MochiKit.Sortable.onEnd */
onEnd: function (element, draggable) {
var self = MochiKit.Sortable;
self.unmark();
var options = self.options(element);
if (options.lastValue != self.serialize(options.element)) {
options.onUpdate(options.element);
}
},
// return all suitable-for-sortable elements in a guaranteed order
/** @id MochiKit.Sortable.findElements */
findElements: function (element, options) {
return MochiKit.Sortable.findChildren(element, options.only, options.tree, options.tag);
},
/** @id MochiKit.Sortable.findTreeElements */
findTreeElements: function (element, options) {
return MochiKit.Sortable.findChildren(
element, options.only, options.tree ? true : false, options.treeTag);
},
/** @id MochiKit.Sortable.findChildren */
findChildren: function (element, only, recursive, tagName) {
if (!element.hasChildNodes()) {
return null;
}
tagName = tagName.toUpperCase();
if (only) {
only = MochiKit.Base.flattenArray([only]);
}
var elements = [];
MochiKit.Base.map(function (e) {
if (e.tagName &&
e.tagName.toUpperCase() == tagName &&
(!only ||
MochiKit.Iter.some(only, function (c) {
return MochiKit.DOM.hasElementClass(e, c);
}))) {
elements.push(e);
}
if (recursive) {
var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName);
if (grandchildren && grandchildren.length > 0) {
elements = elements.concat(grandchildren);
}
}
}, element.childNodes);
return elements;
},
/** @id MochiKit.Sortable.onHover */
onHover: function (element, dropon, overlap) {
if (MochiKit.DOM.isChildNode(dropon, element)) {
return;
}
var self = MochiKit.Sortable;
if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
return;
} else if (overlap > 0.5) {
self.mark(dropon, 'before');
if (dropon.previousSibling != element) {
var oldParentNode = element.parentNode;
element.style.visibility = 'hidden'; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
if (dropon.parentNode != oldParentNode) {
self.options(oldParentNode).onChange(element);
}
self.options(dropon.parentNode).onChange(element);
}
} else {
self.mark(dropon, 'after');
var nextElement = dropon.nextSibling || null;
if (nextElement != element) {
var oldParentNode = element.parentNode;
element.style.visibility = 'hidden'; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
if (dropon.parentNode != oldParentNode) {
self.options(oldParentNode).onChange(element);
}
self.options(dropon.parentNode).onChange(element);
}
}
},
_offsetSize: function (element, type) {
if (type == 'vertical' || type == 'height') {
return element.offsetHeight;
} else {
return element.offsetWidth;
}
},
/** @id MochiKit.Sortable.onEmptyHover */
onEmptyHover: function (element, dropon, overlap) {
var oldParentNode = element.parentNode;
var self = MochiKit.Sortable;
var droponOptions = self.options(dropon);
if (!MochiKit.DOM.isChildNode(dropon, element)) {
var index;
var children = self.findElements(dropon, {tag: droponOptions.tag,
only: droponOptions.only});
var child = null;
if (children) {
var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
for (index = 0; index < children.length; index += 1) {
if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
offset -= self._offsetSize(children[index], droponOptions.overlap);
} else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
child = index + 1 < children.length ? children[index + 1] : null;
break;
} else {
child = children[index];
break;
}
}
}
dropon.insertBefore(element, child);
self.options(oldParentNode).onChange(element);
droponOptions.onChange(element);
}
},
/** @id MochiKit.Sortable.unmark */
unmark: function () {
var m = MochiKit.Sortable._marker;
if (m) {
MochiKit.Style.hideElement(m);
}
},
/** @id MochiKit.Sortable.mark */
mark: function (dropon, position) {
// mark on ghosting only
var d = MochiKit.DOM;
var self = MochiKit.Sortable;
var sortable = self.options(dropon.parentNode);
if (sortable && !sortable.ghosting) {
return;
}
if (!self._marker) {
self._marker = d.getElement('dropmarker') ||
document.createElement('DIV');
MochiKit.Style.hideElement(self._marker);
d.addElementClass(self._marker, 'dropmarker');
self._marker.style.position = 'absolute';
document.getElementsByTagName('body').item(0).appendChild(self._marker);
}
var offsets = MochiKit.Position.cumulativeOffset(dropon);
self._marker.style.left = offsets.x + 'px';
self._marker.style.top = offsets.y + 'px';
if (position == 'after') {
if (sortable.overlap == 'horizontal') {
self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
} else {
self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
}
}
MochiKit.Style.showElement(self._marker);
},
_tree: function (element, options, parent) {
var self = MochiKit.Sortable;
var children = self.findElements(element, options) || [];
for (var i = 0; i < children.length; ++i) {
var match = children[i].id.match(options.format);
if (!match) {
continue;
}
var child = {
id: encodeURIComponent(match ? match[1] : null),
element: element,
parent: parent,
children: [],
position: parent.children.length,
container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
}
/* Get the element containing the children and recurse over it */
if (child.container) {
self._tree(child.container, options, child)
}
parent.children.push (child);
}
return parent;
},
/* Finds the first element of the given tag type within a parent element.
Used for finding the first LI[ST] within a L[IST]I[TEM].*/
_findChildrenElement: function (element, containerTag) {
if (element && element.hasChildNodes) {
containerTag = containerTag.toUpperCase();
for (var i = 0; i < element.childNodes.length; ++i) {
if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
return element.childNodes[i];
}
}
}
return null;
},
/** @id MochiKit.Sortable.tree */
tree: function (element, options) {
element = MochiKit.DOM.getElement(element);
var sortableOptions = MochiKit.Sortable.options(element);
options = MochiKit.Base.update({
tag: sortableOptions.tag,
treeTag: sortableOptions.treeTag,
only: sortableOptions.only,
name: element.id,
format: sortableOptions.format
}, options || {});
var root = {
id: null,
parent: null,
children: new Array,
container: element,
position: 0
}
return MochiKit.Sortable._tree(element, options, root);
},
/**
* Specifies the sequence for the Sortable.
* @param {Node} element Element to use as the Sortable.
* @param {Object} newSequence New sequence to use.
* @param {Object} options Options to use fro the Sortable.
*/
setSequence: function (element, newSequence, options) {
var self = MochiKit.Sortable;
var b = MochiKit.Base;
element = MochiKit.DOM.getElement(element);
options = b.update(self.options(element), options || {});
var nodeMap = {};
b.map(function (n) {
var m = n.id.match(options.format);
if (m) {
nodeMap[m[1]] = [n, n.parentNode];
}
n.parentNode.removeChild(n);
}, self.findElements(element, options));
b.map(function (ident) {
var n = nodeMap[ident];
if (n) {
n[1].appendChild(n[0]);
delete nodeMap[ident];
}
}, newSequence);
},
/* Construct a [i] index for a particular node */
_constructIndex: function (node) {
var index = '';
do {
if (node.id) {
index = '[' + node.position + ']' + index;
}
} while ((node = node.parent) != null);
return index;
},
/** @id MochiKit.Sortable.sequence */
sequence: function (element, options) {
element = MochiKit.DOM.getElement(element);
var self = MochiKit.Sortable;
var options = MochiKit.Base.update(self.options(element), options || {});
return MochiKit.Base.map(function (item) {
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
}, MochiKit.DOM.getElement(self.findElements(element, options) || []));
},
/**
* Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
* These options override the Sortable options for the serialization only.
* @param {Node} element Element to serialize.
* @param {Object} options Serialization options.
*/
serialize: function (element, options) {
element = MochiKit.DOM.getElement(element);
var self = MochiKit.Sortable;
options = MochiKit.Base.update(self.options(element), options || {});
var name = encodeURIComponent(options.name || element.id);
if (options.tree) {
return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
return [name + self._constructIndex(item) + "[id]=" +
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
}, self.tree(element, options).children)).join('&');
} else {
return MochiKit.Base.map(function (item) {
return name + "[]=" + encodeURIComponent(item);
}, self.sequence(element, options)).join('&');
}
}
});
// trunk compatibility
MochiKit.Sortable.Sortable = MochiKit.Sortable;
MochiKit.Sortable.__new__ = function () {
MochiKit.Base.nameFunctions(this);
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
};
};
MochiKit.Sortable.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Sortable);

View file

@ -0,0 +1,594 @@
/***
MochiKit.Style 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved.
***/
MochiKit.Base._deps('Style', ['Base', 'DOM']);
MochiKit.Style.NAME = 'MochiKit.Style';
MochiKit.Style.VERSION = '1.4.2';
MochiKit.Style.__repr__ = function () {
return '[' + this.NAME + ' ' + this.VERSION + ']';
};
MochiKit.Style.toString = function () {
return this.__repr__();
};
MochiKit.Style.EXPORT_OK = [];
MochiKit.Style.EXPORT = [
'setStyle',
'setOpacity',
'getStyle',
'getElementDimensions',
'elementDimensions', // deprecated
'setElementDimensions',
'getElementPosition',
'elementPosition', // deprecated
'setElementPosition',
"makePositioned",
"undoPositioned",
"makeClipping",
"undoClipping",
'setDisplayForElement',
'hideElement',
'showElement',
'getViewportDimensions',
'getViewportPosition',
'Dimensions',
'Coordinates'
];
/*
Dimensions
*/
/** @id MochiKit.Style.Dimensions */
MochiKit.Style.Dimensions = function (w, h) {
this.w = w;
this.h = h;
};
MochiKit.Style.Dimensions.prototype.__repr__ = function () {
var repr = MochiKit.Base.repr;
return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
};
MochiKit.Style.Dimensions.prototype.toString = function () {
return this.__repr__();
};
/*
Coordinates
*/
/** @id MochiKit.Style.Coordinates */
MochiKit.Style.Coordinates = function (x, y) {
this.x = x;
this.y = y;
};
MochiKit.Style.Coordinates.prototype.__repr__ = function () {
var repr = MochiKit.Base.repr;
return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
};
MochiKit.Style.Coordinates.prototype.toString = function () {
return this.__repr__();
};
MochiKit.Base.update(MochiKit.Style, {
/** @id MochiKit.Style.getStyle */
getStyle: function (elem, cssProperty) {
var dom = MochiKit.DOM;
var d = dom._document;
elem = dom.getElement(elem);
cssProperty = MochiKit.Base.camelize(cssProperty);
if (!elem || elem == d) {
return undefined;
}
if (cssProperty == 'opacity' && typeof(elem.filters) != 'undefined') {
var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
if (opacity && opacity[1]) {
return parseFloat(opacity[1]) / 100;
}
return 1.0;
}
if (cssProperty == 'float' || cssProperty == 'cssFloat' || cssProperty == 'styleFloat') {
if (elem.style["float"]) {
return elem.style["float"];
} else if (elem.style.cssFloat) {
return elem.style.cssFloat;
} else if (elem.style.styleFloat) {
return elem.style.styleFloat;
} else {
return "none";
}
}
var value = elem.style ? elem.style[cssProperty] : null;
if (!value) {
if (d.defaultView && d.defaultView.getComputedStyle) {
var css = d.defaultView.getComputedStyle(elem, null);
cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
).toLowerCase(); // from dojo.style.toSelectorCase
value = css ? css.getPropertyValue(cssProperty) : null;
} else if (elem.currentStyle) {
value = elem.currentStyle[cssProperty];
if (/^\d/.test(value) && !/px$/.test(value) && cssProperty != 'fontWeight') {
/* Convert to px using an hack from Dean Edwards */
var left = elem.style.left;
var rsLeft = elem.runtimeStyle.left;
elem.runtimeStyle.left = elem.currentStyle.left;
elem.style.left = value || 0;
value = elem.style.pixelLeft + "px";
elem.style.left = left;
elem.runtimeStyle.left = rsLeft;
}
}
}
if (cssProperty == 'opacity') {
value = parseFloat(value);
}
if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.findValue(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
value = 'auto';
}
}
return value == 'auto' ? null : value;
},
/** @id MochiKit.Style.setStyle */
setStyle: function (elem, style) {
elem = MochiKit.DOM.getElement(elem);
for (var name in style) {
switch (name) {
case 'opacity':
MochiKit.Style.setOpacity(elem, style[name]);
break;
case 'float':
case 'cssFloat':
case 'styleFloat':
if (typeof(elem.style["float"]) != "undefined") {
elem.style["float"] = style[name];
} else if (typeof(elem.style.cssFloat) != "undefined") {
elem.style.cssFloat = style[name];
} else {
elem.style.styleFloat = style[name];
}
break;
default:
elem.style[MochiKit.Base.camelize(name)] = style[name];
}
}
},
/** @id MochiKit.Style.setOpacity */
setOpacity: function (elem, o) {
elem = MochiKit.DOM.getElement(elem);
var self = MochiKit.Style;
if (o == 1) {
var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
elem.style["opacity"] = toSet ? 0.999999 : 1.0;
if (/MSIE/.test(navigator.userAgent)) {
elem.style['filter'] =
self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
}
} else {
if (o < 0.00001) {
o = 0;
}
elem.style["opacity"] = o;
if (/MSIE/.test(navigator.userAgent)) {
elem.style['filter'] =
self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
}
}
},
/*
getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
License: BSD, http://developer.yahoo.net/yui/license.txt
*/
/** @id MochiKit.Style.getElementPosition */
getElementPosition: function (elem, /* optional */relativeTo) {
var self = MochiKit.Style;
var dom = MochiKit.DOM;
elem = dom.getElement(elem);
if (!elem ||
(!(elem.x && elem.y) &&
(!elem.parentNode === null ||
self.getStyle(elem, 'display') == 'none'))) {
return undefined;
}
var c = new self.Coordinates(0, 0);
var box = null;
var parent = null;
var d = MochiKit.DOM._document;
var de = d.documentElement;
var b = d.body;
if (!elem.parentNode && elem.x && elem.y) {
/* it's just a MochiKit.Style.Coordinates object */
c.x += elem.x || 0;
c.y += elem.y || 0;
} else if (elem.getBoundingClientRect) { // IE shortcut
/*
The IE shortcut can be off by two. We fix it. See:
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
This is similar to the method used in
MochiKit.Signal.Event.mouse().
*/
box = elem.getBoundingClientRect();
c.x += box.left +
(de.scrollLeft || b.scrollLeft) -
(de.clientLeft || 0);
c.y += box.top +
(de.scrollTop || b.scrollTop) -
(de.clientTop || 0);
} else if (elem.offsetParent) {
c.x += elem.offsetLeft;
c.y += elem.offsetTop;
parent = elem.offsetParent;
if (parent != elem) {
while (parent) {
c.x += parseInt(parent.style.borderLeftWidth) || 0;
c.y += parseInt(parent.style.borderTopWidth) || 0;
c.x += parent.offsetLeft;
c.y += parent.offsetTop;
parent = parent.offsetParent;
}
}
/*
Opera < 9 and old Safari (absolute) incorrectly account for
body offsetTop and offsetLeft.
*/
var ua = navigator.userAgent.toLowerCase();
if ((typeof(opera) != 'undefined' &&
parseFloat(opera.version()) < 9) ||
(ua.indexOf('AppleWebKit') != -1 &&
self.getStyle(elem, 'position') == 'absolute')) {
c.x -= b.offsetLeft;
c.y -= b.offsetTop;
}
// Adjust position for strange Opera scroll bug
if (elem.parentNode) {
parent = elem.parentNode;
} else {
parent = null;
}
while (parent) {
var tagName = parent.tagName.toUpperCase();
if (tagName === 'BODY' || tagName === 'HTML') {
break;
}
var disp = self.getStyle(parent, 'display');
// Handle strange Opera bug for some display
if (disp.search(/^inline|table-row.*$/i)) {
c.x -= parent.scrollLeft;
c.y -= parent.scrollTop;
}
if (parent.parentNode) {
parent = parent.parentNode;
} else {
parent = null;
}
}
}
if (typeof(relativeTo) != 'undefined') {
relativeTo = arguments.callee(relativeTo);
if (relativeTo) {
c.x -= (relativeTo.x || 0);
c.y -= (relativeTo.y || 0);
}
}
return c;
},
/** @id MochiKit.Style.setElementPosition */
setElementPosition: function (elem, newPos/* optional */, units) {
elem = MochiKit.DOM.getElement(elem);
if (typeof(units) == 'undefined') {
units = 'px';
}
var newStyle = {};
var isUndefNull = MochiKit.Base.isUndefinedOrNull;
if (!isUndefNull(newPos.x)) {
newStyle['left'] = newPos.x + units;
}
if (!isUndefNull(newPos.y)) {
newStyle['top'] = newPos.y + units;
}
MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
},
/** @id MochiKit.Style.makePositioned */
makePositioned: function (element) {
element = MochiKit.DOM.getElement(element);
var pos = MochiKit.Style.getStyle(element, 'position');
if (pos == 'static' || !pos) {
element.style.position = 'relative';
// Opera returns the offset relative to the positioning context,
// when an element is position relative but top and left have
// not been defined
if (/Opera/.test(navigator.userAgent)) {
element.style.top = 0;
element.style.left = 0;
}
}
},
/** @id MochiKit.Style.undoPositioned */
undoPositioned: function (element) {
element = MochiKit.DOM.getElement(element);
if (element.style.position == 'relative') {
element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
}
},
/** @id MochiKit.Style.makeClipping */
makeClipping: function (element) {
element = MochiKit.DOM.getElement(element);
var s = element.style;
var oldOverflow = { 'overflow': s.overflow,
'overflow-x': s.overflowX,
'overflow-y': s.overflowY };
if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
element.style.overflow = 'hidden';
element.style.overflowX = 'hidden';
element.style.overflowY = 'hidden';
}
return oldOverflow;
},
/** @id MochiKit.Style.undoClipping */
undoClipping: function (element, overflow) {
element = MochiKit.DOM.getElement(element);
if (typeof(overflow) == 'string') {
element.style.overflow = overflow;
} else if (overflow != null) {
element.style.overflow = overflow['overflow'];
element.style.overflowX = overflow['overflow-x'];
element.style.overflowY = overflow['overflow-y'];
}
},
/** @id MochiKit.Style.getElementDimensions */
getElementDimensions: function (elem, contentSize/*optional*/) {
var self = MochiKit.Style;
var dom = MochiKit.DOM;
if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
return new self.Dimensions(elem.w || 0, elem.h || 0);
}
elem = dom.getElement(elem);
if (!elem) {
return undefined;
}
var disp = self.getStyle(elem, 'display');
// display can be empty/undefined on WebKit/KHTML
if (disp == 'none' || disp == '' || typeof(disp) == 'undefined') {
var s = elem.style;
var originalVisibility = s.visibility;
var originalPosition = s.position;
var originalDisplay = s.display;
s.visibility = 'hidden';
s.position = 'absolute';
s.display = self._getDefaultDisplay(elem);
var originalWidth = elem.offsetWidth;
var originalHeight = elem.offsetHeight;
s.display = originalDisplay;
s.position = originalPosition;
s.visibility = originalVisibility;
} else {
originalWidth = elem.offsetWidth || 0;
originalHeight = elem.offsetHeight || 0;
}
if (contentSize) {
var tableCell = 'colSpan' in elem && 'rowSpan' in elem;
var collapse = (tableCell && elem.parentNode && self.getStyle(
elem.parentNode, 'borderCollapse') == 'collapse')
if (collapse) {
if (/MSIE/.test(navigator.userAgent)) {
var borderLeftQuota = elem.previousSibling? 0.5 : 1;
var borderRightQuota = elem.nextSibling? 0.5 : 1;
}
else {
var borderLeftQuota = 0.5;
var borderRightQuota = 0.5;
}
} else {
var borderLeftQuota = 1;
var borderRightQuota = 1;
}
originalWidth -= Math.round(
(parseFloat(self.getStyle(elem, 'paddingLeft')) || 0)
+ (parseFloat(self.getStyle(elem, 'paddingRight')) || 0)
+ borderLeftQuota *
(parseFloat(self.getStyle(elem, 'borderLeftWidth')) || 0)
+ borderRightQuota *
(parseFloat(self.getStyle(elem, 'borderRightWidth')) || 0)
);
if (tableCell) {
if (/Opera/.test(navigator.userAgent)
&& !/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)) {
var borderHeightQuota = 0;
} else if (/MSIE/.test(navigator.userAgent)) {
var borderHeightQuota = 1;
} else {
var borderHeightQuota = collapse? 0.5 : 1;
}
} else {
var borderHeightQuota = 1;
}
originalHeight -= Math.round(
(parseFloat(self.getStyle(elem, 'paddingTop')) || 0)
+ (parseFloat(self.getStyle(elem, 'paddingBottom')) || 0)
+ borderHeightQuota * (
(parseFloat(self.getStyle(elem, 'borderTopWidth')) || 0)
+ (parseFloat(self.getStyle(elem, 'borderBottomWidth')) || 0))
);
}
return new self.Dimensions(originalWidth, originalHeight);
},
/** @id MochiKit.Style.setElementDimensions */
setElementDimensions: function (elem, newSize/* optional */, units) {
elem = MochiKit.DOM.getElement(elem);
if (typeof(units) == 'undefined') {
units = 'px';
}
var newStyle = {};
var isUndefNull = MochiKit.Base.isUndefinedOrNull;
if (!isUndefNull(newSize.w)) {
newStyle['width'] = newSize.w + units;
}
if (!isUndefNull(newSize.h)) {
newStyle['height'] = newSize.h + units;
}
MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
},
_getDefaultDisplay: function (elem) {
var self = MochiKit.Style;
var dom = MochiKit.DOM;
elem = dom.getElement(elem);
if (!elem) {
return undefined;
}
var tagName = elem.tagName.toUpperCase();
return self._defaultDisplay[tagName] || 'block';
},
/** @id MochiKit.Style.setDisplayForElement */
setDisplayForElement: function (display, element/*, ...*/) {
var elements = MochiKit.Base.extend(null, arguments, 1);
var getElement = MochiKit.DOM.getElement;
for (var i = 0; i < elements.length; i++) {
element = getElement(elements[i]);
if (element) {
element.style.display = display;
}
}
},
/** @id MochiKit.Style.getViewportDimensions */
getViewportDimensions: function () {
var d = new MochiKit.Style.Dimensions();
var w = MochiKit.DOM._window;
var b = MochiKit.DOM._document.body;
if (w.innerWidth) {
d.w = w.innerWidth;
d.h = w.innerHeight;
} else if (b && b.parentElement && b.parentElement.clientWidth) {
d.w = b.parentElement.clientWidth;
d.h = b.parentElement.clientHeight;
} else if (b && b.clientWidth) {
d.w = b.clientWidth;
d.h = b.clientHeight;
}
return d;
},
/** @id MochiKit.Style.getViewportPosition */
getViewportPosition: function () {
var c = new MochiKit.Style.Coordinates(0, 0);
var d = MochiKit.DOM._document;
var de = d.documentElement;
var db = d.body;
if (de && (de.scrollTop || de.scrollLeft)) {
c.x = de.scrollLeft;
c.y = de.scrollTop;
} else if (db) {
c.x = db.scrollLeft;
c.y = db.scrollTop;
}
return c;
},
__new__: function () {
var m = MochiKit.Base;
var inlines = ['A','ABBR','ACRONYM','B','BASEFONT','BDO','BIG','BR',
'CITE','CODE','DFN','EM','FONT','I','IMG','KBD','LABEL',
'Q','S','SAMP','SMALL','SPAN','STRIKE','STRONG','SUB',
'SUP','TEXTAREA','TT','U','VAR'];
this._defaultDisplay = { 'TABLE': 'table',
'THEAD': 'table-header-group',
'TBODY': 'table-row-group',
'TFOOT': 'table-footer-group',
'COLGROUP': 'table-column-group',
'COL': 'table-column',
'TR': 'table-row',
'TD': 'table-cell',
'TH': 'table-cell',
'CAPTION': 'table-caption',
'LI': 'list-item',
'INPUT': 'inline-block',
'SELECT': 'inline-block' };
// CSS 'display' support in IE6/7 is just broken...
if (/MSIE/.test(navigator.userAgent)) {
for (var k in this._defaultDisplay) {
var v = this._defaultDisplay[k];
if (v.indexOf('table') == 0) {
this._defaultDisplay[k] = 'block';
}
}
}
for (var i = 0; i < inlines.length; i++) {
this._defaultDisplay[inlines[i]] = 'inline';
}
this.elementPosition = this.getElementPosition;
this.elementDimensions = this.getElementDimensions;
this.hideElement = m.partial(this.setDisplayForElement, 'none');
// TODO: showElement could be improved by using getDefaultDisplay.
this.showElement = m.partial(this.setDisplayForElement, 'block');
this.EXPORT_TAGS = {
':common': this.EXPORT,
':all': m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
}
});
MochiKit.Style.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Style);

View file

@ -0,0 +1,162 @@
/***
MochiKit.Test 1.4.2
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
MochiKit.Base._deps('Test', ['Base']);
MochiKit.Test.NAME = "MochiKit.Test";
MochiKit.Test.VERSION = "1.4.2";
MochiKit.Test.__repr__ = function () {
return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Test.toString = function () {
return this.__repr__();
};
MochiKit.Test.EXPORT = ["runTests"];
MochiKit.Test.EXPORT_OK = [];
MochiKit.Test.runTests = function (obj) {
if (typeof(obj) == "string") {
obj = JSAN.use(obj);
}
var suite = new MochiKit.Test.Suite();
suite.run(obj);
};
MochiKit.Test.Suite = function () {
this.testIndex = 0;
MochiKit.Base.bindMethods(this);
};
MochiKit.Test.Suite.prototype = {
run: function (obj) {
try {
obj(this);
} catch (e) {
this.traceback(e);
}
},
traceback: function (e) {
var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
print("not ok " + this.testIndex + " - Error thrown");
for (var i = 0; i < items.length; i++) {
var kv = items[i];
if (kv[0] == "stack") {
kv[1] = kv[1].split(/\n/)[0];
}
this.print("# " + kv.join(": "));
}
},
print: function (s) {
print(s);
},
is: function (got, expected, /* optional */message) {
var res = 1;
var msg = null;
try {
res = MochiKit.Base.compare(got, expected);
} catch (e) {
msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
}
if (res) {
msg = "Expected value did not compare equal";
}
if (!res) {
return this.testResult(true, message);
}
return this.testResult(false, message,
[[msg], ["got:", got], ["expected:", expected]]);
},
testResult: function (pass, msg, failures) {
this.testIndex += 1;
if (pass) {
this.print("ok " + this.testIndex + " - " + msg);
return;
}
this.print("not ok " + this.testIndex + " - " + msg);
if (failures) {
for (var i = 0; i < failures.length; i++) {
this.print("# " + failures[i].join(" "));
}
}
},
isDeeply: function (got, expected, /* optional */message) {
var m = MochiKit.Base;
var res = 1;
try {
res = m.compare(got, expected);
} catch (e) {
// pass
}
if (res === 0) {
return this.ok(true, message);
}
var gk = m.keys(got);
var ek = m.keys(expected);
gk.sort();
ek.sort();
if (m.compare(gk, ek)) {
// differing keys
var cmp = {};
var i;
for (i = 0; i < gk.length; i++) {
cmp[gk[i]] = "got";
}
for (i = 0; i < ek.length; i++) {
if (ek[i] in cmp) {
delete cmp[ek[i]];
} else {
cmp[ek[i]] = "expected";
}
}
var diffkeys = m.keys(cmp);
diffkeys.sort();
var gotkeys = [];
var expkeys = [];
while (diffkeys.length) {
var k = diffkeys.shift();
if (k in Object.prototype) {
continue;
}
(cmp[k] == "got" ? gotkeys : expkeys).push(k);
}
}
return this.testResult((!res), msg,
(msg ? [["got:", got], ["expected:", expected]] : undefined)
);
},
ok: function (res, message) {
return this.testResult(res, message);
}
};
MochiKit.Test.__new__ = function () {
var m = MochiKit.Base;
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": m.concat(this.EXPORT, this.EXPORT_OK)
};
m.nameFunctions(this);
};
MochiKit.Test.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Test);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@import url("../../../SimpleTest/test.css");

View file

@ -0,0 +1,32 @@
[DEFAULT]
support-files =
SimpleTest/test.css
test_Base.js
test_Color.js
test_DateTime.js
test_DragAndDrop.js
test_Format.js
test_Iter.js
test_Logging.js
test_MochiKit-Async.json
test_Signal.js
[test_MochiKit-Async.html]
[test_MochiKit-Base.html]
[test_MochiKit-Color.html]
[test_MochiKit-DateTime.html]
[test_MochiKit-DOM.html]
[test_MochiKit-DOM-Safari.html]
skip-if = (android_version == '18' && debug) # intermittent time-out
[test_MochiKit-DragAndDrop.html]
[test_MochiKit-Format.html]
[test_MochiKit-Iter.html]
[test_MochiKit-Logging.html]
[test_MochiKit-MochiKit.html]
[test_MochiKit-Selector.html]
[test_MochiKit-Signal.html]
[test_MochiKit-Style.html]
[test_MochiKit-Visual.html]
# This test is broken: "Error: JSAN is not defined ... Line: 10".
# (And is removed in future MochiKit v1.5)
#[test_MochiKit-JSAN.html]

View file

@ -0,0 +1,577 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Base'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Base'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_Base = function (t) {
// test bind
var not_self = {"toString": function () { return "not self"; } };
var self = {"toString": function () { return "self"; } };
var func = function (arg) { return this.toString() + " " + arg; };
var boundFunc = bind(func, self);
not_self.boundFunc = boundFunc;
t.is( boundFunc("foo"), "self foo", "boundFunc bound to self properly" );
t.is( not_self.boundFunc("foo"), "self foo", "boundFunc bound to self on another obj" );
t.is( bind(boundFunc, not_self)("foo"), "not self foo", "boundFunc successfully rebound!" );
t.is( bind(boundFunc, undefined, "foo")(), "self foo", "boundFunc partial no self change" );
t.is( bind(boundFunc, not_self, "foo")(), "not self foo", "boundFunc partial self change" );
// test method
not_self = {"toString": function () { return "not self"; } };
self = {"toString": function () { return "self"; } };
func = function (arg) { return this.toString() + " " + arg; };
var boundMethod = method(self, func);
not_self.boundMethod = boundMethod;
t.is( boundMethod("foo"), "self foo", "boundMethod bound to self properly" );
t.is( not_self.boundMethod("foo"), "self foo", "boundMethod bound to self on another obj" );
t.is( method(not_self, boundMethod)("foo"), "not self foo", "boundMethod successfully rebound!" );
t.is( method(undefined, boundMethod, "foo")(), "self foo", "boundMethod partial no self change" );
t.is( method(not_self, boundMethod, "foo")(), "not self foo", "boundMethod partial self change" );
// test bindLate
self = {"toString": function () { return "self"; } };
boundFunc = bindLate("toString", self);
t.is( boundFunc(), "self", "bindLate binds properly" );
self.toString = function () { return "not self"; };
t.is( boundFunc(), "not self", "bindLate late function lookup" );
func = function (arg) { return this.toString() + " " + arg; };
boundFunc = bindLate(func, self);
t.is( boundFunc("foo"), "not self foo", "bindLate fallback to standard bind" );
// test bindMethods
var O = function (value) {
bindMethods(this);
this.value = value;
};
O.prototype.func = function () {
return this.value;
};
var o = new O("boring");
var p = {};
p.func = o.func;
var func = o.func;
t.is( o.func(), "boring", "bindMethods doesn't break shit" );
t.is( p.func(), "boring", "bindMethods works on other objects" );
t.is( func(), "boring", "bindMethods works on functions" );
var p = clone(o);
t.ok( p instanceof O, "cloned correct inheritance" );
var q = clone(p);
t.ok( q instanceof O, "clone-cloned correct inheritance" );
q.foo = "bar";
t.is( p.foo, undefined, "clone-clone is copy-on-write" );
p.bar = "foo";
t.is( o.bar, undefined, "clone is copy-on-write" );
t.is( q.bar, "foo", "clone-clone has proper delegation" );
// unbind
p.func = bind(p.func, null);
t.is( p.func(), "boring", "clone function calls correct" );
q.value = "awesome";
t.is( q.func(), "awesome", "clone really does work" );
// test boring boolean funcs
t.is( isNull(null), true, "isNull matches null" );
t.is( isNull(undefined), false, "isNull doesn't match undefined" );
t.is( isNull({}), false, "isNull doesn't match objects" );
t.is( isCallable(isCallable), true, "isCallable returns true on itself" );
t.is( isCallable(1), false, "isCallable returns false on numbers" );
t.is( isUndefined(null), false, "null is not undefined" );
t.is( isUndefined(""), false, "empty string is not undefined" );
t.is( isUndefined(undefined), true, "undefined is undefined" );
t.is( isUndefined({}.foo), true, "missing property is undefined" );
t.is( isUndefinedOrNull(null), true, "null is undefined or null" );
t.is( isUndefinedOrNull(""), false, "empty string is not undefined or null" );
t.is( isUndefinedOrNull(undefined), true, "undefined is undefined or null" );
t.is( isUndefinedOrNull({}.foo), true, "missing property is undefined or null" );
t.is( isEmpty(null), true, "isEmpty null" );
t.is( isEmpty([], [], ""), true, "isEmpty true" );
t.is( isEmpty([], [1], ""), true, "isEmpty true" );
t.is( isEmpty([1], [1], "1"), false, "isEmpty false" );
t.is( isEmpty([1], [1], "1"), false, "isEmpty false" );
t.is( isNotEmpty(null), false, "isNotEmpty null" );
t.is( isNotEmpty([], [], ""), false, "isNotEmpty false" );
t.is( isNotEmpty([], [1], ""), false, "isNotEmpty false" );
t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" );
t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" );
t.is( isArrayLike(undefined), false, "isArrayLike(undefined)" );
t.is( isArrayLike(null), false, "isArrayLike(null)" );
t.is( isArrayLike([]), true, "isArrayLike([])" );
// test extension of arrays
var a = [];
var b = [];
var three = [1, 2, 3];
extend(a, three, 1);
t.ok( objEqual(a, [2, 3]), "extend to an empty array" );
extend(a, three, 1)
t.ok( objEqual(a, [2, 3, 2, 3]), "extend to a non-empty array" );
extend(b, three);
t.ok( objEqual(b, three), "extend of an empty array" );
var c1 = extend(null, three);
t.ok( objEqual(c1, three), "extend null" );
var c2 = extend(undefined, three);
t.ok( objEqual(c2, three), "extend undefined" );
t.is( compare(1, 2), -1, "numbers compare lt" );
t.is( compare(2, 1), 1, "numbers compare gt" );
t.is( compare(1, 1), 0, "numbers compare eq" );
t.is( compare([1], [1]), 0, "arrays compare eq" );
t.is( compare([1], [1, 2]), -1, "arrays compare lt (length)" );
t.is( compare([1, 2], [2, 1]), -1, "arrays compare lt (contents)" );
t.is( compare([1, 2], [1]), 1, "arrays compare gt (length)" );
t.is( compare([2, 1], [1, 1]), 1, "arrays compare gt (contents)" );
// test partial application
var a = [];
var func = function (a, b) {
if (arguments.length != 2) {
return "bad args";
} else {
return this.value + a + b;
}
};
var self = {"value": 1, "func": func};
var self2 = {"value": 2};
t.is( self.func(2, 3), 6, "setup for test is correct" );
self.funcTwo = partial(self.func, 2);
t.is( self.funcTwo(3), 6, "partial application works" );
t.is( self.funcTwo(3), 6, "partial application works still" );
t.is( bind(self.funcTwo, self2)(3), 7, "rebinding partial works" );
self.funcTwo = bind(bind(self.funcTwo, self2), null);
t.is( self.funcTwo(3), 6, "re-unbinding partial application works" );
// nodeWalk test
// ... looks a lot like a DOM tree on purpose
var tree = {
"id": "nodeWalkTestTree",
"test:int": "1",
"childNodes": [
{
"test:int": "2",
"childNodes": [
{"test:int": "5"},
"ignored string",
{"ignored": "object"},
["ignored", "list"],
{
"test:skipchildren": "1",
"childNodes": [{"test:int": 6}]
}
]
},
{"test:int": "3"},
{"test:int": "4"}
]
}
var visitedNodes = [];
nodeWalk(tree, function (node) {
var attr = node["test:int"];
if (attr) {
visitedNodes.push(attr);
}
if (node["test:skipchildren"]) {
return;
}
return node.childNodes;
});
t.ok( objEqual(visitedNodes, ["1", "2", "3", "4", "5"]), "nodeWalk looks like it works");
// test map
var minusOne = function (x) { return x - 1; };
var res = map(minusOne, [1, 2, 3]);
t.ok( objEqual(res, [0, 1, 2]), "map works" );
var res2 = xmap(minusOne, 1, 2, 3);
t.ok( objEqual(res2, res), "xmap works" );
res = map(operator.add, [1, 2, 3], [2, 4, 6]);
t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works" );
res = map(operator.add, [1, 2, 3], [2, 4, 6, 8]);
t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (q long)" );
res = map(operator.add, [1, 2, 3, 4], [2, 4, 6]);
t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (p long)" );
res = map(null, [1, 2, 3], [2, 4, 6]);
t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "map(null, p, q) works" );
res = zip([1, 2, 3], [2, 4, 6]);
t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "zip(p, q) works" );
res = map(null, [1, 2, 3]);
t.ok( objEqual(res, [1, 2, 3]), "map(null, lst) works" );
t.is( isNotEmpty("foo"), true, "3 char string is not empty" );
t.is( isNotEmpty(""), false, "0 char string is empty" );
t.is( isNotEmpty([1, 2, 3]), true, "3 element list is not empty" );
t.is( isNotEmpty([]), false, "0 element list is empty" );
// test filter
var greaterThanThis = function (x) { return x > this; };
var greaterThanOne = function (x) { return x > 1; };
var res = filter(greaterThanOne, [-1, 0, 1, 2, 3]);
t.ok( objEqual(res, [2, 3]), "filter works" );
var res = filter(greaterThanThis, [-1, 0, 1, 2, 3], 1);
t.ok( objEqual(res, [2, 3]), "filter self works" );
var res2 = xfilter(greaterThanOne, -1, 0, 1, 2, 3);
t.ok( objEqual(res2, res), "xfilter works" );
t.is(objMax(1, 2, 9, 12, 42, -16, 16), 42, "objMax works (with numbers)");
t.is(objMin(1, 2, 9, 12, 42, -16, 16), -16, "objMin works (with numbers)");
// test adapter registry
var R = new AdapterRegistry();
R.register("callable", isCallable, function () { return "callable"; });
R.register("arrayLike", isArrayLike, function () { return "arrayLike"; });
t.is( R.match(function () {}), "callable", "registry found callable" );
t.is( R.match([]), "arrayLike", "registry found ArrayLike" );
try {
R.match(null);
t.ok( false, "non-matching didn't raise!" );
} catch (e) {
t.is( e, NotFound, "non-matching raised correctly" );
}
R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" });
R.register("undefined", isUndefined, function () { return "undefined" });
t.is( R.match(undefined), "undefinedOrNull", "priorities are as documented" );
t.ok( R.unregister("undefinedOrNull"), "removed adapter" );
t.is( R.match(undefined), "undefined", "adapter was removed" );
R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" }, true);
t.is( R.match(undefined), "undefinedOrNull", "override works" );
var a1 = {"a": 1, "b": 2, "c": 2};
var a2 = {"a": 2, "b": 1, "c": 2};
t.is( keyComparator("a")(a1, a2), -1, "keyComparator 1 lt" );
t.is( keyComparator("c")(a1, a2), 0, "keyComparator 1 eq" );
t.is( keyComparator("c", "b")(a1, a2), 1, "keyComparator 2 eq gt" );
t.is( keyComparator("c", "a")(a1, a2), -1, "keyComparator 2 eq lt" );
t.is( reverseKeyComparator("a")(a1, a2), 1, "reverseKeyComparator" );
t.is( compare(concat([1], [2], [3]), [1, 2, 3]), 0, "concat" );
t.is( repr("foo"), '"foo"', "string repr" );
t.is( repr(1), '1', "number repr" );
t.is( listMin([1, 3, 5, 3, -1]), -1, "listMin" );
t.is( objMin(1, 3, 5, 3, -1), -1, "objMin" );
t.is( listMax([1, 3, 5, 3, -1]), 5, "listMax" );
t.is( objMax(1, 3, 5, 3, -1), 5, "objMax" );
var v = keys(a1);
v.sort();
t.is( compare(v, ["a", "b", "c"]), 0, "keys" );
v = items(a1);
v.sort();
t.is( compare(v, [["a", 1], ["b", 2], ["c", 2]]), 0, "items" );
var StringMap = function() {};
a = new StringMap();
a.foo = "bar";
b = new StringMap();
b.foo = "bar";
try {
compare(a, b);
t.ok( false, "bad comparison registered!?" );
} catch (e) {
t.ok( e instanceof TypeError, "bad comparison raised TypeError" );
}
t.is( repr(a), "[object Object]", "default repr for StringMap" );
var isStringMap = function () {
for (var i = 0; i < arguments.length; i++) {
if (!(arguments[i] instanceof StringMap)) {
return false;
}
}
return true;
};
registerRepr("stringMap",
isStringMap,
function (obj) {
return "StringMap(" + repr(items(obj)) + ")";
}
);
t.is( repr(a), 'StringMap([["foo", "bar"]])', "repr worked" );
// not public API
MochiKit.Base.reprRegistry.unregister("stringMap");
t.is( repr(a), "[object Object]", "default repr for StringMap" );
registerComparator("stringMap",
isStringMap,
function (a, b) {
// no sorted(...) in base
a = items(a);
b = items(b);
a.sort(compare);
b.sort(compare);
return compare(a, b);
}
);
t.is( compare(a, b), 0, "registerComparator" );
update(a, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1});
t.is( a.foo, "bar", "update worked (first obj)" );
t.is( a.wibble, "baz", "update worked (second obj)" );
t.is( a.grr, 1, "update worked (skipped undefined and null)" );
t.is( compare(a, b), 1, "update worked (comparison)" );
setdefault(a, {"foo": "unf"}, {"bar": "web taco"} );
t.is( a.foo, "bar", "setdefault worked (skipped existing)" );
t.is( a.bar, "web taco", "setdefault worked (set non-existing)" );
a = null;
a = setdefault(null, {"foo": "bar"});
t.is( a.foo, "bar", "setdefault worked (self is null)" );
a = null;
a = setdefault(undefined, {"foo": "bar"});
t.is( a.foo, "bar", "setdefault worked (self is undefined)" );
a = null;
a = update(null, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1});
t.is( a.foo, "bar", "update worked (self is null, first obj)" );
t.is( a.wibble, "baz", "update worked (self is null, second obj)" );
t.is( a.grr, 1, "update worked (self is null, skipped undefined and null)" );
a = null;
a = update(undefined, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1});
t.is( a.foo, "bar", "update worked (self is undefined, first obj)" );
t.is( a.wibble, "baz", "update worked (self is undefined, second obj)" );
t.is( a.grr, 1, "update worked (self is undefined, skipped undefined and null)" );
var c = items(merge({"foo": "bar"}, {"wibble": "baz"}));
c.sort(compare);
t.is( compare(c, [["foo", "bar"], ["wibble", "baz"]]), 0, "merge worked" );
// not public API
MochiKit.Base.comparatorRegistry.unregister("stringMap");
try {
compare(a, b);
t.ok( false, "bad comparison registered!?" );
} catch (e) {
t.ok( e instanceof TypeError, "bad comparison raised TypeError" );
}
var o = {"__repr__": function () { return "__repr__"; }};
t.is( repr(o), "__repr__", "__repr__ protocol" );
t.is( repr(MochiKit.Base), MochiKit.Base.__repr__(), "__repr__ protocol when repr is defined" );
var o = {"NAME": "NAME"};
t.is( repr(o), "NAME", "NAME protocol (obj)" );
o = function () { return "TACO" };
o.NAME = "NAME";
t.is( repr(o), "NAME", "NAME protocol (func)" );
t.is( repr(MochiKit.Base.nameFunctions), "MochiKit.Base.nameFunctions", "test nameFunctions" );
// Done!
t.is( urlEncode("1+2=2").toUpperCase(), "1%2B2%3D2", "urlEncode" );
t.is( queryString(["a", "b"], [1, "two"]), "a=1&b=two", "queryString");
t.is( queryString({"a": 1}), "a=1", "one item alternate form queryString" );
var o = {"a": 1, "b": 2, "c": function() {}};
var res = queryString(o).split("&");
res.sort();
t.is( res.join("&"), "a=1&b=2", "two item alternate form queryString, function skip" );
var res = parseQueryString("1+1=2&b=3%3D2");
t.is( res["1 1"], "2", "parseQueryString pathological name" );
t.is( res.b, "3=2", "parseQueryString second name:value pair" );
var res = parseQueryString("foo=one&foo=two", true);
t.is( res["foo"].join(" "), "one two", "parseQueryString useArrays" );
var res = parseQueryString("?foo=2&bar=1");
t.is( res["foo"], "2", "parseQueryString strip leading question mark");
var res = parseQueryString("x=1&y=2");
t.is( typeof(res['&']), "undefined", "extra cruft in parseQueryString output");
t.is( serializeJSON("foo\n\r\b\f\t\u000B\u001B"), "\"foo\\n\\r\\b\\f\\t\\u000B\\u001B\"", "string JSON" );
t.is( serializeJSON(null), "null", "null JSON");
try {
serializeJSON(undefined);
t.ok(false, "undefined should not be serializable");
} catch (e) {
t.ok(e instanceof TypeError, "undefined not serializable");
}
t.is( serializeJSON(1), "1", "1 JSON");
t.is( serializeJSON(1.23), "1.23", "1.23 JSON");
t.is( serializeJSON(serializeJSON), null, "function JSON (null, not string)" );
t.is( serializeJSON([1, "2", 3.3]), "[1, \"2\", 3.3]", "array JSON" );
var res = evalJSON(serializeJSON({"a":1, "b":2}));
t.is( res.a, 1, "evalJSON on an object (1)" );
t.is( res.b, 2, "evalJSON on an object (2)" );
var res = {"a": 1, "b": 2, "json": function () { return this; }};
var res = evalJSON(serializeJSON(res));
t.is( res.a, 1, "evalJSON on an object that jsons self (1)" );
t.is( res.b, 2, "evalJSON on an object that jsons self (2)" );
var strJSON = {"a": 1, "b": 2, "json": function () { return "json"; }};
t.is( serializeJSON(strJSON), "\"json\"", "json serialization calling" );
t.is( serializeJSON([strJSON]), "[\"json\"]", "json serialization calling in a structure" );
t.is( evalJSON('/* {"result": 1} */').result, 1, "json comment stripping" );
t.is( evalJSON('/* {"*/ /*": 1} */')['*/ /*'], 1, "json comment stripping" );
registerJSON("isDateLike",
isDateLike,
function (d) {
return "this was a date";
}
);
t.is( serializeJSON(new Date()), "\"this was a date\"", "json registry" );
MochiKit.Base.jsonRegistry.unregister("isDateLike");
var a = {"foo": {"bar": 12, "wibble": 13}};
var b = {"foo": {"baz": 4, "bar": 16}, "bar": 4};
updatetree(a, b);
var expect = [["bar", 16], ["baz", 4], ["wibble", 13]];
var got = items(a.foo);
got.sort(compare);
t.is( repr(got), repr(expect), "updatetree merge" );
t.is( a.bar, 4, "updatetree insert" );
var aa = {"foo": {"bar": 12, "wibble": 13}};
var bb = {"foo": {"baz": 4, "bar": 16}, "bar": 4};
cc = updatetree(null, aa, bb);
got = items(cc.foo);
got.sort(compare);
t.is( repr(got), repr(expect), "updatetree merge (self is null)" );
t.is( cc.bar, 4, "updatetree insert (self is null)" );
cc = updatetree(undefined, aa, bb);
got = items(cc.foo);
got.sort(compare);
t.is( repr(got), repr(expect), "updatetree merge (self is undefined)" );
t.is( cc.bar, 4, "updatetree insert (self is undefined)" );
var c = counter();
t.is( c(), 1, "counter starts at 1" );
t.is( c(), 2, "counter increases" );
c = counter(2);
t.is( c(), 2, "counter starts at 2" );
t.is( c(), 3, "counter increases" );
t.is( findValue([1, 2, 3], 4), -1, "findValue returns -1 on not found");
t.is( findValue([1, 2, 3], 1), 0, "findValue returns correct index");
t.is( findValue([1, 2, 3], 1, 1), -1, "findValue honors start");
t.is( findValue([1, 2, 3], 2, 0, 1), -1, "findValue honors end");
t.is( findIdentical([1, 2, 3], 4), -1, "findIdentical returns -1");
t.is( findIdentical([1, 2, 3], 1), 0, "findIdentical returns correct index");
t.is( findIdentical([1, 2, 3], 1, 1), -1, "findIdentical honors start");
t.is( findIdentical([1, 2, 3], 2, 0, 1), -1, "findIdentical honors end");
var flat = flattenArguments(1, "2", 3, [4, [5, [6, 7], 8, [], 9]]);
var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9];
t.is( repr(flat), repr(expect), "flattenArguments" );
var fn = function () {
return [this, concat(arguments)];
}
t.is( methodcaller("toLowerCase")("FOO"), "foo", "methodcaller with a method name" );
t.is( repr(methodcaller(fn, 2, 3)(1)), "[1, [2, 3]]", "methodcaller with a function" );
var f1 = function (x) { return [1, x]; };
var f2 = function (x) { return [2, x]; };
var f3 = function (x) { return [3, x]; };
t.is( repr(f1(f2(f3(4)))), "[1, [2, [3, 4]]]", "test the compose test" );
t.is( repr(compose(f1,f2,f3)(4)), "[1, [2, [3, 4]]]", "three fn composition works" );
t.is( repr(compose(compose(f1,f2),f3)(4)), "[1, [2, [3, 4]]]", "associative left" );
t.is( repr(compose(f1,compose(f2,f3))(4)), "[1, [2, [3, 4]]]", "associative right" );
try {
compose(f1, "foo");
t.ok( false, "wrong compose argument not raised!" );
} catch (e) {
t.is( e.name, 'TypeError', "wrong compose argument raised correctly" );
}
t.is(camelize('one'), 'one', 'one word');
t.is(camelize('one-two'), 'oneTwo', 'two words');
t.is(camelize('one-two-three'), 'oneTwoThree', 'three words');
t.is(camelize('1-one'), '1One', 'letter and word');
t.is(camelize('one-'), 'one', 'trailing hyphen');
t.is(camelize('-one'), 'One', 'starting hyphen');
t.is(camelize('o-two'), 'oTwo', 'one character and word');
var flat = flattenArray([1, "2", 3, [4, [5, [6, 7], 8, [], 9]]]);
var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9];
t.is( repr(flat), repr(expect), "flattenArray" );
/* mean */
try {
mean();
t.ok( false, "mean no arguments didn't raise!" );
} catch (e) {
t.is( e.name, 'TypeError', "no arguments raised correctly" );
}
t.is( mean(1), 1, 'single argument (arg list)');
t.is( mean([1]), 1, 'single argument (array)');
t.is( mean(1,2,3), 2, 'three arguments (arg list)');
t.is( mean([1,2,3]), 2, 'three arguments (array)');
t.is( average(1), 1, 'test the average alias');
/* median */
try {
median();
t.ok( false, "median no arguments didn't raise!" );
} catch (e) {
t.is( e.name, 'TypeError', "no arguments raised correctly" );
}
t.is( median(1), 1, 'single argument (arg list)');
t.is( median([1]), 1, 'single argument (array)');
t.is( median(3,1,2), 2, 'three arguments (arg list)');
t.is( median([3,1,2]), 2, 'three arguments (array)');
t.is( median(3,1,2,4), 2.5, 'four arguments (arg list)');
t.is( median([3,1,2,4]), 2.5, 'four arguments (array)');
/* #185 */
t.is( serializeJSON(parseQueryString("")), "{}", "parseQueryString('')" );
t.is( serializeJSON(parseQueryString("", true)), "{}", "parseQueryString('', true)" );
/* #109 */
t.is( queryString({ids: [1,2,3]}), "ids=1&ids=2&ids=3", "queryString array value" );
t.is( queryString({ids: "123"}), "ids=123", "queryString string value" );
/* test values */
var o = {a: 1, b: 2, c: 4, d: -1};
var got = values(o);
got.sort();
t.is( repr(got), repr([-1, 1, 2, 4]), "values()" );
t.is( queryString([["foo", "bar"], ["baz", "wibble"]]), "foo=baz&bar=wibble" );
o = parseQueryString("foo=1=1=1&bar=2&baz&wibble=");
t.is( o.foo, "1=1=1", "parseQueryString multiple = first" );
t.is( o.bar, "2", "parseQueryString multiple = second" );
t.is( o.baz, "", "parseQueryString multiple = third" );
t.is( o.wibble, "", "parseQueryString multiple = fourth" );
/* queryString with null values */
t.is( queryString(["a", "b"], [1, null]), "a=1", "queryString with null value" );
t.is( queryString({"a": 1, "b": null}), "a=1", "queryString with null value" );
var reprFunc = function (a, b) {
return;
}
t.is( repr(reprFunc), "function (a, b) {...}", "repr of function" );
};

View file

@ -0,0 +1,137 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Color'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Color'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_Color = function (t) {
var approx = function (a, b, msg) {
return t.is(a.toPrecision(4), b.toPrecision(4), msg);
};
t.is( Color.whiteColor().toHexString(), "#ffffff", "whiteColor has right hex" );
t.is( Color.blackColor().toHexString(), "#000000", "blackColor has right hex" );
t.is( Color.blueColor().toHexString(), "#0000ff", "blueColor has right hex" );
t.is( Color.redColor().toHexString(), "#ff0000", "redColor has right hex" );
t.is( Color.greenColor().toHexString(), "#00ff00", "greenColor has right hex" );
t.is( compare(Color.whiteColor(), Color.whiteColor()), 0, "default colors compare right" );
t.ok( Color.whiteColor() == Color.whiteColor(), "default colors are interned" );
t.ok( Color.whiteColor().toRGBString(), "rgb(255,255,255)", "toRGBString white" );
t.ok( Color.blueColor().toRGBString(), "rgb(0,0,255)", "toRGBString blue" );
t.is( Color.fromRGB(190/255, 222/255, 173/255).toHexString(), "#bedead", "fromRGB works" );
t.is( Color.fromRGB(226/255, 15.9/255, 182/255).toHexString(), "#e210b6", "fromRGB < 16 works" );
t.is( Color.fromRGB({r:190/255,g:222/255,b:173/255}).toHexString(), "#bedead", "alt fromRGB works" );
t.is( Color.fromHexString("#bedead").toHexString(), "#bedead", "round-trip hex" );
t.is( Color.fromString("#bedead").toHexString(), "#bedead", "round-trip string(hex)" );
t.is( Color.fromRGBString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" );
t.is( Color.fromString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" );
var hsl = Color.redColor().asHSL();
approx( hsl.h, 0.0, "red hsl.h" );
approx( hsl.s, 1.0, "red hsl.s" );
approx( hsl.l, 0.5, "red hsl.l" );
hsl = Color.fromRGB(0, 0, 0.5).asHSL();
approx( hsl.h, 2/3, "darkblue hsl.h" );
approx( hsl.s, 1.0, "darkblue hsl.s" );
approx( hsl.l, 0.25, "darkblue hsl.l" );
hsl = Color.fromString("#4169E1").asHSL();
approx( hsl.h, (5/8), "4169e1 h");
approx( hsl.s, (8/11), "4169e1 s");
approx( hsl.l, (29/51), "4169e1 l");
hsl = Color.fromString("#555544").asHSL();
approx( hsl.h, (1/6), "555544 h" );
approx( hsl.s, (1/9), "555544 s" );
approx( hsl.l, (3/10), "555544 l" );
hsl = Color.fromRGB(0.5, 1, 0.5).asHSL();
approx( hsl.h, 1/3, "aqua hsl.h" );
approx( hsl.s, 1.0, "aqua hsl.s" );
approx( hsl.l, 0.75, "aqua hsl.l" );
t.is(
Color.fromHSL(hsl.h, hsl.s, hsl.l).toHexString(),
Color.fromRGB(0.5, 1, 0.5).toHexString(),
"fromHSL works with components"
);
t.is(
Color.fromHSL(hsl).toHexString(),
Color.fromRGB(0.5, 1, 0.5).toHexString(),
"fromHSL alt form"
);
t.is(
Color.fromString("hsl(120,100%,75%)").toHexString(),
"#80ff80",
"fromHSLString"
);
t.is(
Color.fromRGB(0.5, 1, 0.5).toHSLString(),
"hsl(120,100.0%,75.00%)",
"toHSLString"
);
t.is( Color.fromHSL(0, 0, 0).toHexString(), "#000000", "fromHSL to black" );
hsl = Color.blackColor().asHSL();
approx( hsl.h, 0.0, "black hsl.h" );
approx( hsl.s, 0.0, "black hsl.s" );
approx( hsl.l, 0.0, "black hsl.l" );
hsl.h = 1.0;
hsl = Color.blackColor().asHSL();
approx( hsl.h, 0.0, "asHSL returns copy" );
var rgb = Color.brownColor().asRGB();
approx( rgb.r, 153/255, "brown rgb.r" );
approx( rgb.g, 102/255, "brown rgb.g" );
approx( rgb.b, 51/255, "brown rgb.b" );
rgb.r = 0;
rgb = Color.brownColor().asRGB();
approx( rgb.r, 153/255, "asRGB returns copy" );
t.is( Color.fromName("aqua").toHexString(), "#00ffff", "aqua fromName" );
t.is( Color.fromString("aqua").toHexString(), "#00ffff", "aqua fromString" );
t.is( Color.fromName("transparent"), Color.transparentColor(), "transparent fromName" );
t.is( Color.fromString("transparent"), Color.transparentColor(), "transparent fromString" );
t.is( Color.transparentColor().toRGBString(), "rgba(0,0,0,0)", "transparent toRGBString" );
t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").asRGB().a, 0.5, "rgba parsing alpha correctly" );
t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").toRGBString(), "rgba(0,255,255,0.5)", "rgba output correctly" );
t.is( Color.fromRGBString("rgba( 0, 255, 255, 1)").toHexString(), "#00ffff", "fromRGBString with spaces and alpha" );
t.is( Color.fromRGBString("rgb( 0, 255, 255)").toHexString(), "#00ffff", "fromRGBString with spaces" );
t.is( Color.fromRGBString("rgb( 0, 100%, 255)").toHexString(), "#00ffff", "fromRGBString with percents" );
var hsv = Color.redColor().asHSV();
approx( hsv.h, 0.0, "red hsv.h" );
approx( hsv.s, 1.0, "red hsv.s" );
approx( hsv.v, 1.0, "red hsv.v" );
t.is( Color.fromHSV(hsv).toHexString(), Color.redColor().toHexString(), "red hexstring" );
hsv = Color.fromRGB(0, 0, 0.5).asHSV();
approx( hsv.h, 2/3, "darkblue hsv.h" );
approx( hsv.s, 1.0, "darkblue hsv.s" );
approx( hsv.v, 0.5, "darkblue hsv.v" );
t.is( Color.fromHSV(hsv).toHexString(), Color.fromRGB(0, 0, 0.5).toHexString(), "darkblue hexstring" );
hsv = Color.fromString("#4169E1").asHSV();
approx( hsv.h, 5/8, "4169e1 h");
approx( hsv.s, 32/45, "4169e1 s");
approx( hsv.v, 15/17, "4169e1 l");
t.is( Color.fromHSV(hsv).toHexString(), "#4169e1", "4169e1 hexstring" );
hsv = Color.fromString("#555544").asHSV();
approx( hsv.h, 1/6, "555544 h" );
approx( hsv.s, 1/5, "555544 s" );
approx( hsv.v, 1/3, "555544 l" );
t.is( Color.fromHSV(hsv).toHexString(), "#555544", "555544 hexstring" );
hsv = Color.fromRGB(0.5, 1, 0.5).asHSV();
approx( hsv.h, 1/3, "aqua hsv.h" );
approx( hsv.s, 0.5, "aqua hsv.s" );
approx( hsv.v, 1, "aqua hsv.v" );
t.is(
Color.fromHSV(hsv.h, hsv.s, hsv.v).toHexString(),
Color.fromRGB(0.5, 1, 0.5).toHexString(),
"fromHSV works with components"
);
t.is(
Color.fromHSV(hsv).toHexString(),
Color.fromRGB(0.5, 1, 0.5).toHexString(),
"fromHSV alt form"
);
hsv = Color.fromRGB(1, 1, 1).asHSV()
approx( hsv.h, 0, 'white hsv.h' );
approx( hsv.s, 0, 'white hsv.s' );
approx( hsv.v, 1, 'white hsv.v' );
t.is(
Color.fromHSV(0, 0, 1).toHexString(),
'#ffffff',
'HSV saturation'
);
};

View file

@ -0,0 +1,52 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.DateTime'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.DateTime'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_DateTime = function (t) {
var testDate = isoDate('2005-2-3');
t.is(testDate.getFullYear(), 2005, "isoDate year ok");
t.is(testDate.getDate(), 3, "isoDate day ok");
t.is(testDate.getMonth(), 1, "isoDate month ok");
t.ok(objEqual(testDate, new Date("February 3, 2005")), "matches string date");
t.is(toISODate(testDate), '2005-02-03', 'toISODate ok');
var testDate = isoDate('2005-06-08');
t.is(testDate.getFullYear(), 2005, "isoDate year ok");
t.is(testDate.getDate(), 8, "isoDate day ok");
t.is(testDate.getMonth(), 5, "isoDate month ok");
t.ok(objEqual(testDate, new Date("June 8, 2005")), "matches string date");
t.is(toISODate(testDate), '2005-06-08', 'toISODate ok');
var testDate = isoDate('0500-12-12');
t.is(testDate.getFullYear(), 500, 'isoDate year ok for year < 1000');
t.is(testDate.getDate(), 12, 'isoDate day ok for year < 1000');
t.is(testDate.getMonth(), 11, 'isoDate month ok for year < 1000');
t.ok(objEqual(testDate, new Date("December 12, 0500")), "matches string date for year < 1000");
t.is(toISODate(testDate), '0500-12-12', 'toISODate ok for year < 1000');
t.is(compare(new Date("February 3, 2005"), new Date(2005, 1, 3)), 0, "dates compare eq");
t.is(compare(new Date("February 3, 2005"), new Date(2005, 2, 3)), -1, "dates compare lt");
t.is(compare(new Date("February 3, 2005"), new Date(2005, 0, 3)), 1, "dates compare gt");
var testDate = isoDate('2005-2-3');
t.is(compare(americanDate('2/3/2005'), testDate), 0, "americanDate eq");
t.is(compare('2/3/2005', toAmericanDate(testDate)), 0, "toAmericanDate eq");
var testTimestamp = isoTimestamp('2005-2-3 22:01:03');
t.is(compare(testTimestamp, new Date(2005,1,3,22,1,3)), 0, "isoTimestamp eq");
t.is(compare(testTimestamp, isoTimestamp('2005-2-3T22:01:03')), 0, "isoTimestamp (real ISO) eq");
t.is(compare(toISOTimestamp(testTimestamp), '2005-02-03 22:01:03'), 0, "toISOTimestamp eq");
testTimestamp = isoTimestamp('2005-2-3T22:01:03Z');
t.is(toISOTimestamp(testTimestamp, true), '2005-02-03T22:01:03Z', "toISOTimestamp (real ISO) eq");
var localTZ = Math.round((new Date(2005,1,3,22,1,3)).getTimezoneOffset()/60)
var direction = (localTZ < 0) ? "+" : "-";
localTZ = Math.abs(localTZ);
localTZ = direction + ((localTZ < 10) ? "0" : "") + localTZ;
testTimestamp = isoTimestamp("2005-2-3T22:01:03" + localTZ);
var testDateTimestamp = new Date(2005,1,3,22,1,3);
t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with local tz");
testTimestamp = isoTimestamp("2005-2-3T17:01:03-05");
var testDateTimestamp = new Date(Date.UTC(2005,1,3,22,1,3));
t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with specific tz");
};

View file

@ -0,0 +1,30 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_DragAndDrop = function (t) {
var drag1 = new MochiKit.DragAndDrop.Draggable('drag1', {'revert': true, 'ghosting': true});
var drop1 = new MochiKit.DragAndDrop.Droppable('drop1', {'hoverclass': 'drop-hover'});
drop1.activate();
t.is(hasElementClass('drop1', 'drop-hover'), true, "hoverclass ok");
drop1.deactivate();
t.is(hasElementClass('drop1', 'drop-hover'), false, "remove hoverclass ok");
drop1.destroy();
t.is( isEmpty(MochiKit.DragAndDrop.Droppables.drops), true, "Unregister droppable ok");
var onhover = function (element) {
t.is(element, getElement('drag1'), 'onhover ok');
};
var drop2 = new MochiKit.DragAndDrop.Droppable('drop1', {'onhover': onhover});
var pos = getElementPosition('drop1');
pos = {"x": pos.x + 5, "y": pos.y + 5};
MochiKit.DragAndDrop.Droppables.show({"page": pos}, getElement('drag1'));
drag1.destroy();
t.is( isEmpty(MochiKit.DragAndDrop.Draggables.drops), true, "Unregister draggable ok");
};

View file

@ -0,0 +1,89 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Format'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Format'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_Format = function (t) {
t.is( truncToFixed(0.1234, 3), "0.123", "truncToFixed truncate" );
t.is( truncToFixed(0.12, 3), "0.120", "truncToFixed trailing zeros" );
t.is( truncToFixed(0.15, 1), "0.1", "truncToFixed no round" );
t.is( truncToFixed(0.15, 0), "0", "truncToFixed zero (edge case)" );
t.is( truncToFixed(568.80, 2), "568.80", "truncToFixed 568.80, floating-point error" );
t.is( truncToFixed(1.23e+20, 2), "123000000000000000000.00", "truncToFixed 1.23e+20" );
t.is( truncToFixed(-1.23e+20, 2), "-123000000000000000000.00", "truncToFixed -1.23e+20" );
t.is( truncToFixed(1.23e-10, 2), "0.00", "truncToFixed 1.23e-10" );
t.is( roundToFixed(0.1234, 3), "0.123", "roundToFixed truncate" );
t.is( roundToFixed(0.12, 3), "0.120", "roundToFixed trailing zeros" );
t.is( roundToFixed(0.15, 1), "0.2", "roundToFixed round" );
t.is( roundToFixed(0.15, 0), "0", "roundToFixed zero (edge case)" );
t.is( roundToFixed(568.80, 2), "568.80", "roundToFixed 568.80, floating-point error" );
t.is( twoDigitFloat(-0.1234), "-0.12", "twoDigitFloat -0.1234 correct");
t.is( twoDigitFloat(-0.1), "-0.1", "twoDigitFloat -0.1 correct");
t.is( twoDigitFloat(-0), "0", "twoDigitFloat -0 correct");
t.is( twoDigitFloat(0), "0", "twoDigitFloat 0 correct");
t.is( twoDigitFloat(1), "1", "twoDigitFloat 1 correct");
t.is( twoDigitFloat(1.0), "1", "twoDigitFloat 1.0 correct");
t.is( twoDigitFloat(1.2), "1.2", "twoDigitFloat 1.2 correct");
t.is( twoDigitFloat(1.234), "1.23", "twoDigitFloat 1.234 correct");
t.is( twoDigitFloat(0.23), "0.23", "twoDigitFloat 0.23 correct");
t.is( twoDigitFloat(0.01), "0.01", "twoDigitFloat 0.01 correct");
t.is( twoDigitFloat(568.80), "568.8", "twoDigitFloat, floating-point error");
t.is( percentFormat(123), "12300%", "percentFormat 123 correct");
t.is( percentFormat(1.23), "123%", "percentFormat 123 correct");
t.is( twoDigitAverage(1, 0), "0", "twoDigitAverage dbz correct");
t.is( twoDigitAverage(1, 1), "1", "twoDigitAverage 1 correct");
t.is( twoDigitAverage(1, 10), "0.1", "twoDigitAverage .1 correct");
function reprIs(a, b) {
arguments[0] = repr(a);
arguments[1] = repr(b);
t.is.apply(this, arguments);
}
reprIs( lstrip("\r\t\n foo \n\t\r"), "foo \n\t\r", "lstrip whitespace chars" );
reprIs( rstrip("\r\t\n foo \n\t\r"), "\r\t\n foo", "rstrip whitespace chars" );
reprIs( strip("\r\t\n foo \n\t\r"), "foo", "strip whitespace chars" );
reprIs( lstrip("\r\n\t \r", "\r"), "\n\t \r", "lstrip custom chars" );
reprIs( rstrip("\r\n\t \r", "\r"), "\r\n\t ", "rstrip custom chars" );
reprIs( strip("\r\n\t \r", "\r"), "\n\t ", "strip custom chars" );
var nf = numberFormatter("$###,###.00 footer");
t.is( nf(1000.1), "$1,000.10 footer", "trailing zeros" );
t.is( nf(1000000.1), "$1,000,000.10 footer", "two seps" );
t.is( nf(100), "$100.00 footer", "shorter than sep" );
t.is( nf(100.555), "$100.56 footer", "rounding" );
t.is( nf(-100.555), "$-100.56 footer", "default neg" );
nf = numberFormatter("-$###,###.00");
t.is( nf(-100.555), "-$100.56", "custom neg" );
nf = numberFormatter("0000.0000");
t.is( nf(0), "0000.0000", "leading and trailing" );
t.is( nf(1.1), "0001.1000", "leading and trailing" );
t.is( nf(12345.12345), "12345.1235", "no need for leading/trailing" );
nf = numberFormatter("0000.0000");
t.is( nf("taco"), "", "default placeholder" );
nf = numberFormatter("###,###.00", "foo", "de_DE");
t.is( nf("taco"), "foo", "custom placeholder" );
t.is( nf(12345.12345), "12.345,12", "de_DE locale" );
nf = numberFormatter("#%");
t.is( nf(1), "100%", "trivial percent" );
t.is( nf(0.55), "55%", "percent" );
var customLocale = {
separator: " apples and ",
decimal: " bagels at ",
percent: "am for breakfast"};
var customFormatter = numberFormatter("###,###.0%", "No breakfast", customLocale);
t.is( customFormatter(23.458), "2 apples and 345 bagels at 8am for breakfast", "custom locale" );
nf = numberFormatter("###,###");
t.is( nf(123), "123", "large number format" );
t.is( nf(1234), "1,234", "large number format" );
t.is( nf(12345), "12,345", "large number format" );
t.is( nf(123456), "123,456", "large number format" );
t.is( nf(1234567), "1,234,567", "large number format" );
t.is( nf(12345678), "12,345,678", "large number format" );
t.is( nf(123456789), "123,456,789", "large number format" );
t.is( nf(1234567890), "1,234,567,890", "large number format" );
t.is( nf(12345678901), "12,345,678,901", "large number format" );
t.is( nf(123456789012), "123,456,789,012", "large number format" );
};

View file

@ -0,0 +1,186 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Iter'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Iter'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_Iter = function (t) {
t.is( sum([1, 2, 3, 4, 5]), 15, "sum works on Arrays" );
t.is( compare(list([1, 2, 3]), [1, 2, 3]), 0, "list([x]) == [x]" );
t.is( compare(list(range(6, 0, -1)), [6, 5, 4, 3, 2, 1]), 0, "list(range(6, 0, -1)");
t.is( compare(list(range(6)), [0, 1, 2, 3, 4, 5]), 0, "list(range(6))" );
var moreThanTwo = partial(operator.lt, 2);
t.is( sum(ifilter(moreThanTwo, range(6))), 12, "sum(ifilter(, range()))" );
t.is( sum(ifilterfalse(moreThanTwo, range(6))), 3, "sum(ifilterfalse(, range()))" );
var c = count(10);
t.is( compare([c.next(), c.next(), c.next()], [10, 11, 12]), 0, "count()" );
c = cycle([1, 2]);
t.is( compare([c.next(), c.next(), c.next()], [1, 2, 1]), 0, "cycle()" );
c = repeat("foo", 3);
t.is( compare(list(c), ["foo", "foo", "foo"]), 0, "repeat()" );
c = izip([1, 2], [3, 4, 5], repeat("foo"));
t.is( compare(list(c), [[1, 3, "foo"], [2, 4, "foo"]]), 0, "izip()" );
t.is( compare(list(range(5)), [0, 1, 2, 3, 4]), 0, "range(x)" );
c = islice(range(10), 0, 10, 2);
t.is( compare(list(c), [0, 2, 4, 6, 8]), 0, "islice(x, y, z)" );
c = imap(operator.add, [1, 2, 3], [2, 4, 6]);
t.is( compare(list(c), [3, 6, 9]), 0, "imap(fn, p, q)" );
c = filter(partial(operator.lt, 1), iter([1, 2, 3]));
t.is( compare(c, [2, 3]), 0, "filter(fn, iterable)" );
c = map(partial(operator.add, -1), iter([1, 2, 3]));
t.is( compare(c, [0, 1, 2]), 0, "map(fn, iterable)" );
c = map(operator.add, iter([1, 2, 3]), [2, 4, 6]);
t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, q)" );
c = map(operator.add, iter([1, 2, 3]), iter([2, 4, 6]));
t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, iterable)" );
c = applymap(operator.add, [[1, 2], [2, 4], [3, 6]]);
t.is( compare(list(c), [3, 6, 9]), 0, "applymap()" );
c = applymap(function (a) { return [this, a]; }, [[1], [2]], 1);
t.is( compare(list(c), [[1, 1], [1, 2]]), 0, "applymap(self)" );
c = chain(range(2), range(3));
t.is( compare(list(c), [0, 1, 0, 1, 2]), 0, "chain(p, q)" );
var lessThanFive = partial(operator.gt, 5);
c = takewhile(lessThanFive, count());
t.is( compare(list(c), [0, 1, 2, 3, 4]), 0, "takewhile()" );
c = dropwhile(lessThanFive, range(10));
t.is( compare(list(c), [5, 6, 7, 8, 9]), 0, "dropwhile()" );
c = tee(range(5), 3);
t.is( compare(list(c[0]), list(c[1])), 0, "tee(..., 3) p0 == p1" );
t.is( compare(list(c[2]), [0, 1, 2, 3, 4]), 0, "tee(..., 3) p2 == fixed" );
t.is( compare(reduce(operator.add, range(10)), 45), 0, "reduce(op.add)" );
try {
reduce(operator.add, []);
t.ok( false, "reduce didn't raise anything with empty list and no start?!" );
} catch (e) {
if (e instanceof TypeError) {
t.ok( true, "reduce raised TypeError correctly" );
} else {
t.ok( false, "reduce raised the wrong exception?" );
}
}
t.is( reduce(operator.add, [], 10), 10, "range initial value OK empty" );
t.is( reduce(operator.add, [1], 10), 11, "range initial value OK populated" );
t.is( compare(iextend([1], range(2)), [1, 0, 1]), 0, "iextend(...)" );
var rval = [];
var o = [0, 1, 2, 3];
o.next = range(2).next;
t.is( iextend([], o).length, 2, "iextend handles array-like iterables" );
var x = [];
exhaust(imap(bind(x.push, x), range(5)));
t.is( compare(x, [0, 1, 2, 3, 4]), 0, "exhaust(...)" );
t.is( every([1, 2, 3, 4, 5, 4], lessThanFive), false, "every false" );
t.is( every([1, 2, 3, 4, 4], lessThanFive), true, "every true" );
t.is( some([1, 2, 3, 4, 4], lessThanFive), true, "some true" );
t.is( some([5, 6, 7, 8, 9], lessThanFive), false, "some false" );
t.is( some([5, 6, 7, 8, 4], lessThanFive), true, "some true" );
var rval = [];
forEach(range(2), rval.push, rval);
t.is( compare(rval, [0, 1]), 0, "forEach works bound" );
function foo(o) {
rval.push(o);
}
forEach(range(2), foo);
t.is( compare(rval, [0, 1, 0, 1]), 0, "forEach works unbound" );
var rval = [];
var o = [0, 1, 2, 3];
o.next = range(2).next;
forEach(o, rval.push, rval);
t.is( rval.length, 2, "forEach handles array-like iterables" );
t.is( compare(sorted([3, 2, 1]), [1, 2, 3]), 0, "sorted default" );
rval = sorted(["aaa", "bb", "c"], keyComparator("length"));
t.is(compare(rval, ["c", "bb", "aaa"]), 0, "sorted custom");
t.is( compare(reversed(range(4)), [3, 2, 1, 0]), 0, "reversed iterator" );
t.is( compare(reversed([5, 6, 7]), [7, 6, 5]), 0, "reversed list" );
var o = {lst: [1, 2, 3], iterateNext: function () { return this.lst.shift(); }};
t.is( compare(list(o), [1, 2, 3]), 0, "iterateNext" );
function except(exc, func) {
try {
func();
t.ok(false, exc.name + " was not raised.");
} catch (e) {
if (e == exc) {
t.ok( true, "raised " + exc.name + " correctly" );
} else {
t.ok( false, "raised the wrong exception?" );
}
}
}
odd = partial(operator.and, 1)
// empty
grouped = groupby([]);
except(StopIteration, grouped.next);
// exhaust sub-iterator
grouped = groupby([2,4,6,7], odd);
kv = grouped.next(); k = kv[0], subiter = kv[1];
t.is(k, 0, "odd(2) = odd(4) = odd(6) == 0");
t.is(subiter.next(), 2, "sub-iterator.next() == 2");
t.is(subiter.next(), 4, "sub-iterator.next() == 4");
t.is(subiter.next(), 6, "sub-iterator.next() == 6");
except(StopIteration, subiter.next);
kv = grouped.next(); key = kv[0], subiter = kv[1];
t.is(key, 1, "odd(7) == 1");
t.is(subiter.next(), 7, "sub-iterator.next() == 7");
except(StopIteration, subiter.next);
// not consume sub-iterator
grouped = groupby([2,4,6,7], odd);
kv = grouped.next(); key = kv[0], subiter = kv[1];
t.is(key, 0, "0 = odd(2) = odd(4) = odd(6)");
kv = grouped.next(); key = kv[0], subiter = kv[1];
t.is(key, 1, "1 = odd(7)");
except(StopIteration, grouped.next);
// consume sub-iterator partially
grouped = groupby([3,1,1,2], odd);
kv = grouped.next(); key = kv[0], subiter = kv[1];
t.is(key, 1, "odd(1) == 1");
t.is(subiter.next(), 3, "sub-iterator.next() == 3");
kv = grouped.next(); key = kv[0], v = kv[1];
t.is(key, 0, "skip (1,1), odd(2) == 0");
except(StopIteration, grouped.next);
// null
grouped = groupby([null,null]);
kv = grouped.next(); k = kv[0], v = kv[1];
t.is(k, null, "null ok");
// groupby - array version
isEqual = (t.isDeeply || function (a, b, msg) {
return t.ok(compare(a, b) == 0, msg);
});
isEqual(groupby_as_array([ ] ), [ ], "empty");
isEqual(groupby_as_array([1,1,1]), [ [1,[1,1,1]] ], "[1,1,1]: [1,1,1]");
isEqual(groupby_as_array([1,2,2]), [ [1,[1] ], [2,[2,2]] ], "[1,2,2]: [1], [2,2]");
isEqual(groupby_as_array([1,1,2]), [ [1,[1,1] ], [2,[2 ]] ], "[1,1,2]: [1,1], [2]");
isEqual(groupby_as_array([null,null] ), [ [null,[null,null]] ], "[null,null]: [null,null]");
grouped = groupby_as_array([1,1,3,2,4,6,8], odd);
isEqual(grouped, [[1, [1,1,3]], [0,[2,4,6,8]]], "[1,1,3,2,4,6,7] odd: [1,1,3], [2,4,6,8]");
};

View file

@ -0,0 +1,88 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Logging'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Logging'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_Logging = function (t) {
// just in case
logger.clear();
t.is( logLevelAtLeast('DEBUG')('INFO'), false, 'logLevelAtLeast false' );
t.is( logLevelAtLeast('WARNING')('INFO'), false, 'logLevelAtLeast true' );
t.ok( logger instanceof Logger, "global logger installed" );
var allMessages = [];
logger.addListener("allMessages", null,
bind(allMessages.push, allMessages));
var fatalMessages = [];
logger.addListener("fatalMessages", "FATAL",
bind(fatalMessages.push, fatalMessages));
var firstTwo = [];
logger.addListener("firstTwo", null,
bind(firstTwo.push, firstTwo));
log("foo");
var msgs = logger.getMessages();
t.is( msgs.length, 1, 'global log() put one message in queue' );
t.is( compare(allMessages, msgs), 0, "allMessages listener" );
var msg = msgs.pop();
t.is( compare(msg.info, ["foo"]), 0, "info matches" );
t.is( msg.level, "INFO", "level matches" );
logDebug("debugFoo");
t.is( msgs.length, 0, 'getMessages() returns copy' );
msgs = logger.getMessages();
t.is( compare(allMessages, msgs), 0, "allMessages listener" );
t.is( msgs.length, 2, 'logDebug()' );
msg = msgs.pop();
t.is( compare(msg.info, ["debugFoo"]), 0, "info matches" );
t.is( msg.level, "DEBUG", "level matches" );
logger.removeListener("firstTwo");
logError("errorFoo");
msgs = logger.getMessages();
t.is( compare(allMessages, msgs), 0, "allMessages listener" );
t.is( msgs.length, 3, 'logError()' );
msg = msgs.pop();
t.is( compare(msg.info, ["errorFoo"]), 0, "info matches" );
t.is( msg.level, "ERROR", "level matches" );
logWarning("warningFoo");
msgs = logger.getMessages();
t.is( compare(allMessages, msgs), 0, "allMessages listener" );
t.is( msgs.length, 4, 'logWarning()' );
msg = msgs.pop();
t.is( compare(msg.info, ["warningFoo"]), 0, "info matches" );
t.is( msg.level, "WARNING", "level matches" );
logFatal("fatalFoo");
msgs = logger.getMessages();
t.is( compare(allMessages, msgs), 0, "allMessages listener" );
t.is( msgs.length, 5, 'logFatal()' );
msg = msgs.pop();
t.is( compare(fatalMessages, [msg]), 0, "fatalMessages listener" );
t.is( compare(msg.info, ["fatalFoo"]), 0, "info matches" );
t.is( msg.level, "FATAL", "level matches" );
msgs = logger.getMessages(1);
t.is( compare(fatalMessages, msgs), 0, "getMessages with limit returns latest" );
logger.removeListener("allMessages");
logger.removeListener("fatalMessages");
t.is( compare(firstTwo, logger.getMessages().slice(0, 2)), 0, "firstTwo" );
logger.clear();
msgs = logger.getMessages();
t.is(msgs.length, 0, "clear removes existing messages");
logger.baseLog(LogLevel.INFO, 'infoFoo');
msg = logger.getMessages().pop();
t.is(msg.level, "INFO", "baseLog converts level")
logger.baseLog(45, 'errorFoo');
msg = logger.getMessages().pop();
t.is(msg.level, "ERROR", "baseLog converts ad-hoc level")
};

View file

@ -0,0 +1,408 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Async.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript">
try {
var increment = function (res) {
return res + 1;
}
var throwStuff = function (res) {
throw new GenericError(res);
}
var catchStuff = function (res) {
return res.message;
}
var returnError = function (res) {
return new GenericError(res);
}
var anythingOkCallback = function (msg) {
return function (res) {
ok(true, msg);
return res;
}
}
var testEqCallback = function () {
/*
sort of emulate how deferreds work in Twisted
for "convenient" testing
*/
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
return function (res) {
var nargs = args.slice();
nargs.unshift(res);
is.apply(this, nargs);
return res;
}
}
var neverHappen = function (d) {
ok(false, "this should never happen");
}
/*
Test normal Deferred operation
*/
var d = new Deferred();
d.addCallback(testEqCallback(1, "pre-deferred callback"));
d.callback(1);
d.addCallback(increment);
d.addCallback(testEqCallback(2, "post-deferred callback"));
d.addCallback(throwStuff);
d.addCallback(neverHappen);
d.addErrback(catchStuff);
d.addCallback(testEqCallback(2, "throw -> err, catch -> success"));
d.addCallback(returnError);
d.addCallback(neverHappen);
d.addErrback(catchStuff);
d.addCallback(testEqCallback(2, "return -> err, catch -> succcess"));
/*
Test Deferred cancellation
*/
var cancelled = function (d) {
ok(true, "canceller called!");
}
var cancelledError = function (res) {
ok(res instanceof CancelledError, "CancelledError here");
}
d = new Deferred(cancelled);
d.addCallback(neverHappen);
d.addErrback(cancelledError);
d.cancel();
/*
Test succeed / fail
*/
d = succeed(1).addCallback(testEqCallback(1, "succeed"));
// default error
d = fail().addCallback(neverHappen);
d = d.addErrback(anythingOkCallback("default fail"));
// default wrapped error
d = fail("web taco").addCallback(neverHappen).addErrback(catchStuff);
d = d.addCallback(testEqCallback("web taco", "wrapped fail"));
// default unwrapped error
d = fail(new GenericError("ugh")).addCallback(neverHappen).addErrback(catchStuff);
d = d.addCallback(testEqCallback("ugh", "unwrapped fail"));
/*
Test deferred dependencies
*/
var deferredIncrement = function (res) {
var rval = succeed(res);
rval.addCallback(increment);
return rval;
}
d = succeed(1).addCallback(deferredIncrement);
d = d.addCallback(testEqCallback(2, "dependent deferred succeed"));
var deferredFailure = function (res) {
return fail(res);
}
d = succeed("ugh").addCallback(deferredFailure).addErrback(catchStuff);
d = d.addCallback(testEqCallback("ugh", "dependent deferred fail"));
/*
Test double-calling, double-failing, etc.
*/
try {
succeed(1).callback(2);
neverHappen();
} catch (e) {
ok(e instanceof AlreadyCalledError, "double-call");
}
try {
fail(1).errback(2);
neverHappen();
} catch (e) {
ok(e instanceof AlreadyCalledError, "double-fail");
}
try {
d = succeed(1);
d.cancel();
d = d.callback(2);
ok(true, "swallowed one callback, no canceller");
d.callback(3);
neverHappen();
} catch (e) {
ok(e instanceof AlreadyCalledError, "swallow cancel");
}
try {
d = new Deferred(cancelled);
d.cancel();
d = d.callback(1);
neverHappen();
} catch (e) {
ok(e instanceof AlreadyCalledError, "non-swallowed cancel");
}
/* Test incorrect Deferred usage */
d = new Deferred();
try {
d.callback(new Deferred());
neverHappen();
} catch (e) {
ok (e instanceof Error, "deferred not allowed for callback");
}
d = new Deferred();
try {
d.errback(new Deferred());
neverHappen();
} catch (e) {
ok (e instanceof Error, "deferred not allowed for errback");
}
d = new Deferred();
(new Deferred()).addCallback(function () { return d; }).callback(1);
try {
d.addCallback(function () {});
neverHappen();
} catch (e) {
ok (e instanceof Error, "chained deferred not allowed to be re-used");
}
/*
evalJSONRequest test
*/
var fakeReq = {"responseText":'[1,2,3,4,"asdf",{"a":["b", "c"]}]'};
var obj = [1,2,3,4,"asdf",{"a":["b", "c"]}];
isDeeply(obj, evalJSONRequest(fakeReq), "evalJSONRequest");
try {
MochiKit.Async.getXMLHttpRequest();
ok(true, "getXMLHttpRequest");
} catch (e) {
ok(false, "no love from getXMLHttpRequest");
}
var lock = new DeferredLock();
var lst = [];
var pushNumber = function (x) {
return function (res) { lst.push(x); }
};
lock.acquire().addCallback(pushNumber(1));
is( compare(lst, [1]), 0, "lock acquired" );
lock.acquire().addCallback(pushNumber(2));
is( compare(lst, [1]), 0, "lock waiting for release" );
lock.acquire().addCallback(pushNumber(3));
is( compare(lst, [1]), 0, "lock waiting for release" );
lock.release();
is( compare(lst, [1, 2]), 0, "lock passed on" );
lock.release();
is( compare(lst, [1, 2, 3]), 0, "lock passed on" );
lock.release();
try {
lock.release();
ok( false, "over-release didn't raise" );
} catch (e) {
ok( true, "over-release raised" );
}
lock.acquire().addCallback(pushNumber(1));
is( compare(lst, [1, 2, 3, 1]), 0, "lock acquired" );
lock.release();
is( compare(lst, [1, 2, 3, 1]), 0, "lock released" );
var d = new Deferred();
lst = [];
d.addCallback(operator.add, 2);
d.addBoth(operator.add, 4);
d.addCallback(bind(lst.push, lst));
d.callback(1);
is( lst[0], 7, "auto-partial addCallback addBoth" );
d.addCallback(function () { throw new Error(); });
ebTest = function(a, b) {
map(bind(lst.push, lst), arguments);
};
d.addErrback(ebTest, "foo");
is( lst[1], "foo", "auto-partial errback" );
is( lst.length, 3, "auto-partial errback" );
/*
Test DeferredList
*/
var callList = [new Deferred(), new Deferred(), new Deferred()];
callList[0].addCallback(increment);
callList[1].addCallback(increment);
callList[2].addCallback(increment);
var defList = new DeferredList(callList);
ok(defList instanceof Deferred, "DeferredList looks like a Deferred");
callList[0].callback(3);
callList[1].callback(5);
callList[2].callback(4);
defList.addCallback(function (lst) {
is( arrayEqual(lst, [[true, 4], [true, 6], [true, 5]]), true,
"deferredlist result ok" );
});
/*
Test fireOnOneCallback
*/
var callList2 = [new Deferred(), new Deferred(), new Deferred()];
callList2[0].addCallback(increment);
callList2[1].addCallback(increment);
callList2[2].addCallback(increment);
var defList2 = new DeferredList(callList2, true);
callList2[1].callback(5);
callList2[0].callback(3);
callList2[2].callback(4);
defList2.addCallback(function (lst) {
is( arrayEqual(lst, [1, 6]), true, "deferredlist fireOnOneCallback ok" );
});
/*
Test fireOnOneErrback
*/
var callList3 = [new Deferred(), new Deferred(), new Deferred()];
callList3[0].addCallback(increment);
callList3[1].addCallback(throwStuff);
callList3[2].addCallback(increment);
var defList3 = new DeferredList(callList3, false, true);
defList3.callback = neverHappen;
callList3[0].callback(3);
callList3[1].callback("foo");
callList3[2].callback(4);
defList3.addErrback(function (err) {
is( err.message, "foo", "deferredlist fireOnOneErrback ok" );
});
/*
Test consumeErrors
*/
var callList4 = [new Deferred(), new Deferred(), new Deferred()];
callList4[0].addCallback(increment);
callList4[1].addCallback(throwStuff);
callList4[2].addCallback(increment);
var defList4 = new DeferredList(callList4, false, false, true);
defList4.addErrback(neverHappen);
callList4[1].addCallback(function (arg) {
is(arg, null, "deferredlist consumeErrors ok" );
});
callList4[0].callback(3);
callList4[1].callback("foo");
callList4[2].callback(4);
/*
Test gatherResults
*/
var callList5 = [new Deferred(), new Deferred(), new Deferred()];
callList5[0].addCallback(increment);
callList5[1].addCallback(increment);
callList5[2].addCallback(increment);
var gatherRet = gatherResults(callList5);
callList5[0].callback(3);
callList5[1].callback(5);
callList5[2].callback(4);
gatherRet.addCallback(function (lst) {
is( arrayEqual(lst, [4, 6, 5]), true,
"gatherResults result ok" );
});
/*
Test maybeDeferred
*/
var maybeDef = maybeDeferred(increment, 4);
maybeDef.addCallback(testEqCallback(5, "maybeDeferred sync ok"));
var maybeDef2 = deferredIncrement(8);
maybeDef2.addCallback(testEqCallback(9, "maybeDeferred async ok"));
ok( true, "synchronous test suite finished!");
var t = (new Date().getTime());
SimpleTest.waitForExplicitFinish();
checkCallLater = function (originalTime) {
is(originalTime, t, "argument passed in OK");
is(arguments.length, 1, "argument count right");
};
var lock = new DeferredLock();
withLock = function (msg) {
var cb = partial.apply(null, extend(null, arguments, 1));
var d = lock.acquire().addCallback(cb);
d.addErrback(ok, false, msg);
d.addCallback(function () {
ok(true, msg);
lock.release();
});
return d;
}
withLock("callLater", function () {
return callLater(0, checkCallLater, t);
});
withLock("wait", function () {
return wait(0, t).addCallback(checkCallLater);
});
withLock("loadJSONDoc", function () {
var d = loadJSONDoc("test_MochiKit-Async.json");
d.addCallback(function (doc) {
is(doc.passed, true, "loadJSONDoc passed");
});
d.addErrback(function (doc) {
ok(false, "loadJSONDoc failed");
});
return d;
});
lock.acquire().addCallback(function () {
ok(true, "async suite finished");
SimpleTest.finish();
});
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1 @@
{"passed": true}

View file

@ -0,0 +1,34 @@
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript" src="test_Base.js"></script>
<script type="text/javascript">
try {
tests.test_Base({ok:ok,is:is});
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,84 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<style type="text/css">.redtext {color: red}</style>
</head>
<body>
<div style="position:absolute; top: 0px; left:0px; width:0px; height:0px">
<span style="color: red" id="c_direct"></span>
<span class="redtext" id="c_indirect"></span>
</div>
<pre id="test">
<script type="text/javascript" src="test_Color.js"></script>
<script type="text/javascript">
try {
var t = {ok:ok, is:is};
tests.test_Color({ok:ok, is:is});
is(
Color.fromText(SPAN()).toHexString(),
"#000000",
"fromText no style"
);
is(
Color.fromText("c_direct").toHexString(),
Color.fromName("red").toHexString(),
"fromText direct style"
);
is(
Color.fromText("c_indirect").toHexString(),
Color.fromName("red").toHexString(),
"fromText indirect style"
);
is(
Color.fromComputedStyle("c_direct", "color").toHexString(),
Color.fromName("red").toHexString(),
"fromComputedStyle direct style"
);
is(
Color.fromComputedStyle("c_indirect", "color").toHexString(),
Color.fromName("red").toHexString(),
"fromComputedStyle indirect style"
);
is(
Color.fromBackground((SPAN(null, 'test'))).toHexString(),
Color.fromName("white").toHexString(),
"fromBackground with DOM"
);
// Done!
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,48 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript">
try {
for (var i = 0; i < 10000; i++) {
var n = document.createElement("DIV");
n.appendChild(document.createTextNode(""));
var list = MochiKit.Iter.list(n.childNodes);
var n2 = document.createElement("DIV");
appendChildNodes(n2, n.childNodes);
var n3 = document.createElement("DIV");
replaceChildNodes(n3, n2.childNodes);
}
ok( true, "Safari didn't crash! #213" );
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,363 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<div style="display: none;">
<form id="form_test">
<select name="select">
<option value="foo" selected="selected">foo</option>
<option value="bar">bar</option>
<option value="baz">baz</option>
</select>
<select name="selmultiple" multiple="multiple">
<option value="bar" selected="selected">bar</option>
<option value="baz" selected="selected">baz</option>
<option value="foo">foo</option>
</select>
<input type="hidden" name="hidden" value="test" />
<input type="radio" name="radio_off" value="1" />
<input type="radio" name="radio_off" value="2" />
<input type="radio" name="radio_off" value="3" />
<input type="radio" name="radio_on" value="1" />
<input type="radio" name="radio_on" value="2" checked="checked" />
<input type="radio" name="radio_on" value="3" />
</form>
<form id="form_test2">
<select name="selempty">
<option value="" selected="selected">foo</option>
</select>
<select name="selempty2">
<option selected="selected">foo</option>
</select>
</form>
<div id="parentTwo" class="two">
<div id="parentOne" class="one">
<div id="parentZero" class="zero">
<span id="child">child</span>
</div>
</div>
</div>
</div>
<pre id="test">
<script type="text/javascript">
try {
lst = [];
o = {"blah": function () { lst.push("original"); }};
addToCallStack(o, "blah", function () { lst.push("new"); }, true);
addToCallStack(o, "blah", function () { lst.push("stuff"); }, true);
is( typeof(o.blah), 'function', 'addToCallStack has a function' );
is( o.blah.callStack.length, 3, 'callStack length 3' );
o.blah();
is( lst.join(" "), "original new stuff", "callStack in correct order" );
is( o.blah, null, "set to null" );
lst = [];
o = {"blah": function () { lst.push("original"); }};
addToCallStack(o, "blah",
function () { lst.push("new"); return false;}, false);
addToCallStack(o, "blah", function () { lst.push("stuff"); }, false);
o.blah();
is( lst.join(" "), "original new", "callStack in correct order (abort)" );
o.blah();
is( lst.join(" "), "original new original new", "callStack in correct order (again)" );
is( escapeHTML("<>\"&bar"), "&lt;&gt;&quot;&amp;bar", "escapeHTML" ); // for emacs highlighting: "
var isDOM = function (value, expected, message) {
is( escapeHTML(toHTML(value)), escapeHTML(expected), message );
};
var d = document.createElement('span');
updateNodeAttributes(d, {"foo": "bar", "baz": "wibble"});
isDOM( d, '<span baz="wibble" foo="bar"/>', "updateNodeAttributes" );
var d = document.createElement('input');
d.value = "foo";
updateNodeAttributes(d, { value: "bar" });
is( d.value, 'bar', "updateNodeAttributes updates value property" );
is( d.getAttribute("value"), 'bar', "updateNodeAttributes updates value attribute" );
var d = document.createElement('span');
var o = { elem: SPAN(null, "foo"), __dom__: function() { return this.elem; } };
appendChildNodes(d, 'word up', [document.createElement('span')], o);
isDOM( d, '<span>word up<span/><span>foo</span></span>', 'appendChildNodes' );
removeElement(o);
isDOM( d, '<span>word up<span/></span>', 'removeElement using DOM Coercion Rules' );
replaceChildNodes(d, 'Think Different');
isDOM( d, '<span>Think Different</span>', 'replaceChildNodes' );
insertSiblingNodesBefore(d.childNodes[0], 'word up', document.createElement('span'));
isDOM( d, '<span>word up<span/>Think Different</span>', 'insertSiblingNodesBefore' );
insertSiblingNodesAfter(d.childNodes[0], 'purple monkey', document.createElement('span'));
isDOM( d, '<span>word uppurple monkey<span/><span/>Think Different</span>', 'insertSiblingNodesAfter' );
d = createDOM("span");
isDOM( d, "<span/>", "createDOM empty" );
d = createDOM("span", {"foo": "bar", "baz": "wibble"});
isDOM( d, '<span baz="wibble" foo="bar"/>', "createDOM attributes" );
d = createDOM("span", {"foo": "bar", "baz": "wibble", "spam": "egg"}, "one", "two", "three");
is( getNodeAttribute(d, 'foo'), "bar", "createDOM attribute" );
is( getNodeAttribute(d, 'baz'), "wibble", "createDOM attribute" );
is( getNodeAttribute(d, 'lang'), null, "getNodeAttribute on IE added attribute" );
is( getNodeAttribute("donotexist", 'foo'), null, "getNodeAttribute invalid node id" );
removeNodeAttribute(d, "spam");
is( scrapeText(d), "onetwothree", "createDOM contents" );
isDOM( d, '<span baz="wibble" foo="bar">onetwothree</span>', "createDOM contents" );
d = createDOM("span", null, function (f) {
return this.nodeName.toLowerCase() + "hi" + f.nodeName.toLowerCase();});
isDOM( d, '<span>spanhispan</span>', 'createDOM function call' );
d = createDOM("span", null, {msg: "hi", dom: function (f) {
return f.nodeName.toLowerCase() + this.msg; }});
isDOM( d, '<span>spanhi</span>', 'createDOM this.dom() call' );
d = createDOM("span", null, {msg: "hi", __dom__: function (f) {
return f.nodeName.toLowerCase() + this.msg; }});
isDOM( d, '<span>spanhi</span>', 'createDOM this.__dom__() call' );
d = createDOM("span", null, range(4));
isDOM( d, '<span>0123</span>', 'createDOM iterable' );
var d = {"taco": "pork"};
registerDOMConverter("taco",
function (o) { return !isUndefinedOrNull(o.taco); },
function (o) { return "Goddamn, I like " + o.taco + " tacos"; }
);
d = createDOM("span", null, d);
// not yet public API
domConverters.unregister("taco");
isDOM( d, "<span>Goddamn, I like pork tacos</span>", "createDOM with custom converter" );
is(
escapeHTML(toHTML(SPAN(null))),
escapeHTML(toHTML(createDOM("span", null))),
"createDOMFunc vs createDOM"
);
is( scrapeText(d), "Goddamn, I like pork tacos", "scrape OK" );
is( scrapeText(d, true).join(""), "Goddamn, I like pork tacos", "scrape Array OK" );
var st = DIV(null, STRONG(null, "d"), "oor ", STRONG(null, "f", SPAN(null, "r"), "a"), "me");
is( scrapeText(st), "door frame", "scrape in-order" );
ok( !isUndefinedOrNull(getElement("test")), "getElement might work" );
ok( !isUndefinedOrNull($("test")), "$ alias might work" );
ok( getElement("donotexist") === null, "getElement invalid id" );
d = createDOM("span", null, "one", "two");
swapDOM(d.childNodes[0], document.createTextNode("uno"));
isDOM( d, "<span>unotwo</span>", "swapDOM" );
var o = { elem: SPAN(null, "foo"), __dom__: function() { return this.elem; } };
swapDOM(d.childNodes[0], o);
isDOM( d, "<span><span>foo</span>two</span>", "swapDOM using DOM Coercion Rules" );
is( scrapeText(d, true).join(" "), "foo two", "multi-node scrapeText" );
/*
TODO:
addLoadEvent (async test?)
*/
d = createDOM("span", {"class": "foo"});
setElementClass(d, "bar baz");
ok( d.className == "bar baz", "setElementClass");
toggleElementClass("bar", d);
ok( d.className == "baz", "toggleElementClass: " + d.className);
toggleElementClass("bar", d);
ok( hasElementClass(d, "baz", "bar"),
"toggleElementClass 2: " + d.className);
addElementClass(d, "bar");
ok( hasElementClass(d, "baz", "bar"),
"toggleElementClass 3: " + d.className);
ok( addElementClass(d, "blah"), "addElementClass return");
ok( hasElementClass(d, "baz", "bar", "blah"), "addElementClass action");
ok( !hasElementClass(d, "not"), "hasElementClass single");
ok( !hasElementClass(d, "baz", "not"), "hasElementClass multiple");
ok( removeElementClass(d, "blah"), "removeElementClass" );
ok( !removeElementClass(d, "blah"), "removeElementClass again" );
ok( !hasElementClass(d, "blah"), "removeElementClass again (hasElement)" );
removeElementClass(d, "baz");
ok( !swapElementClass(d, "blah", "baz"), "false swapElementClass" );
ok( !hasElementClass(d, "baz"), "false swapElementClass from" );
ok( !hasElementClass(d, "blah"), "false swapElementClass to" );
addElementClass(d, "blah");
ok( swapElementClass(d, "blah", "baz"), "swapElementClass" );
ok( hasElementClass(d, "baz"), "swapElementClass has toClass" );
ok( !hasElementClass(d, "blah"), "swapElementClass !has fromClass" );
ok( !swapElementClass(d, "blah", "baz"), "swapElementClass twice" );
ok( hasElementClass(d, "baz"), "swapElementClass has toClass" );
ok( !hasElementClass(d, "blah"), "swapElementClass !has fromClass" );
ok( !hasElementClass("donotexist", "foo"), "hasElementClass invalid node id" );
TABLE;
TBODY;
TR;
var t = TABLE(null,
TBODY({"class": "foo bar", "id":"tbody0"},
TR({"class": "foo", "id":"tr0"}),
TR({"class": "bar", "id":"tr1"})
)
);
var matchElements = getElementsByTagAndClassName;
is(
map(itemgetter("id"), matchElements(null, "foo", t)).join(" "),
"tbody0 tr0",
"getElementsByTagAndClassName found all tags with foo class"
);
is(
map(itemgetter("id"), matchElements("tr", "foo", t)).join(" "),
"tr0",
"getElementsByTagAndClassName found all tr tags with foo class"
);
is(
map(itemgetter("id"), matchElements("tr", null, t)).join(" "),
"tr0 tr1",
"getElementsByTagAndClassName found all tr tags"
);
is( getElementsByTagAndClassName("td", null, t).length, 0, "getElementsByTagAndClassName no match found");
is( getElementsByTagAndClassName("p", [], "donotexist").length, 0, "getElementsByTagAndClassName invalid parent id");
is( getFirstElementByTagAndClassName(null, "foo", t).id, "tbody0", "getFirstElementByTagAndClassName class name" );
is( getFirstElementByTagAndClassName("tr", "foo", t).id, "tr0", "getFirstElementByTagAndClassName tag and class name" );
is( getFirstElementByTagAndClassName("tr", null, t).id, "tr0", "getFirstElementByTagAndClassName tag name" );
ok( getFirstElementByTagAndClassName("td", null, t) === null, "getFirstElementByTagAndClassName no matching tag" );
ok( getFirstElementByTagAndClassName("tr", "donotexist", t) === null, "getFirstElementByTagAndClassName no matching class" );
ok( getFirstElementByTagAndClassName('*', null, 'donotexist') === null, "getFirstElementByTagAndClassName invalid parent id" );
var oldDoc = document;
var doc = MochiKit.MockDOM.createDocument();
is( currentDocument(), document, "currentDocument() correct" );
withDocument(doc, function () {
ok( document != doc, "global doc unchanged" );
is( currentDocument(), doc, "currentDocument() correct" );
var h1 = H1();
var span = SPAN(null, "foo", h1);
appendChildNodes(currentDocument().body, span);
});
is( document, oldDoc, "doc restored" );
is( doc.childNodes.length, 1, "doc has one child" );
is( doc.body.childNodes.length, 1, "body has one child" );
var sp = doc.body.childNodes[0];
is( sp.nodeName, "SPAN", "only child is SPAN" );
is( sp.childNodes.length, 2, "SPAN has two childNodes" );
is( sp.childNodes[0].nodeValue, "foo", "first node is text" );
is( sp.childNodes[1].nodeName, "H1", "second child is H1" );
is( currentDocument(), document, "currentDocument() correct" );
try {
withDocument(doc, function () {
ok( document != doc, "global doc unchanged" );
is( currentDocument(), doc, "currentDocument() correct" );
throw new Error("foo");
});
ok( false, "didn't throw" );
} catch (e) {
ok( true, "threw" );
}
var mockWindow = {"foo": "bar"};
is (currentWindow(), window, "currentWindow ok");
withWindow(mockWindow, function () {
is(currentWindow(), mockWindow, "withWindow ok");
});
is (currentWindow(), window, "currentWindow ok");
doc = MochiKit.MockDOM.createDocument();
var frm;
withDocument(doc, function () {
frm = FORM({name: "ignore"},
INPUT({name:"foo", value:"bar"}),
INPUT({name:"foo", value:"bar"}),
INPUT({name:"baz", value:"bar"})
);
});
var kv = formContents(frm);
is( kv[0].join(","), "foo,foo,baz", "mock formContents names" );
is( kv[1].join(","), "bar,bar,bar", "mock formContents values" );
is( queryString(frm), "foo=bar&foo=bar&baz=bar", "mock queryString hook" );
var kv = formContents("form_test");
is( kv[0].join(","), "select,selmultiple,selmultiple,hidden,radio_on", "formContents names" );
is( kv[1].join(","), "foo,bar,baz,test,2", "formContents values" );
is( queryString("form_test"), "select=foo&selmultiple=bar&selmultiple=baz&hidden=test&radio_on=2", "queryString hook" );
kv = formContents("form_test2");
is( kv[0].join(","), "selempty,selempty2", "formContents names empty option values" );
is( kv[1].join(","), ",foo", "formContents empty option values" );
is( queryString("form_test2"), "selempty=&selempty2=foo", "queryString empty option values" );
var d = DIV(null, SPAN(), " \n\t", SPAN(), "foo", SPAN(), " ");
is( d.childNodes.length, 6, "removeEmptyNodes test conditions correct" );
removeEmptyTextNodes(d);
is( d.childNodes.length, 4, "removeEmptyNodes" );
is( getFirstParentByTagAndClassName('child', 'div', 'two'), getElement("parentTwo"), "getFirstParentByTagAndClassName found parent" );
is( getFirstParentByTagAndClassName('child', 'div'), getElement("parentZero"), "getFirstParentByTagAndClassName found parent (any class)" );
is( getFirstParentByTagAndClassName('child', '*', 'two'), getElement("parentTwo"), "getFirstParentByTagAndClassName found parent (any tag)" );
is( getFirstParentByTagAndClassName('child', '*'), getElement("parentZero"), "getFirstParentByTagAndClassName found parent (any tag + any class)" );
ok( getFirstParentByTagAndClassName('child', 'form') === null, "getFirstParentByTagAndClassName found null parent (no match)" );
ok( getFirstParentByTagAndClassName('donotexist', '*') === null, "getFirstParentByTagAndClassName invalid elem id" );
ok( isChildNode('child', 'child'), "isChildNode of itself");
ok( isChildNode('child', 'parentZero'), "isChildNode direct child");
ok( isChildNode('child', 'parentTwo'), "isChildNode sub child");
ok( !isChildNode('child', 'form_test'), "isChildNode wrong child");
ok( !isChildNode('child', 'donotexist'), "isChildNode no parent");
ok( !isChildNode('donotexist', 'child'), "isChildNode no parent");
ok( isChildNode('child', document.body), "isChildNode of body");
ok( isChildNode($('child').firstChild, 'parentTwo'), "isChildNode text node");
ok( !isChildNode( SPAN(), document.body), "isChildNode child not in DOM");
ok( !isChildNode( SPAN(), 'child'), "isChildNode child not in DOM");
ok( !isChildNode( 'child', SPAN()), "isChildNode parent not in DOM");
// Test optional dependency on Iter
var Iter = MochiKit.Iter;
delete MochiKit["Iter"];
d = DIV({"foo": "bar"}, SPAN({}, "one"));
is( getNodeAttribute(d, 'foo'), "bar", "createDOM attribute without Iter" );
is( scrapeText(d), "one", "node contents without Iter" );
MochiKit.Iter = Iter;
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,39 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/DateTime.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript" src="test_DateTime.js"></script>
<script type="text/javascript">
try {
tests.test_DateTime({ok:ok, is:is});
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,60 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="../MochiKit/Signal.js"></script>
<!--
Include MochiKit/Position.js to fix the 2 following errors:
"Error: uncaught exception: MochiKit.Visual depends on MochiKit.Position!"
"Error: uncaught exception: MochiKit.DragAndDrop depends on MochiKit.Position!"
-->
<script type="text/javascript" src="../MochiKit/Position.js"></script>
<script type="text/javascript" src="../MochiKit/Visual.js"></script>
<script type="text/javascript" src="../MochiKit/DragAndDrop.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<style type="text/css">
.drop-hover {
}
#drag1 {
visibility: hidden;
}
#drop1 {
visibility: hidden;
}
</style>
</head>
<body>
<div id='drag1'>drag1</div>
<div id='drop1'>drop1</div>
<pre id="test">
<script type="text/javascript" src="test_DragAndDrop.js"></script>
<script type="text/javascript">
try {
// Counting the number of tests is really lame
tests.test_DragAndDrop({ok:ok, is:is});
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,39 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Format.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript" src="test_Format.js"></script>
<script type="text/javascript">
try {
tests.test_Format({ok:ok, is:is});
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,38 @@
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript" src="test_Iter.js"></script>
<script type="text/javascript">
try {
tests.test_Iter({ok:ok, is:is});
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,32 @@
<html>
<head>
<script type="text/javascript" src="JSAN.js"></script>
</head>
<body>
<pre id="test">
<script type="text/javascript">
// TODO: Make this a harness for the other tests
JSAN.use('Test.More');
JSAN.addRepository('..');
var lst = [];
plan({"tests": 1});
var wc = {};
wc['MochiKit'] = true;
for (var k in window) { wc[k] = true; }
for (var k in window) { wc[k] = true; }
JSAN.use('MochiKit.MochiKit', []);
for (var k in window) {
if (!(k in wc) && !(k.charAt(0) == '[')) {
lst.push(k);
}
}
lst.sort();
pollution = lst.join(" ");
is(pollution, "compare reduce", "namespace pollution?");
JSAN.use('MochiKit.MochiKit');
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,40 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript" src="test_Logging.js"></script>
<script type="text/javascript">
try {
tests.test_Logging({ok:ok, is:is});
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,18 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript">
is( isUndefined(null), false, "null is not undefined" );
is( isUndefined(""), false, "empty string is not undefined" );
is( isUndefined(undefined), true, "undefined is undefined" );
is( isUndefined({}.foo), true, "missing property is undefined" );
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,295 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Selector.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<style type="text/css">
p, #sequence {
display: none;
}
</style>
</head>
<body>
<p>Test originally from <a href="http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector" rel="bookmark">this blog entry</a>.</p>
<p>Here are some links in a normal paragraph: <a href="http://www.google.com/" title="Google!">Google</a>, <a href="http://groups.google.com/">Google Groups</a>. This link has <code>class="blog"</code>: <a href="http://diveintomark.org/" class="blog" fakeattribute="bla">diveintomark</a></p>
<div id="foo">
<p>Everything inside the red border is inside a div with <code>id="foo"</code>.</p>
<p>This is a normal link: <a href="http://www.yahoo.com/">Yahoo</a></p>
<a style="display: none" href="http://www.example.com/outsidep">This a is not inside a p</a>
<p>This link has <code>class="blog"</code>: <a href="http://simon.incutio.com/" class="blog">Simon Willison's Weblog</a></p>
<p>This <span><a href="http://www.example.com/insidespan">link</a></span> is inside a span, not directly child of p</p>
<p lang="en-us">Nonninn</p>
<p lang="is-IS">Sniðugt</p>
<p>
<input type="button" name="enabled" value="enabled" id="enabled">
<input type="button" name="disabled" value="disabled" id="disabled" disabled="1" />
<input type="checkbox" name="checked" value="checked" id="checked" checked="1" />
</p>
</div>
<div id="sequence">
<a href="http://www.example.com/link1">Link 1</a>
<a href="http://www.example.com/link2">Link 2</a>
<a href="http://www.example.com/link3">Link 3</a>
<a href="http://www.example.com/link4">Link 4</a>
<p>Something else</p>
<a href="http://www.example.com/link5">Link 5</a>
<a href="http://www.example.com/link6">Link 6</a>
<a href="http://www.example.com/link7">Link 7</a>
<a href="http://www.example.com/link8">Link 8</a>
</div>
<div id="multiclass" class="multiple classnames here"></div>
<pre id="test">
<script type="text/javascript">
try {
var testExpected = function (res, exp, lbl) {
for (var i=0; i < res.length; i ++) {
is( res[i].href, exp[i], lbl + ' (' + i + ')');
}
};
var expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector',
'http://www.google.com/',
'http://groups.google.com/',
'http://diveintomark.org/',
'http://www.yahoo.com/',
'http://www.example.com/outsidep',
'http://simon.incutio.com/',
'http://www.example.com/insidespan',
'http://www.example.com/link1',
'http://www.example.com/link2',
'http://www.example.com/link3',
'http://www.example.com/link4',
'http://www.example.com/link5',
'http://www.example.com/link6',
'http://www.example.com/link7',
'http://www.example.com/link8'];
var results = $$('a');
testExpected(results, expected, "'a' selector");
expected = ['http://diveintomark.org/', 'http://simon.incutio.com/'];
results = $$('p a.blog');
testExpected(results, expected, "'p a.blog' selector");
expected = ['http://www.yahoo.com/',
'http://www.example.com/outsidep',
'http://simon.incutio.com/',
'http://www.example.com/insidespan',
'http://www.example.com/link1',
'http://www.example.com/link2',
'http://www.example.com/link3',
'http://www.example.com/link4',
'http://www.example.com/link5',
'http://www.example.com/link6',
'http://www.example.com/link7',
'http://www.example.com/link8'];
results = $$('div a');
testExpected(results, expected, "'div a' selector");
expected = ['http://www.yahoo.com/',
'http://www.example.com/outsidep',
'http://simon.incutio.com/',
'http://www.example.com/insidespan'];
results = $$('div#foo a');
testExpected(results, expected, "'div#foo a' selector");
expected = ['http://simon.incutio.com/',
'http://www.example.com/insidespan'];
results = $$('#foo a.blog');
testExpected(results, expected, "'#foo a.blog' selector");
expected = ['http://diveintomark.org/',
'http://simon.incutio.com/',
'http://www.example.com/insidespan'];
results = $$('.blog');
testExpected(results, expected, "'.blog' selector");
expected = ['http://www.google.com/',
'http://www.yahoo.com/',
'http://www.example.com/outsidep',
'http://www.example.com/insidespan',
'http://www.example.com/link1',
'http://www.example.com/link2',
'http://www.example.com/link3',
'http://www.example.com/link4',
'http://www.example.com/link5',
'http://www.example.com/link6',
'http://www.example.com/link7',
'http://www.example.com/link8'];
results = $$('a[href^="http://www"]');
testExpected(results, expected, "'a[href^=http://www]' selector");
expected = ['http://diveintomark.org/'];
results = $$('a[href$="org/"]');
testExpected(results, expected, "'a[href$=org/]' selector");
expected = ['http://www.google.com/',
'http://groups.google.com/'];
results = $$('a[href*="google"]');
testExpected(results, expected, "'a[href*=google]' selector");
expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector'];
results = $$('a[rel="bookmark"]');
testExpected(results, expected, "'a[rel=bookmark]' selector");
expected = ['http://diveintomark.org/'];
results = $$('a[fakeattribute]');
testExpected(results, expected, "'a[fakeattribute]' selector");
/* This doesn't work in IE due to silly DOM implementation
expected = ['http://www.google.com/'];
results = $$('a[title]');
testExpected(results, expected, "'a[title]' selector");
*/
// Test attribute operators (also for elements not having the attribute)
results = $$('p[lang="en-us"]');
is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang=en-us]' selector");
results = $$('p[lang!="is-IS"]');
is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang!=is-IS]' selector");
results = $$('p[lang~="en-us"]');
is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang~=en-us]' selector");
results = $$('p[lang^="en"]');
is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang^=en]' selector");
results = $$('p[lang$="us"]');
is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang$=us]' selector");
results = $$('p[lang*="-u"]');
is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang*=-u]' selector");
results = $$('p[lang|="en"]');
is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang|=en]' selector");
expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector',
'http://www.google.com/',
'http://groups.google.com/',
'http://diveintomark.org/',
'http://www.yahoo.com/',
'http://simon.incutio.com/',
'http://www.example.com/insidespan'];
results = $$('p > a');
testExpected(results, expected, "'p > a' selector");
expected = ['http://www.example.com/insidespan'];
results = $$('span > a');
testExpected(results, expected, "'span > a' selector");
expected = ['http://groups.google.com/',
'http://www.example.com/link2',
'http://www.example.com/link3',
'http://www.example.com/link4',
'http://www.example.com/link6',
'http://www.example.com/link7',
'http://www.example.com/link8'];
results = $$('a + a');
testExpected(results, expected, "'a + a' selector");
expected = ['http://www.example.com/outsidep',
'http://www.example.com/link5',
'http://www.example.com/link6',
'http://www.example.com/link7',
'http://www.example.com/link8'];
results = $$('p ~ a');
testExpected(results, expected, "'p ~ a' selector");
expected = ['http://www.example.com/link1',
'http://www.example.com/link3',
'http://www.example.com/link6',
'http://www.example.com/link8'];
results = $$('#sequence a:nth-child(odd)');
testExpected(results, expected, "'#sequence a:nth-child(odd)' selector");
expected = ['http://www.example.com/link1',
'http://www.example.com/link3',
'http://www.example.com/link5',
'http://www.example.com/link7'];
results = $$('#sequence a:nth-of-type(odd)');
testExpected(results, expected, "'#sequence a:nth-of-type(odd)' selector");
expected = ['http://www.example.com/link1',
'http://www.example.com/link4',
'http://www.example.com/link7'];
results = $$('#sequence a:nth-of-type(3n+1)');
testExpected(results, expected, "'#sequence a:nth-of-type(3n+1)' selector");
expected = ['http://www.example.com/link5'];
results = $$('#sequence a:nth-child(6)');
testExpected(results, expected, "'#sequence a:nth-child(6)' selector");
expected = ['http://www.example.com/link5'];
results = $$('#sequence a:nth-of-type(5)');
testExpected(results, expected, "'#sequence a:nth-of-type(5)' selector");
expected = [$('enabled'), $('checked')];
results = $$('body :enabled');
for (var i=0; i < results.length; i ++) {
is( results[i], expected[i], "'body :enabled" + ' (' + i + ')');
}
expected = [$('disabled')];
results = $$('body :disabled');
for (var i=0; i < results.length; i ++) {
is( results[i], expected[i], "'body :disabled" + ' (' + i + ')');
}
expected = [$('checked')];
results = $$('body :checked');
for (var i=0; i < results.length; i ++) {
is( results[i], expected[i], "'body :checked" + ' (' + i + ')');
}
expected = document.getElementsByTagName('p');
results = $$('a[href$=outsidep] ~ *');
for (var i=0; i < results.length; i ++) {
is( results[i], expected[i+4], "'a[href$=outsidep] ~ *' selector" + ' (' + i + ')');
}
expected = [document.documentElement];
results = $$(':root');
for (var i=0; i < results.length; i ++) {
is( results[i], expected[i], "':root' selector" + ' (' + i + ')');
}
expected = [$('multiclass')];
results = $$('[class~=classnames]');
for (var i=0; i < results.length; i ++) {
is( results[i], expected[i], "'~=' attribute test" + ' (' + i + ')');
}
var doc = MochiKit.MockDOM.createDocument();
appendChildNodes(doc.body, A({"href": "http://www.example.com/insideAnotherDocument"}, "Inside a document"));
withDocument(doc, function(){
is( $$(":root")[0], doc, ":root on a different document" );
is( $$("a")[0], doc.body.firstChild, "a inside a different document" );
});
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,43 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Signal.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
</head>
<body>
Please ignore this button: <input type="submit" id="submit" /><br />
<pre id="test">
<script type="text/javascript" src="test_Signal.js"></script>
<script type="text/javascript">
try {
tests.test_Signal({ok:ok, is:is});
ok(true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok(false, s);
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,231 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<style type="text/css">
#hideTest {
display: none;
}
</style>
</head>
<body style="border: 0; margin: 0; padding: 0;">
<div id="styleTest" style="position: absolute; left: 400px; top: 100px; width: 100px; height: 80px; padding: 10px 20px 30px 40px; border-width: 1px 2px 3px 4px; border-style: solid; border-color: blue; background: red; opacity: 0.5; filter: alpha(opacity=50); font-size: 10px; overflow-x: visible; overflow-y: hidden;"><div id="innerDiv"></div>TEST<span id="styleSubTest">SUB</span><div id="floatTest" style="float: left;">Float</div></div>
<div id="hideTest" style="width: 100px; height: 100px;"><div id="innerHideTest" style="width: 10px; height: 10px;"></div></div>
<table id="testTable" border="0" cellspacing="0" cellpadding="0"
style="position:absolute;left: 400px; top:300px;line-height:20px;"><tr align="center">
<td id="testCell1" style="width: 80px; height: 30px; border:2px solid blue">1</td>
<td id="testCell2" style="width: 80px; height: 30px; border:2px solid blue">2</td>
<td id="testCell3" style="width: 80px; height: 30px; border:2px solid blue">3</td>
</tr></table>
<pre id="test">
<script type="text/javascript">
try {
// initial
var pos = getElementPosition('styleTest');
is(pos.x, 400, 'initial x position');
is(pos.y, 100, 'initial y position');
// Coordinates including border and padding
pos = getElementPosition('innerDiv');
is(pos.x, 444, 'x position with offsetParent border');
is(pos.y, 111, 'y position with offsetParent border');
// moved
var newPos = new MochiKit.Style.Coordinates(500, 200);
setElementPosition('styleTest', newPos);
pos = getElementPosition('styleTest');
is(pos.x, 500, 'updated x position');
is(pos.y, 200, 'updated y position');
// moved with relativeTo
anotherPos = new MochiKit.Style.Coordinates(100, 100);
pos = getElementPosition('styleTest', anotherPos);
is(pos.x, 400, 'updated x position (using relativeTo parameter)');
is(pos.y, 100, 'updated y position (using relativeTo parameter)');
// Coordinates object
pos = getElementPosition({x: 123, y: 321});
is(pos.x, 123, 'passthrough x position');
is(pos.y, 321, 'passthrough y position');
// Coordinates object with relativeTo
pos = getElementPosition({x: 123, y: 321}, {x: 100, y: 50});
is(pos.x, 23, 'passthrough x position (using relativeTo parameter)');
is(pos.y, 271, 'passthrough y position (using relativeTo parameter)');
pos = getElementPosition('garbage');
is(typeof(pos), 'undefined',
'invalid element should return an undefined position');
// Only set one coordinate
setElementPosition('styleTest', {'x': 300});
pos = getElementPosition('styleTest');
is(pos.x, 300, 'updated only x position');
is(pos.y, 200, 'not updated y position');
var mc = MochiKit.Color.Color;
var red = mc.fromString('rgb(255,0,0)');
var color = null;
color = mc.fromString(getStyle('styleTest', 'background-color'));
is(color.toHexString(), red.toHexString(),
'test getStyle selector case');
color = mc.fromString(getStyle('styleTest', 'backgroundColor'));
is(color.toHexString(), red.toHexString(),
'test getStyle camel case');
is(getStyle('styleSubTest', 'font-size'), '10px',
'test computed getStyle selector case');
is(getStyle('styleSubTest', 'fontSize'), '10px',
'test computed getStyle camel case');
is(eval(getStyle('styleTest', 'opacity')), 0.5,
'test getStyle opacity');
is(getStyle('styleTest', 'opacity'), 0.5, 'test getOpacity');
setStyle('styleTest', {'opacity': 0.2});
is(getStyle('styleTest', 'opacity'), 0.2, 'test setOpacity');
setStyle('styleTest', {'opacity': 0});
is(getStyle('styleTest', 'opacity'), 0, 'test setOpacity');
setStyle('styleTest', {'opacity': 1});
var t = getStyle('styleTest', 'opacity');
ok(t > 0.999 && t <= 1, 'test setOpacity');
is(getStyle('floatTest', 'float'), "left", 'getStyle of float');
is(getStyle('floatTest', 'cssFloat'), "left", 'getStyle of cssFloat');
is(getStyle('floatTest', 'styleFloat'), "left", 'getStyle of styleFloat');
is(getStyle('styleTest', 'float'), "none", 'getStyle of float when unset');
setStyle('floatTest', { "float": "right" });
is(getStyle('floatTest', 'float'), "right", 'setStyle of CSS float');
is(getStyle('floatTest', 'cssFloat'), "right", 'setStyle of CSS cssFloat');
is(getStyle('floatTest', 'styleFloat'), "right", 'setStyle of CSS styleFloat');
var dims = getElementDimensions('styleTest');
is(dims.w, 166, 'getElementDimensions w ok');
is(dims.h, 124, 'getElementDimensions h ok');
dims = getElementDimensions('styleTest', true);
is(dims.w, 100, 'getElementDimensions content w ok');
is(dims.h, 80, 'getElementDimensions content h ok');
setElementDimensions('styleTest', {'w': 200, 'h': 150});
dims = getElementDimensions('styleTest', true);
is(dims.w, 200, 'setElementDimensions w ok');
is(dims.h, 150, 'setElementDimensions h ok');
setElementDimensions('styleTest', {'w': 150});
dims = getElementDimensions('styleTest', true);
is(dims.w, 150, 'setElementDimensions only w ok');
is(dims.h, 150, 'setElementDimensions h not updated ok');
hideElement('styleTest');
dims = getElementDimensions('styleTest', true);
is(dims.w, 150, 'getElementDimensions w ok when display none');
is(dims.h, 150, 'getElementDimensions h ok when display none');
dims = getElementDimensions('hideTest', true);
is(dims.w, 100, 'getElementDimensions w ok when CSS display none');
is(dims.h, 100, 'getElementDimensions h ok when CSS display none');
/* TODO: can we create a work-around for this case?
dims = getElementDimensions('innerHideTest', true);
is(dims.w, 10, 'getElementDimensions w ok when parent CSS display none');
is(dims.h, 10, 'getElementDimensions h ok when parent CSS display none');
*/
var elem = DIV();
appendChildNodes('styleTest', elem);
var before = elem.style.display;
getElementDimensions(elem);
var after = elem.style.display;
is(after, before, 'getElementDimensions modified element display');
dims = getViewportDimensions();
is(dims.w > 0, true, 'test getViewportDimensions w');
is(dims.h > 0, true, 'test getViewportDimensions h');
pos = getViewportPosition();
is(pos.x, 0, 'test getViewportPosition x');
is(pos.y, 0, 'test getViewportPosition y');
// The 3(+3) following |is(dims.w, 80, ...);| need a width of at least 652px to pass.
// Our SimpleTest/TestRunner.js runs tests inside an |iframe.width = "500";| only.
// Work around that.
// NB: This test already passes without this workaround when run alone.
setElementPosition('testTable', {'x': dims.w - (3 * (2 + 80 + 2))});
pos = getElementPosition('testTable');
is(dims.w - pos.x >= (3 * (2 + 80 + 2)), true, 'Is viewport width enough to display \'testTable\' at expected size?');
dims = getElementDimensions('testCell1', true);
is(dims.w, 80, 'default left table cell content w ok');
is(dims.h, 30, 'default left table cell content h ok');
dims = getElementDimensions('testCell2', true);
is(dims.w, 80, 'default middle table cell content w ok');
is(dims.h, 30, 'default middle table cell content h ok');
dims = getElementDimensions('testCell3', true);
is(dims.w, 80, 'default right table cell content w ok');
is(dims.h, 30, 'default right table cell content h ok');
setStyle('testTable', {'borderCollapse': 'collapse'});
dims = getElementDimensions('testCell1', true);
is(dims.w, 80, 'collapsed left table cell content w ok');
is(dims.h, 30, 'collapsed left table cell content h ok');
dims = getElementDimensions('testCell2', true);
is(dims.w, 80, 'collapsed middle table cell content w ok');
is(dims.h, 30, 'collapsed middle table cell content h ok');
dims = getElementDimensions('testCell3', true);
is(dims.w, 80, 'collapsed right table cell content w ok');
is(dims.h, 30, 'collapsed right table cell content h ok');
hideElement('testTable');
var overflow = makeClipping('styleTest');
is(getStyle('styleTest', 'overflow-x'), 'hidden', 'make clipping on overflow-x');
is(getStyle('styleTest', 'overflow-y'), 'hidden', 'make clipping on overflow-y');
undoClipping('styleTest', overflow);
is(getStyle('styleTest', 'overflow-x'), 'visible', 'undo clipping on overflow-x');
is(getStyle('styleTest', 'overflow-y'), 'hidden', 'undo clipping on overflow-y');
ok( true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,197 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Async.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="../MochiKit/Signal.js"></script>
<script type="text/javascript" src="../MochiKit/Position.js"></script>
<script type="text/javascript" src="../MochiKit/Visual.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<style type="text/css">
#elt1, #elt2, #ctn1 {
visibility: hidden;
font-size: 1em;
margin: 2px;
}
#elt3 {
display: none;
}
#ctn1 {
height: 2px;
}
</style>
</head>
<body>
<div id='elt1'>elt1</div>
<div id='ctn1'><div id='elt2'></div></div>
<div id='elt3'>elt3</div>
<pre id="test">
<script type="text/javascript">
try {
var TestQueue = function () {
};
TestQueue.prototype = new MochiKit.Visual.ScopedQueue();
MochiKit.Base.update(TestQueue.prototype, {
startLoop: function (func, interval) {
this.started = true;
var timePos = new Date().getTime();
while (this.started) {
timePos += interval;
MochiKit.Base.map(function (effect) {
effect.loop(timePos);
}, this.effects);
}
},
stopLoop: function () {
this.started = false;
}
});
var gl = new TestQueue();
MochiKit.Visual.Queues.instances['global'] = gl;
MochiKit.Visual.Queues.instances['elt1'] = gl;
MochiKit.Visual.Queues.instances['elt2'] = gl;
MochiKit.Visual.Queues.instances['elt3'] = gl;
MochiKit.Visual.Queues.instances['ctn1'] = gl;
MochiKit.Visual.Queue = gl;
pulsate("elt1", {afterFinish: function () {
is(getElement('elt1').style.display != 'none', true, "pulsate ok");
}});
pulsate("elt1", {pulses: 2, afterFinish: function () {
is(getElement('elt1').style.display != 'none', true, "pulsate with numbered pulses ok");
}});
shake("elt1", {afterFinish: function () {
is(getElement('elt1').style.display != 'none', true, "shake ok");
}});
fade("elt1", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "fade ok");
}});
appear("elt1", {afterFinish: function () {
is(getElement('elt1').style.display != 'none', true, "appear ok");
}});
toggle("elt1", "size", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "toggle size ok");
}});
toggle("elt1", "size", {afterFinish: function () {
is(getElement('elt1').style.display != 'none', true, "toggle size reverse ok");
}});
Morph("elt1", {"style": {"font-size": "2em"}, afterFinish: function () {
is(getStyle("elt1", "font-size"), "2em", "Morph OK");
}});
Morph("elt1", {"style": {"font-size": "1em", "margin-left": "4px"}, afterFinish: function () {
is(getStyle("elt1", "font-size"), "1em", "Morph multiple (font) OK");
is(getStyle("elt1", "margin-left"), "4px", "Morph multiple (margin) OK");
}});
Morph("elt1", {"style": {"font-style": "italic"}, afterFinish: function () {
is(getStyle("elt1", "font-style"), "italic", "Morph generic property OK");
}});
switchOff("elt1", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "switchOff ok");
}});
grow("elt1", {afterFinish: function () {
is(getElement('elt1').style.display != 'none', true, "grow ok");
}});
shrink("elt1", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "shrink ok");
}});
showElement('elt1');
dropOut("elt1", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "dropOut ok");
}});
showElement('elt1');
puff("elt1", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "puff ok");
}});
showElement('elt1');
fold("elt1", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "fold ok");
}});
showElement('elt1');
squish("elt1", {afterFinish: function () {
is(getElement('elt1').style.display, 'none', "squish ok");
}});
slideUp("ctn1", {afterFinish: function () {
is(getElement('ctn1').style.display, 'none', "slideUp ok");
}});
slideDown("ctn1", {afterFinish: function () {
is(getElement('ctn1').style.display != 'none', true, "slideDown ok");
}});
blindDown("ctn1", {afterFinish: function () {
is(getElement('ctn1').style.display != 'none', true, "blindDown ok");
}});
blindUp("ctn1", {afterFinish: function () {
is(getElement('ctn1').style.display, 'none', "blindUp ok");
}});
multiple(["elt1", "ctn1"], appear, {afterFinish: function (effect) {
is(effect.element.style.display != 'none', true, "multiple ok");
}});
toggle("elt3", "size", {afterFinish: function () {
is(getElement('elt3').style.display != 'none', true, "toggle with css ok");
}});
toggle("elt3", "size", {afterFinish: function () {
is(getElement('elt3').style.display, 'none', "toggle with css ok");
}});
var toTests = [roundElement, roundClass, tagifyText, Opacity, Move, Highlight, ScrollTo, Morph];
for (var m in toTests) {
toTests[m]("elt1");
ok(true, toTests[m].NAME + " doesn't need 'new' keyword");
}
Scale("elt1", 1);
ok(true, "Scale doesn't need 'new' keyword");
ok(true, "visual suite finished");
} catch (err) {
var s = "test suite failure!\n";
var o = {};
var k = null;
for (k in err) {
// ensure unique keys?!
if (!o[k]) {
s += k + ": " + err[k] + "\n";
o[k] = err[k];
}
}
ok ( false, s );
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,481 @@
if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); }
if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); }
if (typeof(tests) == 'undefined') { tests = {}; }
tests.test_Signal = function (t) {
var submit = MochiKit.DOM.getElement('submit');
var ident = null;
var i = 0;
var aFunction = function() {
t.ok(this === submit, "aFunction should have 'this' as submit");
i++;
if (typeof(this.someVar) != 'undefined') {
i += this.someVar;
}
};
var aObject = {};
aObject.aMethod = function() {
t.ok(this === aObject, "aMethod should have 'this' as aObject");
i++;
};
ident = connect('submit', 'onclick', aFunction);
MochiKit.DOM.getElement('submit').click();
t.is(i, 1, 'HTML onclick event can be connected to a function');
disconnect(ident);
MochiKit.DOM.getElement('submit').click();
t.is(i, 1, 'HTML onclick can be disconnected from a function');
var submit = MochiKit.DOM.getElement('submit');
ident = connect(submit, 'onclick', aFunction);
submit.click();
t.is(i, 2, 'Checking that a DOM element can be connected to a function');
disconnect(ident);
submit.click();
t.is(i, 2, '...and then disconnected');
if (MochiKit.DOM.getElement('submit').fireEvent ||
(document.createEvent &&
typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) {
/*
Adapted from:
http://www.devdaily.com/java/jwarehouse/jforum/tests/selenium/javascript/htmlutils.js.shtml
License: Apache
Copyright: Copyright 2004 ThoughtWorks, Inc
*/
var triggerMouseEvent = function(element, eventType, canBubble) {
element = MochiKit.DOM.getElement(element);
canBubble = (typeof(canBubble) == 'undefined') ? true : canBubble;
if (element.fireEvent) {
var newEvt = document.createEventObject();
newEvt.clientX = 1;
newEvt.clientY = 1;
newEvt.button = 1;
newEvt.detail = 3;
element.fireEvent('on' + eventType, newEvt);
} else if (document.createEvent && (typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) {
var evt = document.createEvent('MouseEvents');
evt.initMouseEvent(eventType, canBubble, true, // event, bubbles, cancelable
document.defaultView, 3, // view, detail (either scroll or # of clicks)
1, 0, 0, 0, // screenX, screenY, clientX, clientY
false, false, false, false, // ctrlKey, altKey, shiftKey, metaKey
0, null); // buttonCode, relatedTarget
element.dispatchEvent(evt);
}
};
var eventTest = function(e) {
i++;
t.ok((typeof(e.event()) === 'object'), 'checking that event() is an object');
t.ok((typeof(e.type()) === 'string'), 'checking that type() is a string');
t.ok((e.target() === MochiKit.DOM.getElement('submit')), 'checking that target is "submit"');
t.ok((typeof(e.modifier()) === 'object'), 'checking that modifier() is an object');
t.ok(e.modifier().alt === false, 'checking that modifier().alt is defined, but false');
t.ok(e.modifier().ctrl === false, 'checking that modifier().ctrl is defined, but false');
t.ok(e.modifier().meta === false, 'checking that modifier().meta is defined, but false');
t.ok(e.modifier().shift === false, 'checking that modifier().shift is defined, but false');
t.ok((typeof(e.mouse()) === 'object'), 'checking that mouse() is an object');
t.ok((typeof(e.mouse().button) === 'object'), 'checking that mouse().button is an object');
t.ok(e.mouse().button.left === true, 'checking that mouse().button.left is true');
t.ok(e.mouse().button.middle === false, 'checking that mouse().button.middle is false');
t.ok(e.mouse().button.right === false, 'checking that mouse().button.right is false');
t.ok((typeof(e.mouse().page) === 'object'), 'checking that mouse().page is an object');
t.ok((typeof(e.mouse().page.x) === 'number'), 'checking that mouse().page.x is a number');
t.ok((typeof(e.mouse().page.y) === 'number'), 'checking that mouse().page.y is a number');
t.ok((typeof(e.mouse().client) === 'object'), 'checking that mouse().client is an object');
t.ok((typeof(e.mouse().client.x) === 'number'), 'checking that mouse().client.x is a number');
t.ok((typeof(e.mouse().client.y) === 'number'), 'checking that mouse().client.y is a number');
/* these should not be defined */
t.ok((typeof(e.relatedTarget()) === 'undefined'), 'checking that relatedTarget() is undefined');
t.ok((typeof(e.key()) === 'undefined'), 'checking that key() is undefined');
t.ok((typeof(e.mouse().wheel) === 'undefined'), 'checking that mouse().wheel is undefined');
};
ident = connect('submit', 'onmousedown', eventTest);
triggerMouseEvent('submit', 'mousedown', false);
t.is(i, 3, 'Connecting an event to an HTML object and firing a synthetic event');
disconnect(ident);
triggerMouseEvent('submit', 'mousedown', false);
t.is(i, 3, 'Disconnecting an event to an HTML object and firing a synthetic event');
ident = connect('submit', 'onmousewheel', function(e) {
i++;
t.ok((typeof(e.mouse()) === 'object'), 'checking that mouse() is an object');
t.ok((typeof(e.mouse().wheel) === 'object'), 'checking that mouse().wheel is an object');
t.ok((typeof(e.mouse().wheel.x) === 'number'), 'checking that mouse().wheel.x is a number');
t.ok((typeof(e.mouse().wheel.y) === 'number'), 'checking that mouse().wheel.y is a number');
});
var nativeSignal = 'mousewheel';
if (MochiKit.Signal._browserLacksMouseWheelEvent()) {
nativeSignal = 'DOMMouseScroll';
}
triggerMouseEvent('submit', nativeSignal, false);
t.is(i, 4, 'Connecting a mousewheel event to an HTML object and firing a synthetic event');
disconnect(ident);
triggerMouseEvent('submit', nativeSignal, false);
t.is(i, 4, 'Disconnecting a mousewheel event to an HTML object and firing a synthetic event');
}
// non-DOM tests
var hasNoSignals = {};
var hasSignals = {someVar: 1};
var i = 0;
var aFunction = function() {
i++;
if (typeof(this.someVar) != 'undefined') {
i += this.someVar;
}
};
var bFunction = function(someArg, someOtherArg) {
i += someArg + someOtherArg;
};
var aObject = {};
aObject.aMethod = function() {
i++;
};
aObject.bMethod = function() {
i++;
};
var bObject = {};
bObject.bMethod = function() {
i++;
};
ident = connect(hasSignals, 'signalOne', aFunction);
signal(hasSignals, 'signalOne');
t.is(i, 2, 'Connecting function');
i = 0;
disconnect(ident);
signal(hasSignals, 'signalOne');
t.is(i, 0, 'New style disconnecting function');
i = 0;
ident = connect(hasSignals, 'signalOne', bFunction);
signal(hasSignals, 'signalOne', 1, 2);
t.is(i, 3, 'Connecting function');
i = 0;
disconnect(ident);
signal(hasSignals, 'signalOne', 1, 2);
t.is(i, 0, 'New style disconnecting function');
i = 0;
connect(hasSignals, 'signalOne', aFunction);
signal(hasSignals, 'signalOne');
t.is(i, 2, 'Connecting function');
i = 0;
disconnect(hasSignals, 'signalOne', aFunction);
signal(hasSignals, 'signalOne');
t.is(i, 0, 'Old style disconnecting function');
i = 0;
ident = connect(hasSignals, 'signalOne', aObject, aObject.aMethod);
signal(hasSignals, 'signalOne');
t.is(i, 1, 'Connecting obj-function');
i = 0;
disconnect(ident);
signal(hasSignals, 'signalOne');
t.is(i, 0, 'New style disconnecting obj-function');
i = 0;
connect(hasSignals, 'signalOne', aObject, aObject.aMethod);
signal(hasSignals, 'signalOne');
t.is(i, 1, 'Connecting obj-function');
i = 0;
disconnect(hasSignals, 'signalOne', aObject, aObject.aMethod);
signal(hasSignals, 'signalOne');
t.is(i, 0, 'Disconnecting obj-function');
i = 0;
ident = connect(hasSignals, 'signalTwo', aObject, 'aMethod');
signal(hasSignals, 'signalTwo');
t.is(i, 1, 'Connecting obj-string');
i = 0;
disconnect(ident);
signal(hasSignals, 'signalTwo');
t.is(i, 0, 'New style disconnecting obj-string');
i = 0;
connect(hasSignals, 'signalTwo', aObject, 'aMethod');
signal(hasSignals, 'signalTwo');
t.is(i, 1, 'Connecting obj-string');
i = 0;
disconnect(hasSignals, 'signalTwo', aObject, 'aMethod');
signal(hasSignals, 'signalTwo');
t.is(i, 0, 'Old style disconnecting obj-string');
i = 0;
var shouldRaise = function() { return undefined.attr; };
try {
connect(hasSignals, 'signalOne', shouldRaise);
signal(hasSignals, 'signalOne');
t.ok(false, 'An exception was not raised');
} catch (e) {
t.ok(true, 'An exception was raised');
}
disconnect(hasSignals, 'signalOne', shouldRaise);
t.is(i, 0, 'Exception raised, signal should not have fired');
i = 0;
connect(hasSignals, 'signalOne', aObject, 'aMethod');
connect(hasSignals, 'signalOne', aObject, 'bMethod');
signal(hasSignals, 'signalOne');
t.is(i, 2, 'Connecting one signal to two slots in one object');
i = 0;
disconnect(hasSignals, 'signalOne', aObject, 'aMethod');
disconnect(hasSignals, 'signalOne', aObject, 'bMethod');
signal(hasSignals, 'signalOne');
t.is(i, 0, 'Disconnecting one signal from two slots in one object');
i = 0;
connect(hasSignals, 'signalOne', aObject, 'aMethod');
connect(hasSignals, 'signalOne', bObject, 'bMethod');
signal(hasSignals, 'signalOne');
t.is(i, 2, 'Connecting one signal to two slots in two objects');
i = 0;
disconnect(hasSignals, 'signalOne', aObject, 'aMethod');
disconnect(hasSignals, 'signalOne', bObject, 'bMethod');
signal(hasSignals, 'signalOne');
t.is(i, 0, 'Disconnecting one signal from two slots in two objects');
i = 0;
try {
connect(nothing, 'signalOne', aObject, 'aMethod');
signal(nothing, 'signalOne');
t.ok(false, 'An exception was not raised when connecting undefined');
} catch (e) {
t.ok(true, 'An exception was raised when connecting undefined');
}
try {
disconnect(nothing, 'signalOne', aObject, 'aMethod');
t.ok(false, 'An exception was not raised when disconnecting undefined');
} catch (e) {
t.ok(true, 'An exception was raised when disconnecting undefined');
}
try {
connect(hasSignals, 'signalOne', nothing);
signal(hasSignals, 'signalOne');
t.ok(false, 'An exception was not raised when connecting an undefined function');
} catch (e) {
t.ok(true, 'An exception was raised when connecting an undefined function');
}
try {
disconnect(hasSignals, 'signalOne', nothing);
t.ok(false, 'An exception was not raised when disconnecting an undefined function');
} catch (e) {
t.ok(true, 'An exception was raised when disconnecting an undefined function');
}
try {
connect(hasSignals, 'signalOne', aObject, aObject.nothing);
signal(hasSignals, 'signalOne');
t.ok(false, 'An exception was not raised when connecting an undefined method');
} catch (e) {
t.ok(true, 'An exception was raised when connecting an undefined method');
}
try {
connect(hasSignals, 'signalOne', aObject, 'nothing');
signal(hasSignals, 'signalOne');
t.ok(false, 'An exception was not raised when connecting an undefined method (as string)');
} catch (e) {
t.ok(true, 'An exception was raised when connecting an undefined method (as string)');
}
t.is(i, 0, 'Signals should not have fired');
connect(hasSignals, 'signalOne', aFunction);
connect(hasSignals, 'signalOne', aObject, 'aMethod');
disconnectAll(hasSignals, 'signalOne');
signal(hasSignals, 'signalOne');
t.is(i, 0, 'disconnectAll works with single explicit signal');
i = 0;
connect(hasSignals, 'signalOne', aFunction);
connect(hasSignals, 'signalOne', aObject, 'aMethod');
connect(hasSignals, 'signalTwo', aFunction);
connect(hasSignals, 'signalTwo', aObject, 'aMethod');
disconnectAll(hasSignals, 'signalOne');
signal(hasSignals, 'signalOne');
t.is(i, 0, 'disconnectAll works with single explicit signal');
signal(hasSignals, 'signalTwo');
t.is(i, 3, 'disconnectAll does not disconnect unrelated signals');
i = 0;
connect(hasSignals, 'signalOne', aFunction);
connect(hasSignals, 'signalOne', aObject, 'aMethod');
connect(hasSignals, 'signalTwo', aFunction);
connect(hasSignals, 'signalTwo', aObject, 'aMethod');
disconnectAll(hasSignals, 'signalOne', 'signalTwo');
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(i, 0, 'disconnectAll works with two explicit signals');
i = 0;
connect(hasSignals, 'signalOne', aFunction);
connect(hasSignals, 'signalOne', aObject, 'aMethod');
connect(hasSignals, 'signalTwo', aFunction);
connect(hasSignals, 'signalTwo', aObject, 'aMethod');
disconnectAll(hasSignals, ['signalOne', 'signalTwo']);
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(i, 0, 'disconnectAll works with two explicit signals as a list');
i = 0;
connect(hasSignals, 'signalOne', aFunction);
connect(hasSignals, 'signalOne', aObject, 'aMethod');
connect(hasSignals, 'signalTwo', aFunction);
connect(hasSignals, 'signalTwo', aObject, 'aMethod');
disconnectAll(hasSignals);
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(i, 0, 'disconnectAll works with implicit signals');
i = 0;
var toggle = function() {
disconnectAll(hasSignals, 'signalOne');
connect(hasSignals, 'signalOne', aFunction);
i++;
};
connect(hasSignals, 'signalOne', aFunction);
connect(hasSignals, 'signalTwo', function() { i++; });
connect(hasSignals, 'signalTwo', toggle);
connect(hasSignals, 'signalTwo', function() { i++; }); // #147
connect(hasSignals, 'signalTwo', function() { i++; });
signal(hasSignals, 'signalTwo');
t.is(i, 4, 'disconnectAll fired in a signal loop works');
i = 0;
disconnectAll('signalOne');
disconnectAll('signalTwo');
var testfunc = function () { arguments.callee.count++; };
testfunc.count = 0;
var testObj = {
methOne: function () { this.countOne++; }, countOne: 0,
methTwo: function () { this.countTwo++; }, countTwo: 0
};
connect(hasSignals, 'signalOne', testfunc);
connect(hasSignals, 'signalTwo', testfunc);
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(testfunc.count, 2, 'disconnectAllTo func precondition');
disconnectAllTo(testfunc);
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(testfunc.count, 2, 'disconnectAllTo func');
connect(hasSignals, 'signalOne', testObj, 'methOne');
connect(hasSignals, 'signalTwo', testObj, 'methTwo');
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(testObj.countOne, 1, 'disconnectAllTo obj precondition');
t.is(testObj.countTwo, 1, 'disconnectAllTo obj precondition');
disconnectAllTo(testObj);
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(testObj.countOne, 1, 'disconnectAllTo obj');
t.is(testObj.countTwo, 1, 'disconnectAllTo obj');
testObj.countOne = testObj.countTwo = 0;
connect(hasSignals, 'signalOne', testObj, 'methOne');
connect(hasSignals, 'signalTwo', testObj, 'methTwo');
disconnectAllTo(testObj, 'methOne');
signal(hasSignals, 'signalOne');
signal(hasSignals, 'signalTwo');
t.is(testObj.countOne, 0, 'disconnectAllTo obj+str');
t.is(testObj.countTwo, 1, 'disconnectAllTo obj+str');
has__Connect = {
count: 0,
__connect__: function (ident) {
this.count += arguments.length;
disconnect(ident);
}
};
connect(has__Connect, 'signalOne', function() {
t.fail("__connect__ should have disconnected signal");
});
t.is(has__Connect.count, 3, '__connect__ is called when it exists');
signal(has__Connect, 'signalOne');
has__Disconnect = {
count: 0,
__disconnect__: function (ident) {
this.count += arguments.length;
}
};
connect(has__Disconnect, 'signalOne', aFunction);
connect(has__Disconnect, 'signalTwo', aFunction);
disconnectAll(has__Disconnect);
t.is(has__Disconnect.count, 8, '__disconnect__ is called when it exists');
var events = {};
var test_ident = connect(events, "test", function() {
var fail_ident = connect(events, "fail", function () {
events.failed = true;
});
disconnect(fail_ident);
signal(events, "fail");
});
signal(events, "test");
t.is(events.failed, undefined, 'disconnected slots do not fire');
var sink = {f: function (ev) { this.ev = ev; }};
var src = {};
bindMethods(sink);
connect(src, 'signal', sink.f);
signal(src, 'signal', 'worked');
t.is(sink.ev, 'worked', 'custom signal does not re-bind methods');
var lateObj = { fun: function() { this.value = 1; } };
connect(src, 'signal', lateObj, "fun");
signal(src, 'signal');
lateObj.fun = function() { this.value = 2; };
signal(src, 'signal');
t.is(lateObj.value, 2, 'connect uses late function binding');
};

View file

@ -0,0 +1,98 @@
/*
* This code is used for handling synthesizeMouse in a content process.
* Generally it just delegates to EventUtils.js.
*/
// Set up a dummy environment so that EventUtils works. We need to be careful to
// pass a window object into each EventUtils method we call rather than having
// it rely on the |window| global.
var EventUtils = {};
EventUtils.window = {};
EventUtils.parent = EventUtils.window;
EventUtils._EU_Ci = Components.interfaces;
EventUtils._EU_Cc = Components.classes;
// EventUtils' `sendChar` function relies on the navigator to synthetize events.
EventUtils.navigator = content.document.defaultView.navigator;
EventUtils.KeyboardEvent = content.document.defaultView.KeyboardEvent;
Services.scriptloader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
addMessageListener("Test:SynthesizeMouse", (message) => {
let data = message.data;
let target = data.target;
if (typeof target == "string") {
target = content.document.querySelector(target);
}
else if (typeof data.targetFn == "string") {
let runnablestr = `
(() => {
return (${data.targetFn});
})();`
target = eval(runnablestr)();
}
else {
target = message.objects.object;
}
let left = data.x;
let top = data.y;
if (target) {
if (target.ownerDocument !== content.document) {
// Account for nodes found in iframes.
let cur = target;
do {
let frame = cur.ownerDocument.defaultView.frameElement;
let rect = frame.getBoundingClientRect();
left += rect.left;
top += rect.top;
cur = frame;
} while (cur && cur.ownerDocument !== content.document);
// node must be in this document tree.
if (!cur) {
sendAsyncMessage("Test:SynthesizeMouseDone",
{ error: "target must be in the main document tree" });
return;
}
}
let rect = target.getBoundingClientRect();
left += rect.left;
top += rect.top;
if (data.event.centered) {
left += rect.width / 2;
top += rect.height / 2;
}
}
let result;
if (data.event && data.event.wheel) {
EventUtils.synthesizeWheelAtPoint(left, top, data.event, content);
} else {
result = EventUtils.synthesizeMouseAtPoint(left, top, data.event, content);
}
sendAsyncMessage("Test:SynthesizeMouseDone", { defaultPrevented: result });
});
addMessageListener("Test:SendChar", message => {
let result = EventUtils.sendChar(message.data.char, content);
sendAsyncMessage("Test:SendCharDone", { result, seq: message.data.seq });
});
addMessageListener("Test:SynthesizeKey", message => {
EventUtils.synthesizeKey(message.data.key, message.data.event || {}, content);
sendAsyncMessage("Test:SynthesizeKeyDone", { seq: message.data.seq });
});
addMessageListener("Test:SynthesizeComposition", message => {
let result = EventUtils.synthesizeComposition(message.data.event, content);
sendAsyncMessage("Test:SynthesizeCompositionDone", { result, seq: message.data.seq });
});
addMessageListener("Test:SynthesizeCompositionChange", message => {
EventUtils.synthesizeCompositionChange(message.data.event, content);
sendAsyncMessage("Test:SynthesizeCompositionChangeDone", { seq: message.data.seq });
});

View file

@ -0,0 +1,124 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function ChromePowers(window) {
this.window = Components.utils.getWeakReference(window);
// In the case of browser-chrome tests, we are running as a [ChromeWindow]
// and we have no window.QueryInterface available, content.window is what we need
if (typeof(window) == "ChromeWindow" && typeof(content.window) == "Window") {
this.DOMWindowUtils = bindDOMWindowUtils(content.window);
this.window = Components.utils.getWeakReference(content.window);
} else {
this.DOMWindowUtils = bindDOMWindowUtils(window);
}
this.spObserver = new SpecialPowersObserverAPI();
this.spObserver._sendReply = this._sendReply.bind(this);
this.listeners = new Map();
}
ChromePowers.prototype = new SpecialPowersAPI();
ChromePowers.prototype.toString = function() { return "[ChromePowers]"; };
ChromePowers.prototype.sanityCheck = function() { return "foo"; };
// This gets filled in in the constructor.
ChromePowers.prototype.DOMWindowUtils = undefined;
ChromePowers.prototype._sendReply = function(aOrigMsg, aType, aMsg) {
var msg = {'name':aType, 'json': aMsg, 'data': aMsg};
if (!this.listeners.has(aType)) {
throw new Error(`No listener for ${aType}`);
}
this.listeners.get(aType)(msg);
};
ChromePowers.prototype._sendSyncMessage = function(aType, aMsg) {
var msg = {'name':aType, 'json': aMsg, 'data': aMsg};
return [this._receiveMessage(msg)];
};
ChromePowers.prototype._sendAsyncMessage = function(aType, aMsg) {
var msg = {'name':aType, 'json': aMsg, 'data': aMsg};
this._receiveMessage(msg);
};
ChromePowers.prototype._addMessageListener = function(aType, aCallback) {
if (this.listeners.has(aType)) {
throw new Error(`unable to handle multiple listeners for ${aType}`);
}
this.listeners.set(aType, aCallback);
};
ChromePowers.prototype._removeMessageListener = function(aType, aCallback) {
this.listeners.delete(aType);
};
ChromePowers.prototype.registerProcessCrashObservers = function() {
this._sendSyncMessage("SPProcessCrashService", { op: "register-observer" });
};
ChromePowers.prototype.unregisterProcessCrashObservers = function() {
this._sendSyncMessage("SPProcessCrashService", { op: "unregister-observer" });
};
ChromePowers.prototype._receiveMessage = function(aMessage) {
switch (aMessage.name) {
case "SpecialPowers.Quit":
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup);
appStartup.quit(Ci.nsIAppStartup.eForceQuit);
break;
case "SPProcessCrashService":
if (aMessage.json.op == "register-observer" || aMessage.json.op == "unregister-observer") {
// Hack out register/unregister specifically for browser-chrome leaks
break;
} else if (aMessage.type == "crash-observed") {
for (let e of msg.dumpIDs) {
this._encounteredCrashDumpFiles.push(e.id + "." + e.extension);
}
}
default:
// All calls go here, because we need to handle SPProcessCrashService calls as well
return this.spObserver._receiveMessageAPI(aMessage);
}
return undefined; // Avoid warning.
};
ChromePowers.prototype.quit = function() {
// We come in here as SpecialPowers.quit, but SpecialPowers is really ChromePowers.
// For some reason this.<func> resolves to TestRunner, so using SpecialPowers
// allows us to use the ChromePowers object which we defined below.
SpecialPowers._sendSyncMessage("SpecialPowers.Quit", {});
};
ChromePowers.prototype.focus = function(aWindow) {
// We come in here as SpecialPowers.focus, but SpecialPowers is really ChromePowers.
// For some reason this.<func> resolves to TestRunner, so using SpecialPowers
// allows us to use the ChromePowers object which we defined below.
if (aWindow)
aWindow.focus();
};
ChromePowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) {
aCallback();
};
// Expose everything but internal APIs (starting with underscores) to
// web content. We cannot use Object.keys to view SpecialPowers.prototype since
// we are using the functions from SpecialPowersAPI.prototype
ChromePowers.prototype.__exposedProps__ = {};
for (var i in ChromePowers.prototype) {
if (i.charAt(0) != "_")
ChromePowers.prototype.__exposedProps__[i] = "r";
}
if ((window.parent !== null) &&
(window.parent !== undefined) &&
(window.parent.wrappedJSObject.SpecialPowers) &&
!(window.wrappedJSObject.SpecialPowers)) {
window.wrappedJSObject.SpecialPowers = window.parent.SpecialPowers;
} else {
window.wrappedJSObject.SpecialPowers = new ChromePowers(window);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,139 @@
var ExtensionTestUtils = {};
ExtensionTestUtils.loadExtension = function(ext)
{
// Cleanup functions need to be registered differently depending on
// whether we're in browser chrome or plain mochitests.
var registerCleanup;
if (typeof registerCleanupFunction != "undefined") {
registerCleanup = registerCleanupFunction;
} else {
registerCleanup = SimpleTest.registerCleanupFunction.bind(SimpleTest);
}
var testResolve;
var testDone = new Promise(resolve => { testResolve = resolve; });
var messageHandler = new Map();
var messageAwaiter = new Map();
var messageQueue = new Set();
registerCleanup(() => {
if (messageQueue.size) {
let names = Array.from(messageQueue, ([msg]) => msg);
SimpleTest.is(JSON.stringify(names), "[]", "message queue is empty");
}
if (messageAwaiter.size) {
let names = Array.from(messageAwaiter.keys());
SimpleTest.is(JSON.stringify(names), "[]", "no tasks awaiting on messages");
}
});
function checkMessages() {
for (let message of messageQueue) {
let [msg, ...args] = message;
let listener = messageAwaiter.get(msg);
if (listener) {
messageQueue.delete(message);
messageAwaiter.delete(msg);
listener.resolve(...args);
return;
}
}
}
function checkDuplicateListeners(msg) {
if (messageHandler.has(msg) || messageAwaiter.has(msg)) {
throw new Error("only one message handler allowed");
}
}
function testHandler(kind, pass, msg, ...args) {
if (kind == "test-eq") {
let [expected, actual, stack] = args;
SimpleTest.ok(pass, `${msg} - Expected: ${expected}, Actual: ${actual}`, undefined, stack);
} else if (kind == "test-log") {
SimpleTest.info(msg);
} else if (kind == "test-result") {
SimpleTest.ok(pass, msg, undefined, args[0]);
}
}
var handler = {
testResult(kind, pass, msg, ...args) {
if (kind == "test-done") {
SimpleTest.ok(pass, msg, undefined, args[0]);
return testResolve(msg);
}
testHandler(kind, pass, msg, ...args);
},
testMessage(msg, ...args) {
var handler = messageHandler.get(msg);
if (handler) {
handler(...args);
} else {
messageQueue.add([msg, ...args]);
checkMessages();
}
},
};
// Mimic serialization of functions as done in `Extension.generateXPI` and
// `Extension.generateZipFile` because functions are dropped when `ext` object
// is sent to the main process via the message manager.
ext = Object.assign({}, ext);
if (ext.files) {
ext.files = Object.assign({}, ext.files);
for (let filename of Object.keys(ext.files)) {
let file = ext.files[filename];
if (typeof file == "function") {
ext.files[filename] = `(${file})();`
}
}
}
if (typeof ext.background == "function") {
ext.background = `(${ext.background})();`
}
var extension = SpecialPowers.loadExtension(ext, handler);
registerCleanup(() => {
if (extension.state == "pending" || extension.state == "running") {
SimpleTest.ok(false, "Extension left running at test shutdown")
return extension.unload();
} else if (extension.state == "unloading") {
SimpleTest.ok(false, "Extension not fully unloaded at test shutdown")
}
});
extension.awaitMessage = (msg) => {
return new Promise(resolve => {
checkDuplicateListeners(msg);
messageAwaiter.set(msg, {resolve});
checkMessages();
});
};
extension.onMessage = (msg, callback) => {
checkDuplicateListeners(msg);
messageHandler.set(msg, callback);
};
extension.awaitFinish = (msg) => {
return testDone.then(actual => {
if (msg) {
SimpleTest.is(actual, msg, "test result correct");
}
return actual;
});
};
SimpleTest.info(`Extension loaded`);
return extension;
}

View file

@ -0,0 +1,24 @@
LICENSE for SpawnTask.js (the co library):
(The MIT License)
Copyright (c) 2014 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,96 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var LogController = {}; //create the logger object
LogController.counter = 0; //current log message number
LogController.listeners = [];
LogController.logLevel = {
FATAL: 50,
ERROR: 40,
WARNING: 30,
INFO: 20,
DEBUG: 10
};
/* set minimum logging level */
LogController.logLevelAtLeast = function(minLevel) {
if (typeof(minLevel) == 'string') {
minLevel = LogController.logLevel[minLevel];
}
return function (msg) {
var msgLevel = msg.level;
if (typeof(msgLevel) == 'string') {
msgLevel = LogController.logLevel[msgLevel];
}
return msgLevel >= minLevel;
};
};
/* creates the log message with the given level and info */
LogController.createLogMessage = function(level, info) {
var msg = {};
msg.num = LogController.counter;
msg.level = level;
msg.info = info;
msg.timestamp = new Date();
return msg;
};
/* helper method to return a sub-array */
LogController.extend = function (args, skip) {
var ret = [];
for (var i = skip; i<args.length; i++) {
ret.push(args[i]);
}
return ret;
};
/* logs message with given level. Currently used locally by log() and error() */
LogController.logWithLevel = function(level, message/*, ...*/) {
var msg = LogController.createLogMessage(
level,
LogController.extend(arguments, 1)
);
LogController.dispatchListeners(msg);
LogController.counter += 1;
};
/* log with level INFO */
LogController.log = function(message/*, ...*/) {
LogController.logWithLevel('INFO', message);
};
/* log with level ERROR */
LogController.error = function(message/*, ...*/) {
LogController.logWithLevel('ERROR', message);
};
/* send log message to listeners */
LogController.dispatchListeners = function(msg) {
for (var k in LogController.listeners) {
var pair = LogController.listeners[k];
if (pair.ident != k || (pair[0] && !pair[0](msg))) {
continue;
}
pair[1](msg);
}
};
/* add a listener to this log given an identifier, a filter (can be null) and the listener object */
LogController.addListener = function(ident, filter, listener) {
if (typeof(filter) == 'string') {
filter = LogController.logLevelAtLeast(filter);
} else if (filter !== null && typeof(filter) !== 'function') {
throw new Error("Filter must be a string, a function, or null");
}
var entry = [filter, listener];
entry.ident = ident;
LogController.listeners[ident] = entry;
};
/* remove a listener from this log */
LogController.removeListener = function(ident) {
delete LogController.listeners[ident];
};

View file

@ -0,0 +1,122 @@
/* -*- js-indent-level: 4; indent-tabs-mode: nil -*- */
/* vim:set ts=4 sw=4 sts=4 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var MemoryStats = {};
/**
* Statistics that we want to retrieve and display after every test is
* done. The keys of this table are intended to be identical to the
* relevant attributes of nsIMemoryReporterManager. However, since
* nsIMemoryReporterManager doesn't necessarily support all these
* statistics in all build configurations, we also use this table to
* tell us whether statistics are supported or not.
*/
var MEM_STAT_UNKNOWN = 0;
var MEM_STAT_UNSUPPORTED = 1;
var MEM_STAT_SUPPORTED = 2;
MemoryStats._hasMemoryStatistics = {}
MemoryStats._hasMemoryStatistics.vsize = MEM_STAT_UNKNOWN;
MemoryStats._hasMemoryStatistics.vsizeMaxContiguous = MEM_STAT_UNKNOWN;
MemoryStats._hasMemoryStatistics.residentFast = MEM_STAT_UNKNOWN;
MemoryStats._hasMemoryStatistics.heapAllocated = MEM_STAT_UNKNOWN;
MemoryStats._getService = function (className, interfaceName) {
var service;
try {
service = Cc[className].getService(Ci[interfaceName]);
} catch (e) {
service = SpecialPowers.Cc[className]
.getService(SpecialPowers.Ci[interfaceName]);
}
return service;
}
MemoryStats._nsIFile = function (pathname) {
var f;
var contractID = "@mozilla.org/file/local;1";
try {
f = Cc[contractID].createInstance(Ci.nsIFile);
} catch(e) {
f = SpecialPowers.Cc[contractID].createInstance(SpecialPowers.Ci.nsIFile);
}
f.initWithPath(pathname);
return f;
}
MemoryStats.constructPathname = function (directory, basename) {
var d = MemoryStats._nsIFile(directory);
d.append(basename);
return d.path;
}
MemoryStats.dump = function (testNumber,
testURL,
dumpOutputDirectory,
dumpAboutMemory,
dumpDMD) {
// Use dump because treeherder uses --quiet, which drops 'info'
// from the structured logger.
var info = function(message) {
dump(message + "\n");
};
var mrm = MemoryStats._getService("@mozilla.org/memory-reporter-manager;1",
"nsIMemoryReporterManager");
var statMessage = "";
for (var stat in MemoryStats._hasMemoryStatistics) {
var supported = MemoryStats._hasMemoryStatistics[stat];
var firstAccess = false;
if (supported == MEM_STAT_UNKNOWN) {
firstAccess = true;
try {
var value = mrm[stat];
supported = MEM_STAT_SUPPORTED;
} catch (e) {
supported = MEM_STAT_UNSUPPORTED;
}
MemoryStats._hasMemoryStatistics[stat] = supported;
}
if (supported == MEM_STAT_SUPPORTED) {
var sizeInMB = Math.round(mrm[stat] / (1024 * 1024));
statMessage += " | " + stat + " " + sizeInMB + "MB";
} else if (firstAccess) {
info("MEMORY STAT " + stat + " not supported in this build configuration.");
}
}
if (statMessage.length > 0) {
info("MEMORY STAT" + statMessage);
}
if (dumpAboutMemory) {
var basename = "about-memory-" + testNumber + ".json.gz";
var dumpfile = MemoryStats.constructPathname(dumpOutputDirectory,
basename);
info(testURL + " | MEMDUMP-START " + dumpfile);
var md = MemoryStats._getService("@mozilla.org/memory-info-dumper;1",
"nsIMemoryInfoDumper");
md.dumpMemoryReportsToNamedFile(dumpfile, function () {
info("TEST-INFO | " + testURL + " | MEMDUMP-END");
}, null, /* anonymize = */ false);
}
// This is the old, deprecated function.
if (dumpDMD && typeof(DMDReportAndDump) != undefined) {
var basename = "dmd-" + testNumber + "-deprecated.txt";
var dumpfile = MemoryStats.constructPathname(dumpOutputDirectory,
basename);
info(testURL + " | DMD-DUMP-deprecated " + dumpfile);
DMDReportAndDump(dumpfile);
}
if (dumpDMD && typeof(DMDAnalyzeReports) != undefined) {
var basename = "dmd-" + testNumber + ".txt";
var dumpfile = MemoryStats.constructPathname(dumpOutputDirectory,
basename);
info(testURL + " | DMD-DUMP " + dumpfile);
DMDAnalyzeReports(dumpfile);
}
};

View file

@ -0,0 +1,90 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Allows registering a mock XPCOM component, that temporarily replaces the
* original one when an object implementing a given ContractID is requested
* using createInstance.
*
* @param aContractID
* The ContractID of the component to replace, for example
* "@mozilla.org/filepicker;1".
*
* @param aReplacementCtor
* The constructor function for the JavaScript object that will be
* created every time createInstance is called. This object must
* implement QueryInterface and provide the XPCOM interfaces required by
* the specified ContractID (for example
* Components.interfaces.nsIFilePicker).
*/
function MockObjectRegisterer(aContractID, aReplacementCtor) {
this._contractID = aContractID;
this._replacementCtor = aReplacementCtor;
}
MockObjectRegisterer.prototype = {
/**
* Replaces the current factory with one that returns a new mock object.
*
* After register() has been called, it is mandatory to call unregister() to
* restore the original component. Usually, you should use a try-catch block
* to ensure that unregister() is called.
*/
register: function MOR_register() {
if (this._originalFactory)
throw new Exception("Invalid object state when calling register()");
// Define a factory that creates a new object using the given constructor.
var providedConstructor = this._replacementCtor;
this._mockFactory = {
createInstance: function MF_createInstance(aOuter, aIid) {
if (aOuter != null)
throw SpecialPowers.Cr.NS_ERROR_NO_AGGREGATION;
return new providedConstructor().QueryInterface(aIid);
}
};
var retVal = SpecialPowers.swapFactoryRegistration(this._cid, this._contractID, this._mockFactory, this._originalFactory);
if ('error' in retVal) {
throw new Exception("ERROR: " + retVal.error);
} else {
this._cid = retVal.cid;
this._originalFactory = retVal.originalFactory;
}
},
/**
* Restores the original factory.
*/
unregister: function MOR_unregister() {
if (!this._originalFactory)
throw new Exception("Invalid object state when calling unregister()");
// Free references to the mock factory.
SpecialPowers.swapFactoryRegistration(this._cid, this._contractID, this._mockFactory, this._originalFactory);
// Allow registering a mock factory again later.
this._cid = null;
this._originalFactory = null;
this._mockFactory = null;
},
// --- Private methods and properties ---
/**
* The factory of the component being replaced.
*/
_originalFactory: null,
/**
* The CID under which the mock contractID was registered.
*/
_cid: null,
/**
* The nsIFactory that was automatically generated by this object.
*/
_mockFactory: null
}

View file

@ -0,0 +1,370 @@
/**
* This file defines all virtual keycodes for synthesizeNativeKey() of
* EventUtils.js and nsIDOMWindowUtils.sendNativeKeyEvent().
* These values are defined in each platform's SDK or documents.
*/
// Windows
// Windows' native key code values may include scan code value which can be
// retrieved with |((code & 0xFFFF0000 >> 16)|. If the value is 0, it will
// be computed with active keyboard layout automatically.
// FYI: Don't define scan code here for printable keys, numeric keys and
// IME keys because they depend on active keyboard layout.
// XXX: Although, ABNT C1 key depends on keyboard layout in strictly speaking.
// However, computing its scan code from the virtual keycode,
// WIN_VK_ABNT_C1, doesn't work fine (computed as 0x0073, "IntlRo").
// Therefore, we should specify it here explicitly (it should be 0x0056,
// "IntlBackslash"). Fortunately, the key always generates 0x0056 with
// any keyboard layouts as far as I've tested. So, this must be safe to
// test new regressions.
const WIN_VK_LBUTTON = 0x00000001;
const WIN_VK_RBUTTON = 0x00000002;
const WIN_VK_CANCEL = 0xE0460003;
const WIN_VK_MBUTTON = 0x00000004;
const WIN_VK_XBUTTON1 = 0x00000005;
const WIN_VK_XBUTTON2 = 0x00000006;
const WIN_VK_BACK = 0x000E0008;
const WIN_VK_TAB = 0x000F0009;
const WIN_VK_CLEAR = 0x004C000C;
const WIN_VK_RETURN = 0x001C000D;
const WIN_VK_SHIFT = 0x002A0010;
const WIN_VK_CONTROL = 0x001D0011;
const WIN_VK_MENU = 0x00380012;
const WIN_VK_PAUSE = 0x00450013;
const WIN_VK_CAPITAL = 0x003A0014;
const WIN_VK_KANA = 0x00000015;
const WIN_VK_HANGUEL = 0x00000015;
const WIN_VK_HANGUL = 0x00000015;
const WIN_VK_JUNJA = 0x00000017;
const WIN_VK_FINAL = 0x00000018;
const WIN_VK_HANJA = 0x00000019;
const WIN_VK_KANJI = 0x00000019;
const WIN_VK_ESCAPE = 0x0001001B;
const WIN_VK_CONVERT = 0x0000001C;
const WIN_VK_NONCONVERT = 0x0000001D;
const WIN_VK_ACCEPT = 0x0000001E;
const WIN_VK_MODECHANGE = 0x0000001F;
const WIN_VK_SPACE = 0x00390020;
const WIN_VK_PRIOR = 0xE0490021;
const WIN_VK_NEXT = 0xE0510022;
const WIN_VK_END = 0xE04F0023;
const WIN_VK_HOME = 0xE0470024;
const WIN_VK_LEFT = 0xE04B0025;
const WIN_VK_UP = 0xE0480026;
const WIN_VK_RIGHT = 0xE04D0027;
const WIN_VK_DOWN = 0xE0500028;
const WIN_VK_SELECT = 0x00000029;
const WIN_VK_PRINT = 0x0000002A;
const WIN_VK_EXECUTE = 0x0000002B;
const WIN_VK_SNAPSHOT = 0xE037002C;
const WIN_VK_INSERT = 0xE052002D;
const WIN_VK_DELETE = 0xE053002E;
const WIN_VK_HELP = 0x0000002F;
const WIN_VK_0 = 0x00000030;
const WIN_VK_1 = 0x00000031;
const WIN_VK_2 = 0x00000032;
const WIN_VK_3 = 0x00000033;
const WIN_VK_4 = 0x00000034;
const WIN_VK_5 = 0x00000035;
const WIN_VK_6 = 0x00000036;
const WIN_VK_7 = 0x00000037;
const WIN_VK_8 = 0x00000038;
const WIN_VK_9 = 0x00000039;
const WIN_VK_A = 0x00000041;
const WIN_VK_B = 0x00000042;
const WIN_VK_C = 0x00000043;
const WIN_VK_D = 0x00000044;
const WIN_VK_E = 0x00000045;
const WIN_VK_F = 0x00000046;
const WIN_VK_G = 0x00000047;
const WIN_VK_H = 0x00000048;
const WIN_VK_I = 0x00000049;
const WIN_VK_J = 0x0000004A;
const WIN_VK_K = 0x0000004B;
const WIN_VK_L = 0x0000004C;
const WIN_VK_M = 0x0000004D;
const WIN_VK_N = 0x0000004E;
const WIN_VK_O = 0x0000004F;
const WIN_VK_P = 0x00000050;
const WIN_VK_Q = 0x00000051;
const WIN_VK_R = 0x00000052;
const WIN_VK_S = 0x00000053;
const WIN_VK_T = 0x00000054;
const WIN_VK_U = 0x00000055;
const WIN_VK_V = 0x00000056;
const WIN_VK_W = 0x00000057;
const WIN_VK_X = 0x00000058;
const WIN_VK_Y = 0x00000059;
const WIN_VK_Z = 0x0000005A;
const WIN_VK_LWIN = 0xE05B005B;
const WIN_VK_RWIN = 0xE05C005C;
const WIN_VK_APPS = 0xE05D005D;
const WIN_VK_SLEEP = 0x0000005F;
const WIN_VK_NUMPAD0 = 0x00520060;
const WIN_VK_NUMPAD1 = 0x004F0061;
const WIN_VK_NUMPAD2 = 0x00500062;
const WIN_VK_NUMPAD3 = 0x00510063;
const WIN_VK_NUMPAD4 = 0x004B0064;
const WIN_VK_NUMPAD5 = 0x004C0065;
const WIN_VK_NUMPAD6 = 0x004D0066;
const WIN_VK_NUMPAD7 = 0x00470067;
const WIN_VK_NUMPAD8 = 0x00480068;
const WIN_VK_NUMPAD9 = 0x00490069;
const WIN_VK_MULTIPLY = 0x0037006A;
const WIN_VK_ADD = 0x004E006B;
const WIN_VK_SEPARATOR = 0x0000006C;
const WIN_VK_OEM_NEC_SEPARATE = 0x0000006C;
const WIN_VK_SUBTRACT = 0x004A006D;
const WIN_VK_DECIMAL = 0x0053006E;
const WIN_VK_DIVIDE = 0xE035006F;
const WIN_VK_F1 = 0x003B0070;
const WIN_VK_F2 = 0x003C0071;
const WIN_VK_F3 = 0x003D0072;
const WIN_VK_F4 = 0x003E0073;
const WIN_VK_F5 = 0x003F0074;
const WIN_VK_F6 = 0x00400075;
const WIN_VK_F7 = 0x00410076;
const WIN_VK_F8 = 0x00420077;
const WIN_VK_F9 = 0x00430078;
const WIN_VK_F10 = 0x00440079;
const WIN_VK_F11 = 0x0057007A;
const WIN_VK_F12 = 0x0058007B;
const WIN_VK_F13 = 0x0064007C;
const WIN_VK_F14 = 0x0065007D;
const WIN_VK_F15 = 0x0066007E;
const WIN_VK_F16 = 0x0067007F;
const WIN_VK_F17 = 0x00680080;
const WIN_VK_F18 = 0x00690081;
const WIN_VK_F19 = 0x006A0082;
const WIN_VK_F20 = 0x006B0083;
const WIN_VK_F21 = 0x006C0084;
const WIN_VK_F22 = 0x006D0085;
const WIN_VK_F23 = 0x006E0086;
const WIN_VK_F24 = 0x00760087;
const WIN_VK_NUMLOCK = 0xE0450090;
const WIN_VK_SCROLL = 0x00460091;
const WIN_VK_OEM_FJ_JISHO = 0x00000092;
const WIN_VK_OEM_NEC_EQUAL = 0x00000092;
const WIN_VK_OEM_FJ_MASSHOU = 0x00000093;
const WIN_VK_OEM_FJ_TOUROKU = 0x00000094;
const WIN_VK_OEM_FJ_LOYA = 0x00000095;
const WIN_VK_OEM_FJ_ROYA = 0x00000096;
const WIN_VK_LSHIFT = 0x002A00A0;
const WIN_VK_RSHIFT = 0x003600A1;
const WIN_VK_LCONTROL = 0x001D00A2;
const WIN_VK_RCONTROL = 0xE01D00A3;
const WIN_VK_LMENU = 0x003800A4;
const WIN_VK_RMENU = 0xE03800A5;
const WIN_VK_BROWSER_BACK = 0xE06A00A6;
const WIN_VK_BROWSER_FORWARD = 0xE06900A7;
const WIN_VK_BROWSER_REFRESH = 0xE06700A8;
const WIN_VK_BROWSER_STOP = 0xE06800A9;
const WIN_VK_BROWSER_SEARCH = 0x000000AA;
const WIN_VK_BROWSER_FAVORITES = 0xE06600AB;
const WIN_VK_BROWSER_HOME = 0xE03200AC;
const WIN_VK_VOLUME_MUTE = 0xE02000AD;
const WIN_VK_VOLUME_DOWN = 0xE02E00AE;
const WIN_VK_VOLUME_UP = 0xE03000AF;
const WIN_VK_MEDIA_NEXT_TRACK = 0xE01900B0;
const WIN_VK_OEM_FJ_000 = 0x000000B0;
const WIN_VK_MEDIA_PREV_TRACK = 0xE01000B1;
const WIN_VK_OEM_FJ_EUQAL = 0x000000B1;
const WIN_VK_MEDIA_STOP = 0xE02400B2;
const WIN_VK_MEDIA_PLAY_PAUSE = 0xE02200B3;
const WIN_VK_OEM_FJ_00 = 0x000000B3;
const WIN_VK_LAUNCH_MAIL = 0xE06C00B4;
const WIN_VK_LAUNCH_MEDIA_SELECT = 0xE06D00B5;
const WIN_VK_LAUNCH_APP1 = 0xE06B00B6;
const WIN_VK_LAUNCH_APP2 = 0xE02100B7;
const WIN_VK_OEM_1 = 0x000000BA;
const WIN_VK_OEM_PLUS = 0x000000BB;
const WIN_VK_OEM_COMMA = 0x000000BC;
const WIN_VK_OEM_MINUS = 0x000000BD;
const WIN_VK_OEM_PERIOD = 0x000000BE;
const WIN_VK_OEM_2 = 0x000000BF;
const WIN_VK_OEM_3 = 0x000000C0;
const WIN_VK_ABNT_C1 = 0x005600C1;
const WIN_VK_ABNT_C2 = 0x000000C2;
const WIN_VK_OEM_4 = 0x000000DB;
const WIN_VK_OEM_5 = 0x000000DC;
const WIN_VK_OEM_6 = 0x000000DD;
const WIN_VK_OEM_7 = 0x000000DE;
const WIN_VK_OEM_8 = 0x000000DF;
const WIN_VK_OEM_NEC_DP1 = 0x000000E0;
const WIN_VK_OEM_AX = 0x000000E1;
const WIN_VK_OEM_NEC_DP2 = 0x000000E1;
const WIN_VK_OEM_102 = 0x000000E2;
const WIN_VK_OEM_NEC_DP3 = 0x000000E2;
const WIN_VK_ICO_HELP = 0x000000E3;
const WIN_VK_OEM_NEC_DP4 = 0x000000E3;
const WIN_VK_ICO_00 = 0x000000E4;
const WIN_VK_PROCESSKEY = 0x000000E5;
const WIN_VK_ICO_CLEAR = 0x000000E6;
const WIN_VK_PACKET = 0x000000E7;
const WIN_VK_ERICSSON_BASE = 0x000000E8;
const WIN_VK_OEM_RESET = 0x000000E9;
const WIN_VK_OEM_JUMP = 0x000000EA;
const WIN_VK_OEM_PA1 = 0x000000EB;
const WIN_VK_OEM_PA2 = 0x000000EC;
const WIN_VK_OEM_PA3 = 0x000000ED;
const WIN_VK_OEM_WSCTRL = 0x000000EE;
const WIN_VK_OEM_CUSEL = 0x000000EF;
const WIN_VK_OEM_ATTN = 0x000000F0;
const WIN_VK_OEM_FINISH = 0x000000F1;
const WIN_VK_OEM_COPY = 0x000000F2;
const WIN_VK_OEM_AUTO = 0x000000F3;
const WIN_VK_OEM_ENLW = 0x000000F4;
const WIN_VK_OEM_BACKTAB = 0x000000F5;
const WIN_VK_ATTN = 0x000000F6;
const WIN_VK_CRSEL = 0x000000F7;
const WIN_VK_EXSEL = 0x000000F8;
const WIN_VK_EREOF = 0x000000F9;
const WIN_VK_PLAY = 0x000000FA;
const WIN_VK_ZOOM = 0x000000FB;
const WIN_VK_NONAME = 0x000000FC;
const WIN_VK_PA1 = 0x000000FD;
const WIN_VK_OEM_CLEAR = 0x000000FE;
const WIN_VK_NUMPAD_RETURN = 0xE01C000D;
const WIN_VK_NUMPAD_PRIOR = 0x00490021;
const WIN_VK_NUMPAD_NEXT = 0x00510022;
const WIN_VK_NUMPAD_END = 0x004F0023;
const WIN_VK_NUMPAD_HOME = 0x00470024;
const WIN_VK_NUMPAD_LEFT = 0x004B0025;
const WIN_VK_NUMPAD_UP = 0x00480026;
const WIN_VK_NUMPAD_RIGHT = 0x004D0027;
const WIN_VK_NUMPAD_DOWN = 0x00500028;
const WIN_VK_NUMPAD_INSERT = 0x0052002D;
const WIN_VK_NUMPAD_DELETE = 0x0053002E;
// Mac
const MAC_VK_ANSI_A = 0x00;
const MAC_VK_ANSI_S = 0x01;
const MAC_VK_ANSI_D = 0x02;
const MAC_VK_ANSI_F = 0x03;
const MAC_VK_ANSI_H = 0x04;
const MAC_VK_ANSI_G = 0x05;
const MAC_VK_ANSI_Z = 0x06;
const MAC_VK_ANSI_X = 0x07;
const MAC_VK_ANSI_C = 0x08;
const MAC_VK_ANSI_V = 0x09;
const MAC_VK_ISO_Section = 0x0A;
const MAC_VK_ANSI_B = 0x0B;
const MAC_VK_ANSI_Q = 0x0C;
const MAC_VK_ANSI_W = 0x0D;
const MAC_VK_ANSI_E = 0x0E;
const MAC_VK_ANSI_R = 0x0F;
const MAC_VK_ANSI_Y = 0x10;
const MAC_VK_ANSI_T = 0x11;
const MAC_VK_ANSI_1 = 0x12;
const MAC_VK_ANSI_2 = 0x13;
const MAC_VK_ANSI_3 = 0x14;
const MAC_VK_ANSI_4 = 0x15;
const MAC_VK_ANSI_6 = 0x16;
const MAC_VK_ANSI_5 = 0x17;
const MAC_VK_ANSI_Equal = 0x18;
const MAC_VK_ANSI_9 = 0x19;
const MAC_VK_ANSI_7 = 0x1A;
const MAC_VK_ANSI_Minus = 0x1B;
const MAC_VK_ANSI_8 = 0x1C;
const MAC_VK_ANSI_0 = 0x1D;
const MAC_VK_ANSI_RightBracket = 0x1E;
const MAC_VK_ANSI_O = 0x1F;
const MAC_VK_ANSI_U = 0x20;
const MAC_VK_ANSI_LeftBracket = 0x21;
const MAC_VK_ANSI_I = 0x22;
const MAC_VK_ANSI_P = 0x23;
const MAC_VK_Return = 0x24;
const MAC_VK_ANSI_L = 0x25;
const MAC_VK_ANSI_J = 0x26;
const MAC_VK_ANSI_Quote = 0x27;
const MAC_VK_ANSI_K = 0x28;
const MAC_VK_ANSI_Semicolon = 0x29;
const MAC_VK_ANSI_Backslash = 0x2A;
const MAC_VK_ANSI_Comma = 0x2B;
const MAC_VK_ANSI_Slash = 0x2C;
const MAC_VK_ANSI_N = 0x2D;
const MAC_VK_ANSI_M = 0x2E;
const MAC_VK_ANSI_Period = 0x2F;
const MAC_VK_Tab = 0x30;
const MAC_VK_Space = 0x31;
const MAC_VK_ANSI_Grave = 0x32;
const MAC_VK_Delete = 0x33;
const MAC_VK_PC_Backspace = 0x33;
const MAC_VK_Powerbook_KeypadEnter = 0x34;
const MAC_VK_Escape = 0x35;
const MAC_VK_RightCommand = 0x36;
const MAC_VK_Command = 0x37;
const MAC_VK_Shift = 0x38;
const MAC_VK_CapsLock = 0x39;
const MAC_VK_Option = 0x3A;
const MAC_VK_Control = 0x3B;
const MAC_VK_RightShift = 0x3C;
const MAC_VK_RightOption = 0x3D;
const MAC_VK_RightControl = 0x3E;
const MAC_VK_Function = 0x3F;
const MAC_VK_F17 = 0x40;
const MAC_VK_ANSI_KeypadDecimal = 0x41;
const MAC_VK_ANSI_KeypadMultiply = 0x43;
const MAC_VK_ANSI_KeypadPlus = 0x45;
const MAC_VK_ANSI_KeypadClear = 0x47;
const MAC_VK_VolumeUp = 0x48;
const MAC_VK_VolumeDown = 0x49;
const MAC_VK_Mute = 0x4A;
const MAC_VK_ANSI_KeypadDivide = 0x4B;
const MAC_VK_ANSI_KeypadEnter = 0x4C;
const MAC_VK_ANSI_KeypadMinus = 0x4E;
const MAC_VK_F18 = 0x4F;
const MAC_VK_F19 = 0x50;
const MAC_VK_ANSI_KeypadEquals = 0x51;
const MAC_VK_ANSI_Keypad0 = 0x52;
const MAC_VK_ANSI_Keypad1 = 0x53;
const MAC_VK_ANSI_Keypad2 = 0x54;
const MAC_VK_ANSI_Keypad3 = 0x55;
const MAC_VK_ANSI_Keypad4 = 0x56;
const MAC_VK_ANSI_Keypad5 = 0x57;
const MAC_VK_ANSI_Keypad6 = 0x58;
const MAC_VK_ANSI_Keypad7 = 0x59;
const MAC_VK_F20 = 0x5A;
const MAC_VK_ANSI_Keypad8 = 0x5B;
const MAC_VK_ANSI_Keypad9 = 0x5C;
const MAC_VK_JIS_Yen = 0x5D;
const MAC_VK_JIS_Underscore = 0x5E;
const MAC_VK_JIS_KeypadComma = 0x5F;
const MAC_VK_F5 = 0x60;
const MAC_VK_F6 = 0x61;
const MAC_VK_F7 = 0x62;
const MAC_VK_F3 = 0x63;
const MAC_VK_F8 = 0x64;
const MAC_VK_F9 = 0x65;
const MAC_VK_JIS_Eisu = 0x66;
const MAC_VK_F11 = 0x67;
const MAC_VK_JIS_Kana = 0x68;
const MAC_VK_F13 = 0x69;
const MAC_VK_PC_PrintScreen = 0x69;
const MAC_VK_F16 = 0x6A;
const MAC_VK_F14 = 0x6B;
const MAC_VK_PC_ScrollLock = 0x6B;
const MAC_VK_F10 = 0x6D;
const MAC_VK_PC_ContextMenu = 0x6E;
const MAC_VK_F12 = 0x6F;
const MAC_VK_F15 = 0x71;
const MAC_VK_PC_Pause = 0x71;
const MAC_VK_Help = 0x72;
const MAC_VK_PC_Insert = 0x72;
const MAC_VK_Home = 0x73;
const MAC_VK_PageUp = 0x74;
const MAC_VK_ForwardDelete = 0x75;
const MAC_VK_PC_Delete = 0x75;
const MAC_VK_F4 = 0x76;
const MAC_VK_End = 0x77;
const MAC_VK_F2 = 0x78;
const MAC_VK_PageDown = 0x79;
const MAC_VK_F1 = 0x7A;
const MAC_VK_LeftArrow = 0x7B;
const MAC_VK_RightArrow = 0x7C;
const MAC_VK_DownArrow = 0x7D;
const MAC_VK_UpArrow = 0x7E;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,296 @@
// # SpawnTask.js
// Directly copied from the "co" library by TJ Holowaychuk.
// See https://github.com/tj/co/tree/4.6.0
// For use with mochitest-plain and mochitest-chrome.
// spawn_task(generatorFunction):
// Expose only the `co` function, which is very similar to Task.spawn in Task.jsm.
// We call this function spawn_task to make its purpose more plain, and to
// reduce the chance of name collisions.
var spawn_task = (function () {
/**
* slice() reference.
*/
var slice = Array.prototype.slice;
/**
* Wrap the given generator `fn` into a
* function that returns a promise.
* This is a separate function so that
* every `co()` call doesn't create a new,
* unnecessary closure.
*
* @param {GeneratorFunction} fn
* @return {Function}
* @api public
*/
co.wrap = function (fn) {
createPromise.__generatorFunction__ = fn;
return createPromise;
function createPromise() {
return co.call(this, fn.apply(this, arguments));
}
};
/**
* Execute the generator function or a generator
* and return a promise.
*
* @param {Function} fn
* @return {Promise}
* @api public
*/
function co(gen) {
var ctx = this;
var args = slice.call(arguments, 1)
// we wrap everything in a promise to avoid promise chaining,
// which leads to memory leak errors.
// see https://github.com/tj/co/issues/180
return new Promise(function(resolve, reject) {
if (typeof gen === 'function') gen = gen.apply(ctx, args);
if (!gen || typeof gen.next !== 'function') return resolve(gen);
onFulfilled();
/**
* @param {Mixed} res
* @return {Promise}
* @api private
*/
function onFulfilled(res) {
var ret;
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
}
/**
* @param {Error} err
* @return {Promise}
* @api private
*/
function onRejected(err) {
var ret;
try {
ret = gen.throw(err);
} catch (e) {
return reject(e);
}
next(ret);
}
/**
* Get the next value in the generator,
* return a promise.
*
* @param {Object} ret
* @return {Promise}
* @api private
*/
function next(ret) {
if (ret.done) return resolve(ret.value);
var value = toPromise.call(ctx, ret.value);
if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
+ 'but the following object was passed: "' + String(ret.value) + '"'));
}
});
}
/**
* Convert a `yield`ed value into a promise.
*
* @param {Mixed} obj
* @return {Promise}
* @api private
*/
function toPromise(obj) {
if (!obj) return obj;
if (isPromise(obj)) return obj;
if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj);
if ('function' == typeof obj) return thunkToPromise.call(this, obj);
if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
if (isObject(obj)) return objectToPromise.call(this, obj);
return obj;
}
/**
* Convert a thunk to a promise.
*
* @param {Function}
* @return {Promise}
* @api private
*/
function thunkToPromise(fn) {
var ctx = this;
return new Promise(function (resolve, reject) {
fn.call(ctx, function (err, res) {
if (err) return reject(err);
if (arguments.length > 2) res = slice.call(arguments, 1);
resolve(res);
});
});
}
/**
* Convert an array of "yieldables" to a promise.
* Uses `Promise.all()` internally.
*
* @param {Array} obj
* @return {Promise}
* @api private
*/
function arrayToPromise(obj) {
return Promise.all(obj.map(toPromise, this));
}
/**
* Convert an object of "yieldables" to a promise.
* Uses `Promise.all()` internally.
*
* @param {Object} obj
* @return {Promise}
* @api private
*/
function objectToPromise(obj){
var results = new obj.constructor();
var keys = Object.keys(obj);
var promises = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var promise = toPromise.call(this, obj[key]);
if (promise && isPromise(promise)) defer(promise, key);
else results[key] = obj[key];
}
return Promise.all(promises).then(function () {
return results;
});
function defer(promise, key) {
// predefine the key in the result
results[key] = undefined;
promises.push(promise.then(function (res) {
results[key] = res;
}));
}
}
/**
* Check if `obj` is a promise.
*
* @param {Object} obj
* @return {Boolean}
* @api private
*/
function isPromise(obj) {
return 'function' == typeof obj.then;
}
/**
* Check if `obj` is a generator.
*
* @param {Mixed} obj
* @return {Boolean}
* @api private
*/
function isGenerator(obj) {
return 'function' == typeof obj.next && 'function' == typeof obj.throw;
}
/**
* Check if `obj` is a generator function.
*
* @param {Mixed} obj
* @return {Boolean}
* @api private
*/
function isGeneratorFunction(obj) {
var constructor = obj.constructor;
if (!constructor) return false;
if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true;
return isGenerator(constructor.prototype);
}
/**
* Check for plain object.
*
* @param {Mixed} val
* @return {Boolean}
* @api private
*/
function isObject(val) {
return Object == val.constructor;
}
return co;
})();
// add_task(generatorFunction):
// Call `add_task(generatorFunction)` for each separate
// asynchronous task in a mochitest. Tasks are run consecutively.
// Before the first task, `SimpleTest.waitForExplicitFinish()`
// will be called automatically, and after the last task,
// `SimpleTest.finish()` will be called.
var add_task = (function () {
// The list of tasks to run.
var task_list = [];
// The "add_task" function
return function (generatorFunction) {
if (task_list.length === 0) {
// This is the first time add_task has been called.
// First, confirm that SimpleTest is available.
if (!SimpleTest) {
throw new Error("SimpleTest not available.");
}
// Don't stop tests until asynchronous tasks are finished.
SimpleTest.waitForExplicitFinish();
// Because the client is using add_task for this set of tests,
// we need to spawn a "master task" that calls each task in succesion.
// Use setTimeout to ensure the master task runs after the client
// script finishes.
setTimeout(function () {
spawn_task(function* () {
// We stop the entire test file at the first exception because this
// may mean that the state of subsequent tests may be corrupt.
try {
for (var task of task_list) {
var name = task.name || "";
info("SpawnTask.js | Entering test " + name);
yield task();
info("SpawnTask.js | Leaving test " + name);
}
} catch (ex) {
try {
ok(false, "" + ex);
} catch (ex2) {
ok(false, "(The exception cannot be converted to string.)");
}
}
// All tasks are finished.
SimpleTest.finish();
});
});
}
// Add the task to the list of tasks to run after
// the main thread is finished.
task_list.push(generatorFunction);
};
})();

View file

@ -0,0 +1,754 @@
/* -*- js-indent-level: 4; indent-tabs-mode: nil -*- */
/*
* e10s event dispatcher from content->chrome
*
* type = eventName (QuitApplication)
* data = json object {"filename":filename} <- for LoggerInit
*/
"use strict";
function getElement(id) {
return ((typeof(id) == "string") ?
document.getElementById(id) : id);
}
this.$ = this.getElement;
function contentDispatchEvent(type, data, sync) {
if (typeof(data) == "undefined") {
data = {};
}
var event = new CustomEvent("contentEvent", {
bubbles: true,
detail: {
"sync": sync,
"type": type,
"data": JSON.stringify(data)
}
});
document.dispatchEvent(event);
}
function contentAsyncEvent(type, data) {
contentDispatchEvent(type, data, 0);
}
/* Helper Function */
function extend(obj, /* optional */ skip) {
// Extend an array with an array-like object starting
// from the skip index
if (!skip) {
skip = 0;
}
if (obj) {
var l = obj.length;
var ret = [];
for (var i = skip; i < l; i++) {
ret.push(obj[i]);
}
}
return ret;
}
function flattenArguments(lst/* ...*/) {
var res = [];
var args = extend(arguments);
while (args.length) {
var o = args.shift();
if (o && typeof(o) == "object" && typeof(o.length) == "number") {
for (var i = o.length - 1; i >= 0; i--) {
args.unshift(o[i]);
}
} else {
res.push(o);
}
}
return res;
}
/**
* TestRunner: A test runner for SimpleTest
* TODO:
*
* * Avoid moving iframes: That causes reloads on mozilla and opera.
*
*
**/
var TestRunner = {};
TestRunner.logEnabled = false;
TestRunner._currentTest = 0;
TestRunner._lastTestFinished = -1;
TestRunner._loopIsRestarting = false;
TestRunner.currentTestURL = "";
TestRunner.originalTestURL = "";
TestRunner._urls = [];
TestRunner._lastAssertionCount = 0;
TestRunner._expectedMinAsserts = 0;
TestRunner._expectedMaxAsserts = 0;
TestRunner.timeout = 5 * 60 * 1000; // 5 minutes.
TestRunner.maxTimeouts = 4; // halt testing after too many timeouts
TestRunner.runSlower = false;
TestRunner.dumpOutputDirectory = "";
TestRunner.dumpAboutMemoryAfterTest = false;
TestRunner.dumpDMDAfterTest = false;
TestRunner.slowestTestTime = 0;
TestRunner.slowestTestURL = "";
TestRunner.interactiveDebugger = false;
TestRunner._expectingProcessCrash = false;
TestRunner._structuredFormatter = new StructuredFormatter();
/**
* Make sure the tests don't hang indefinitely.
**/
TestRunner._numTimeouts = 0;
TestRunner._currentTestStartTime = new Date().valueOf();
TestRunner._timeoutFactor = 1;
TestRunner._checkForHangs = function() {
function reportError(win, msg) {
if ("SimpleTest" in win) {
win.SimpleTest.ok(false, msg);
} else if ("W3CTest" in win) {
win.W3CTest.logFailure(msg);
}
}
function killTest(win) {
if ("SimpleTest" in win) {
win.SimpleTest.timeout();
win.SimpleTest.finish();
} else if ("W3CTest" in win) {
win.W3CTest.timeout();
}
}
if (TestRunner._currentTest < TestRunner._urls.length) {
var runtime = new Date().valueOf() - TestRunner._currentTestStartTime;
if (runtime >= TestRunner.timeout * TestRunner._timeoutFactor) {
var frameWindow = $('testframe').contentWindow.wrappedJSObject ||
$('testframe').contentWindow;
// TODO : Do this in a way that reports that the test ended with a status "TIMEOUT"
reportError(frameWindow, "Test timed out.");
// If we have too many timeouts, give up. We don't want to wait hours
// for results if some bug causes lots of tests to time out.
if (++TestRunner._numTimeouts >= TestRunner.maxTimeouts) {
TestRunner._haltTests = true;
TestRunner.currentTestURL = "(SimpleTest/TestRunner.js)";
reportError(frameWindow, TestRunner.maxTimeouts + " test timeouts, giving up.");
var skippedTests = TestRunner._urls.length - TestRunner._currentTest;
reportError(frameWindow, "Skipping " + skippedTests + " remaining tests.");
}
// Add a little (1 second) delay to ensure automation.py has time to notice
// "Test timed out" log and process it (= take a screenshot).
setTimeout(function delayedKillTest() { killTest(frameWindow); }, 1000);
if (TestRunner._haltTests)
return;
}
setTimeout(TestRunner._checkForHangs, 30000);
}
}
TestRunner.requestLongerTimeout = function(factor) {
TestRunner._timeoutFactor = factor;
}
/**
* This is used to loop tests
**/
TestRunner.repeat = 0;
TestRunner._currentLoop = 1;
TestRunner.expectAssertions = function(min, max) {
if (typeof(max) == "undefined") {
max = min;
}
if (typeof(min) != "number" || typeof(max) != "number" ||
min < 0 || max < min) {
throw "bad parameter to expectAssertions";
}
TestRunner._expectedMinAsserts = min;
TestRunner._expectedMaxAsserts = max;
}
/**
* This function is called after generating the summary.
**/
TestRunner.onComplete = null;
/**
* Adds a failed test case to a list so we can rerun only the failed tests
**/
TestRunner._failedTests = {};
TestRunner._failureFile = "";
TestRunner.addFailedTest = function(testName) {
if (TestRunner._failedTests[testName] == undefined) {
TestRunner._failedTests[testName] = "";
}
};
TestRunner.setFailureFile = function(fileName) {
TestRunner._failureFile = fileName;
}
TestRunner.generateFailureList = function () {
if (TestRunner._failureFile) {
var failures = new SpecialPowersLogger(TestRunner._failureFile);
failures.log(JSON.stringify(TestRunner._failedTests));
failures.close();
}
};
/**
* If logEnabled is true, this is the logger that will be used.
**/
// This delimiter is used to avoid interleaving Mochitest/Gecko logs.
var LOG_DELIMITER = String.fromCharCode(0xe175) + String.fromCharCode(0xee31) + String.fromCharCode(0x2c32) + String.fromCharCode(0xacbf);
// A log callback for StructuredLog.jsm
TestRunner._dumpMessage = function(message) {
var str;
// This is a directive to python to format these messages
// for compatibility with mozharness. This can be removed
// with the MochitestFormatter (see bug 1045525).
message.js_source = 'TestRunner.js'
if (TestRunner.interactiveDebugger && message.action in TestRunner._structuredFormatter) {
str = TestRunner._structuredFormatter[message.action](message);
} else {
str = LOG_DELIMITER + JSON.stringify(message) + LOG_DELIMITER;
}
// BUGFIX: browser-chrome tests don't use LogController
if (Object.keys(LogController.listeners).length !== 0) {
LogController.log(str);
} else {
dump('\n' + str + '\n');
}
// Checking for error messages
if (message.expected || message.level === "ERROR") {
TestRunner.failureHandler();
}
};
// From https://dxr.mozilla.org/mozilla-central/source/testing/modules/StructuredLog.jsm
TestRunner.structuredLogger = new StructuredLogger('mochitest', TestRunner._dumpMessage);
TestRunner.structuredLogger.deactivateBuffering = function() {
TestRunner.structuredLogger._logData("buffering_off");
};
TestRunner.structuredLogger.activateBuffering = function() {
TestRunner.structuredLogger._logData("buffering_on");
};
TestRunner.log = function(msg) {
if (TestRunner.logEnabled) {
TestRunner.structuredLogger.info(msg);
} else {
dump(msg + "\n");
}
};
TestRunner.error = function(msg) {
if (TestRunner.logEnabled) {
TestRunner.structuredLogger.error(msg);
} else {
dump(msg + "\n");
TestRunner.failureHandler();
}
};
TestRunner.failureHandler = function() {
if (TestRunner.runUntilFailure) {
TestRunner._haltTests = true;
}
if (TestRunner.debugOnFailure) {
// You've hit this line because you requested to break into the
// debugger upon a testcase failure on your test run.
debugger;
}
};
/**
* Toggle element visibility
**/
TestRunner._toggle = function(el) {
if (el.className == "noshow") {
el.className = "";
el.style.cssText = "";
} else {
el.className = "noshow";
el.style.cssText = "width:0px; height:0px; border:0px;";
}
};
/**
* Creates the iframe that contains a test
**/
TestRunner._makeIframe = function (url, retry) {
var iframe = $('testframe');
if (url != "about:blank" &&
(("hasFocus" in document && !document.hasFocus()) ||
("activeElement" in document && document.activeElement != iframe))) {
contentAsyncEvent("Focus");
window.focus();
SpecialPowers.focus();
iframe.focus();
if (retry < 3) {
window.setTimeout('TestRunner._makeIframe("'+url+'", '+(retry+1)+')', 1000);
return;
}
TestRunner.structuredLogger.info("Error: Unable to restore focus, expect failures and timeouts.");
}
window.scrollTo(0, $('indicator').offsetTop);
iframe.src = url;
iframe.name = url;
iframe.width = "500";
return iframe;
};
/**
* Returns the current test URL.
* We use this to tell whether the test has navigated to another test without
* being finished first.
*/
TestRunner.getLoadedTestURL = function () {
var prefix = "";
// handle mochitest-chrome URIs
if ($('testframe').contentWindow.location.protocol == "chrome:") {
prefix = "chrome://mochitests";
}
return prefix + $('testframe').contentWindow.location.pathname;
};
TestRunner.setParameterInfo = function (params) {
this._params = params;
};
TestRunner.getParameterInfo = function() {
return this._params;
};
/**
* TestRunner entry point.
*
* The arguments are the URLs of the test to be ran.
*
**/
TestRunner.runTests = function (/*url...*/) {
TestRunner.structuredLogger.info("SimpleTest START");
TestRunner.originalTestURL = $("current-test").innerHTML;
SpecialPowers.registerProcessCrashObservers();
TestRunner._urls = flattenArguments(arguments);
var singleTestRun = this._urls.length <= 1 && TestRunner.repeat <= 1;
TestRunner.showTestReport = singleTestRun;
var frame = $('testframe');
frame.src = "";
if (singleTestRun) {
// Can't use document.body because this runs in a XUL doc as well...
var body = document.getElementsByTagName("body")[0];
body.setAttribute("singletest", "true");
frame.removeAttribute("scrolling");
}
TestRunner._checkForHangs();
TestRunner.runNextTest();
};
/**
* Used for running a set of tests in a loop for debugging purposes
* Takes an array of URLs
**/
TestRunner.resetTests = function(listURLs) {
TestRunner._currentTest = 0;
// Reset our "Current-test" line - functionality depends on it
$("current-test").innerHTML = TestRunner.originalTestURL;
if (TestRunner.logEnabled)
TestRunner.structuredLogger.info("SimpleTest START Loop " + TestRunner._currentLoop);
TestRunner._urls = listURLs;
$('testframe').src="";
TestRunner._checkForHangs();
TestRunner.runNextTest();
}
TestRunner.getNextUrl = function() {
var url = "";
// sometimes we have a subtest/harness which doesn't use a manifest
if ((TestRunner._urls[TestRunner._currentTest] instanceof Object) && ('test' in TestRunner._urls[TestRunner._currentTest])) {
url = TestRunner._urls[TestRunner._currentTest]['test']['url'];
TestRunner.expected = TestRunner._urls[TestRunner._currentTest]['test']['expected'];
} else {
url = TestRunner._urls[TestRunner._currentTest];
TestRunner.expected = 'pass';
}
return url;
}
/**
* Run the next test. If no test remains, calls onComplete().
**/
TestRunner._haltTests = false;
TestRunner.runNextTest = function() {
if (TestRunner._currentTest < TestRunner._urls.length &&
!TestRunner._haltTests)
{
var url = TestRunner.getNextUrl();
TestRunner.currentTestURL = url;
$("current-test-path").innerHTML = url;
TestRunner._currentTestStartTime = new Date().valueOf();
TestRunner._timeoutFactor = 1;
TestRunner._expectedMinAsserts = 0;
TestRunner._expectedMaxAsserts = 0;
TestRunner.structuredLogger.testStart(url);
TestRunner._makeIframe(url, 0);
} else {
$("current-test").innerHTML = "<b>Finished</b>";
// Only unload the last test to run if we're running more than one test.
if (TestRunner._urls.length > 1) {
TestRunner._makeIframe("about:blank", 0);
}
var passCount = parseInt($("pass-count").innerHTML, 10);
var failCount = parseInt($("fail-count").innerHTML, 10);
var todoCount = parseInt($("todo-count").innerHTML, 10);
if (passCount === 0 &&
failCount === 0 &&
todoCount === 0)
{
// No |$('testframe').contentWindow|, so manually update: ...
// ... the log,
TestRunner.structuredLogger.testEnd('SimpleTest/TestRunner.js',
"ERROR",
"OK",
"No checks actually run");
// ... the count,
$("fail-count").innerHTML = 1;
// ... the indicator.
var indicator = $("indicator");
indicator.innerHTML = "Status: Fail (No checks actually run)";
indicator.style.backgroundColor = "red";
}
SpecialPowers.unregisterProcessCrashObservers();
let e10sMode = SpecialPowers.isMainProcess() ? "non-e10s" : "e10s";
TestRunner.structuredLogger.info("TEST-START | Shutdown");
TestRunner.structuredLogger.info("Passed: " + passCount);
TestRunner.structuredLogger.info("Failed: " + failCount);
TestRunner.structuredLogger.info("Todo: " + todoCount);
TestRunner.structuredLogger.info("Mode: " + e10sMode);
TestRunner.structuredLogger.info("Slowest: " + TestRunner.slowestTestTime + 'ms - ' + TestRunner.slowestTestURL);
// If we are looping, don't send this cause it closes the log file
if (TestRunner.repeat === 0) {
TestRunner.structuredLogger.info("SimpleTest FINISHED");
}
if (TestRunner.repeat === 0 && TestRunner.onComplete) {
TestRunner.onComplete();
}
if (TestRunner._currentLoop <= TestRunner.repeat && !TestRunner._haltTests) {
TestRunner._currentLoop++;
TestRunner.resetTests(TestRunner._urls);
TestRunner._loopIsRestarting = true;
} else {
// Loops are finished
if (TestRunner.logEnabled) {
TestRunner.structuredLogger.info("TEST-INFO | Ran " + TestRunner._currentLoop + " Loops");
TestRunner.structuredLogger.info("SimpleTest FINISHED");
}
if (TestRunner.onComplete)
TestRunner.onComplete();
}
TestRunner.generateFailureList();
}
};
TestRunner.expectChildProcessCrash = function() {
TestRunner._expectingProcessCrash = true;
};
/**
* This stub is called by SimpleTest when a test is finished.
**/
TestRunner.testFinished = function(tests) {
// Prevent a test from calling finish() multiple times before we
// have a chance to unload it.
if (TestRunner._currentTest == TestRunner._lastTestFinished &&
!TestRunner._loopIsRestarting) {
TestRunner.structuredLogger.testEnd(TestRunner.currentTestURL,
"ERROR",
"OK",
"called finish() multiple times");
TestRunner.updateUI([{ result: false }]);
return;
}
TestRunner._lastTestFinished = TestRunner._currentTest;
TestRunner._loopIsRestarting = false;
// TODO : replace this by a function that returns the mem data as an object
// that's dumped later with the test_end message
MemoryStats.dump(TestRunner._currentTest,
TestRunner.currentTestURL,
TestRunner.dumpOutputDirectory,
TestRunner.dumpAboutMemoryAfterTest,
TestRunner.dumpDMDAfterTest);
function cleanUpCrashDumpFiles() {
if (!SpecialPowers.removeExpectedCrashDumpFiles(TestRunner._expectingProcessCrash)) {
TestRunner.structuredLogger.testEnd(TestRunner.currentTestURL,
"ERROR",
"OK",
"This test did not leave any crash dumps behind, but we were expecting some!");
tests.push({ result: false });
}
var unexpectedCrashDumpFiles =
SpecialPowers.findUnexpectedCrashDumpFiles();
TestRunner._expectingProcessCrash = false;
if (unexpectedCrashDumpFiles.length) {
TestRunner.structuredLogger.testEnd(TestRunner.currentTestURL,
"ERROR",
"OK",
"This test left crash dumps behind, but we " +
"weren't expecting it to!",
{unexpected_crashdump_files: unexpectedCrashDumpFiles});
tests.push({ result: false });
unexpectedCrashDumpFiles.sort().forEach(function(aFilename) {
TestRunner.structuredLogger.info("Found unexpected crash dump file " +
aFilename + ".");
});
}
}
function runNextTest() {
if (TestRunner.currentTestURL != TestRunner.getLoadedTestURL()) {
TestRunner.structuredLogger.testStatus(TestRunner.currentTestURL,
TestRunner.getLoadedTestURL(),
"FAIL",
"PASS",
"finished in a non-clean fashion, probably" +
" because it didn't call SimpleTest.finish()",
{loaded_test_url: TestRunner.getLoadedTestURL()});
tests.push({ result: false });
}
var runtime = new Date().valueOf() - TestRunner._currentTestStartTime;
TestRunner.structuredLogger.testEnd(TestRunner.currentTestURL,
"OK",
undefined,
"Finished in " + runtime + "ms",
{runtime: runtime}
);
if (TestRunner.slowestTestTime < runtime && TestRunner._timeoutFactor >= 1) {
TestRunner.slowestTestTime = runtime;
TestRunner.slowestTestURL = TestRunner.currentTestURL;
}
TestRunner.updateUI(tests);
// Don't show the interstitial if we just run one test with no repeats:
if (TestRunner._urls.length == 1 && TestRunner.repeat <= 1) {
TestRunner.testUnloaded();
return;
}
var interstitialURL;
if ($('testframe').contentWindow.location.protocol == "chrome:") {
interstitialURL = "tests/SimpleTest/iframe-between-tests.html";
} else {
interstitialURL = "/tests/SimpleTest/iframe-between-tests.html";
}
// check if there were test run after SimpleTest.finish, which should never happen
$('testframe').contentWindow.addEventListener('unload', function() {
var testwin = $('testframe').contentWindow;
if (testwin.SimpleTest && testwin.SimpleTest._tests.length != testwin.SimpleTest.testsLength) {
var wrongtestlength = testwin.SimpleTest._tests.length - testwin.SimpleTest.testsLength;
var wrongtestname = '';
for (var i = 0; i < wrongtestlength; i++) {
wrongtestname = testwin.SimpleTest._tests[testwin.SimpleTest.testsLength + i].name;
TestRunner.structuredLogger.testStatus(TestRunner.currentTestURL, wrongtestname, 'FAIL', 'PASS', "Result logged after SimpleTest.finish()");
}
TestRunner.updateUI([{ result: false }]);
}
} , false);
TestRunner._makeIframe(interstitialURL, 0);
}
SpecialPowers.executeAfterFlushingMessageQueue(function() {
cleanUpCrashDumpFiles();
SpecialPowers.flushPermissions(function () { SpecialPowers.flushPrefEnv(runNextTest); });
});
};
TestRunner.testUnloaded = function() {
// If we're in a debug build, check assertion counts. This code is
// similar to the code in Tester_nextTest in browser-test.js used
// for browser-chrome mochitests.
if (SpecialPowers.isDebugBuild) {
var newAssertionCount = SpecialPowers.assertionCount();
var numAsserts = newAssertionCount - TestRunner._lastAssertionCount;
TestRunner._lastAssertionCount = newAssertionCount;
var url = TestRunner.getNextUrl();
var max = TestRunner._expectedMaxAsserts;
var min = TestRunner._expectedMinAsserts;
if (numAsserts > max) {
TestRunner.structuredLogger.testEnd(url,
"ERROR",
"OK",
"Assertion count " + numAsserts + " is greater than expected range " +
min + "-" + max + " assertions.",
{assertions: numAsserts, min_asserts: min, max_asserts: max});
TestRunner.updateUI([{ result: false }]);
} else if (numAsserts < min) {
TestRunner.structuredLogger.testEnd(url,
"OK",
"ERROR",
"Assertion count " + numAsserts + " is less than expected range " +
min + "-" + max + " assertions.",
{assertions: numAsserts, min_asserts: min, max_asserts: max});
TestRunner.updateUI([{ result: false }]);
} else if (numAsserts > 0) {
TestRunner.structuredLogger.testEnd(url,
"ERROR",
"ERROR",
"Assertion count " + numAsserts + " within expected range " +
min + "-" + max + " assertions.",
{assertions: numAsserts, min_asserts: min, max_asserts: max});
}
}
TestRunner._currentTest++;
if (TestRunner.runSlower) {
setTimeout(TestRunner.runNextTest, 1000);
} else {
TestRunner.runNextTest();
}
};
/**
* Get the results.
*/
TestRunner.countResults = function(tests) {
var nOK = 0;
var nNotOK = 0;
var nTodo = 0;
for (var i = 0; i < tests.length; ++i) {
var test = tests[i];
if (test.todo && !test.result) {
nTodo++;
} else if (test.result && !test.todo) {
nOK++;
} else {
nNotOK++;
}
}
return {"OK": nOK, "notOK": nNotOK, "todo": nTodo};
}
/**
* Print out table of any error messages found during looped run
*/
TestRunner.displayLoopErrors = function(tableName, tests) {
if(TestRunner.countResults(tests).notOK >0){
var table = $(tableName);
var curtest;
if (table.rows.length == 0) {
//if table headers are not yet generated, make them
var row = table.insertRow(table.rows.length);
var cell = row.insertCell(0);
var textNode = document.createTextNode("Test File Name:");
cell.appendChild(textNode);
cell = row.insertCell(1);
textNode = document.createTextNode("Test:");
cell.appendChild(textNode);
cell = row.insertCell(2);
textNode = document.createTextNode("Error message:");
cell.appendChild(textNode);
}
//find the broken test
for (var testnum in tests){
curtest = tests[testnum];
if( !((curtest.todo && !curtest.result) || (curtest.result && !curtest.todo)) ){
//this is a failed test or the result of todo test. Display the related message
row = table.insertRow(table.rows.length);
cell = row.insertCell(0);
textNode = document.createTextNode(TestRunner.currentTestURL);
cell.appendChild(textNode);
cell = row.insertCell(1);
textNode = document.createTextNode(curtest.name);
cell.appendChild(textNode);
cell = row.insertCell(2);
textNode = document.createTextNode((curtest.diag ? curtest.diag : "" ));
cell.appendChild(textNode);
}
}
}
}
TestRunner.updateUI = function(tests) {
var results = TestRunner.countResults(tests);
var passCount = parseInt($("pass-count").innerHTML) + results.OK;
var failCount = parseInt($("fail-count").innerHTML) + results.notOK;
var todoCount = parseInt($("todo-count").innerHTML) + results.todo;
$("pass-count").innerHTML = passCount;
$("fail-count").innerHTML = failCount;
$("todo-count").innerHTML = todoCount;
// Set the top Green/Red bar
var indicator = $("indicator");
if (failCount > 0) {
indicator.innerHTML = "Status: Fail";
indicator.style.backgroundColor = "red";
} else if (passCount > 0) {
indicator.innerHTML = "Status: Pass";
indicator.style.backgroundColor = "#0d0";
} else {
indicator.innerHTML = "Status: ToDo";
indicator.style.backgroundColor = "orange";
}
// Set the table values
var trID = "tr-" + $('current-test-path').innerHTML;
var row = $(trID);
// Only update the row if it actually exists (autoUI)
if (row != null) {
var tds = row.getElementsByTagName("td");
tds[0].style.backgroundColor = "#0d0";
tds[0].innerHTML = parseInt(tds[0].innerHTML) + parseInt(results.OK);
tds[1].style.backgroundColor = results.notOK > 0 ? "red" : "#0d0";
tds[1].innerHTML = parseInt(tds[1].innerHTML) + parseInt(results.notOK);
tds[2].style.backgroundColor = results.todo > 0 ? "orange" : "#0d0";
tds[2].innerHTML = parseInt(tds[2].innerHTML) + parseInt(results.todo);
}
//if we ran in a loop, display any found errors
if (TestRunner.repeat > 0) {
TestRunner.displayLoopErrors('fail-table', tests);
}
}

View file

@ -0,0 +1,92 @@
var gWindowUtils;
try {
gWindowUtils = SpecialPowers.getDOMWindowUtils(window);
if (gWindowUtils && !gWindowUtils.compareCanvases)
gWindowUtils = null;
} catch (e) {
gWindowUtils = null;
}
function snapshotWindow(win, withCaret) {
return SpecialPowers.snapshotWindow(win, withCaret);
}
function snapshotRect(win, rect) {
return SpecialPowers.snapshotRect(win, rect);
}
// If the two snapshots don't compare as expected (true for equal, false for
// unequal), returns their serializations as data URIs. In all cases, returns
// whether the comparison was as expected.
function compareSnapshots(s1, s2, expectEqual, fuzz) {
if (s1.width != s2.width || s1.height != s2.height) {
ok(false, "Snapshot canvases are not the same size - comparing them makes no sense");
return [false];
}
var passed = false;
var numDifferentPixels;
var maxDifference = { value: undefined };
if (gWindowUtils) {
var equal;
try {
numDifferentPixels = gWindowUtils.compareCanvases(s1, s2, maxDifference);
if (!fuzz) {
equal = (numDifferentPixels == 0);
} else {
equal = (numDifferentPixels <= fuzz.numDifferentPixels &&
maxDifference.value <= fuzz.maxDifference);
}
passed = (equal == expectEqual);
} catch (e) {
ok(false, "Exception thrown from compareCanvases: " + e);
}
}
var s1DataURI, s2DataURI;
if (!passed) {
s1DataURI = s1.toDataURL();
s2DataURI = s2.toDataURL();
if (!gWindowUtils) {
passed = ((s1DataURI == s2DataURI) == expectEqual);
}
}
return [passed, s1DataURI, s2DataURI, numDifferentPixels, maxDifference.value];
}
function assertSnapshots(s1, s2, expectEqual, fuzz, s1name, s2name) {
var [passed, s1DataURI, s2DataURI, numDifferentPixels, maxDifference] =
compareSnapshots(s1, s2, expectEqual, fuzz);
var sym = expectEqual ? "==" : "!=";
ok(passed, "reftest comparison: " + sym + " " + s1name + " " + s2name);
if (!passed) {
// The language / format in this message should match the failure messages
// displayed by reftest.js's "RecordResult()" method so that log output
// can be parsed by reftest-analyzer.xhtml
var report = "REFTEST TEST-UNEXPECTED-FAIL | " + s1name +
" | image comparison (" + sym + "), max difference: " +
maxDifference + ", number of differing pixels: " +
numDifferentPixels + "\n";
if (expectEqual) {
report += "REFTEST IMAGE 1 (TEST): " + s1DataURI + "\n";
report += "REFTEST IMAGE 2 (REFERENCE): " + s2DataURI + "\n";
} else {
report += "REFTEST IMAGE: " + s1DataURI + "\n";
}
dump(report);
}
return passed;
}
function assertWindowPureColor(win, color) {
const snapshot = SpecialPowers.snapshotRect(win);
const canvas = document.createElement("canvas");
canvas.width = snapshot.width;
canvas.height = snapshot.height;
const context = canvas.getContext("2d");
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
assertSnapshots(snapshot, canvas, true, null, "snapshot", color);
}

View file

@ -0,0 +1,17 @@
<title>iframe for between tests</title>
<!--
This page exists so that our accounting for assertions correctly
counts assertions that happen while leaving a page. We load this page
after a test finishes, check the assertion counts, and then go on to
load the next.
-->
<script>
window.addEventListener("load", function() {
var runner = (parent.TestRunner || parent.wrappedJSObject.TestRunner);
runner.testUnloaded();
if (SpecialPowers) {
SpecialPowers.DOMWindowUtils.runNextCollectorTimer();
}
});
</script>

View file

@ -0,0 +1,24 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
TEST_HARNESS_FILES.testing.mochitest.tests.SimpleTest += [
'/docshell/test/chrome/docshell_helpers.js',
'/testing/specialpowers/content/MozillaLogger.js',
'EventUtils.js',
'ExtensionTestUtils.js',
'iframe-between-tests.html',
'LogController.js',
'MemoryStats.js',
'MockObjects.js',
'NativeKeyCodes.js',
'paint_listener.js',
'setup.js',
'SimpleTest.js',
'SpawnTask.js',
'test.css',
'TestRunner.js',
'WindowSnapshot.js',
]

View file

@ -0,0 +1,83 @@
(function() {
var accumulatedRect = null;
var onpaint = new Array();
var debug = false;
const FlushModes = {
FLUSH: 0,
NOFLUSH: 1
};
function paintListener(event) {
if (event.target != window)
return;
var eventRect =
[ event.boundingClientRect.left,
event.boundingClientRect.top,
event.boundingClientRect.right,
event.boundingClientRect.bottom ];
if (debug) {
dump("got MozAfterPaint: " + eventRect.join(",") + "\n");
}
accumulatedRect = accumulatedRect
? [ Math.min(accumulatedRect[0], eventRect[0]),
Math.min(accumulatedRect[1], eventRect[1]),
Math.max(accumulatedRect[2], eventRect[2]),
Math.max(accumulatedRect[3], eventRect[3]) ]
: eventRect;
while (onpaint.length > 0) {
window.setTimeout(onpaint.pop(), 0);
}
}
window.addEventListener("MozAfterPaint", paintListener, false);
function waitForPaints(callback, subdoc, flushMode) {
// Wait until paint suppression has ended
var utils = SpecialPowers.getDOMWindowUtils(window);
if (utils.paintingSuppressed) {
if (debug) {
dump("waiting for paint suppression to end...\n");
}
window.setTimeout(function() {
waitForPaints(callback, subdoc, flushMode);
}, 0);
return;
}
// The call to getBoundingClientRect will flush pending layout
// notifications. Sometimes, however, this is undesirable since it can mask
// bugs where the code under test should be performing the flush.
if (flushMode === FlushModes.FLUSH) {
document.documentElement.getBoundingClientRect();
if (subdoc) {
subdoc.documentElement.getBoundingClientRect();
}
}
if (utils.isMozAfterPaintPending) {
if (debug) {
dump("waiting for paint...\n");
}
onpaint.push(
function() { waitForPaints(callback, subdoc, FlushModes.NOFLUSH); });
if (utils.isTestControllingRefreshes) {
utils.advanceTimeAndRefresh(0);
}
return;
}
if (debug) {
dump("done...\n");
}
var result = accumulatedRect || [ 0, 0, 0, 0 ];
accumulatedRect = null;
callback.apply(null, result);
}
window.waitForAllPaintsFlushed = function(callback, subdoc) {
waitForPaints(callback, subdoc, FlushModes.FLUSH);
};
window.waitForAllPaints = function(callback) {
waitForPaints(callback, null, FlushModes.NOFLUSH);
};
})();

View file

@ -0,0 +1,260 @@
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
TestRunner.logEnabled = true;
TestRunner.logger = LogController;
/* Helper function */
function parseQueryString(encodedString, useArrays) {
// strip a leading '?' from the encoded string
var qstr = (encodedString.length > 0 && encodedString[0] == "?")
? encodedString.substring(1)
: encodedString;
var pairs = qstr.replace(/\+/g, "%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
var o = {};
var decode;
if (typeof(decodeURIComponent) != "undefined") {
decode = decodeURIComponent;
} else {
decode = unescape;
}
if (useArrays) {
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split("=");
if (pair.length !== 2) {
continue;
}
var name = decode(pair[0]);
var arr = o[name];
if (!(arr instanceof Array)) {
arr = [];
o[name] = arr;
}
arr.push(decode(pair[1]));
}
} else {
for (i = 0; i < pairs.length; i++) {
pair = pairs[i].split("=");
if (pair.length !== 2) {
continue;
}
o[decode(pair[0])] = decode(pair[1]);
}
}
return o;
};
// Check the query string for arguments
var params = parseQueryString(location.search.substring(1), true);
var config = {};
if (window.readConfig) {
config = readConfig();
}
if (config.testRoot == "chrome" || config.testRoot == "a11y") {
for (var p in params) {
// Compare with arrays to find boolean equivalents, since that's what
// |parseQueryString| with useArrays returns.
if (params[p] == [1]) {
config[p] = true;
} else if (params[p] == [0]) {
config[p] = false;
} else {
config[p] = params[p];
}
}
params = config;
params.baseurl = "chrome://mochitests/content";
} else {
params.baseurl = "";
}
if (params.testRoot == "browser") {
params.testPrefix = "chrome://mochitests/content/browser/";
} else if (params.testRoot == "chrome") {
params.testPrefix = "chrome://mochitests/content/chrome/";
} else if (params.testRoot == "a11y") {
params.testPrefix = "chrome://mochitests/content/a11y/";
} else {
params.testPrefix = "/tests/";
}
// set the per-test timeout if specified in the query string
if (params.timeout) {
TestRunner.timeout = parseInt(params.timeout) * 1000;
}
// log levels for console and logfile
var fileLevel = params.fileLevel || null;
var consoleLevel = params.consoleLevel || null;
// repeat tells us how many times to repeat the tests
if (params.repeat) {
TestRunner.repeat = params.repeat;
}
if (params.runUntilFailure) {
TestRunner.runUntilFailure = true;
}
// closeWhenDone tells us to close the browser when complete
if (params.closeWhenDone) {
TestRunner.onComplete = SpecialPowers.quit;
}
if (params.failureFile) {
TestRunner.setFailureFile(params.failureFile);
}
// Breaks execution and enters the JS debugger on a test failure
if (params.debugOnFailure) {
TestRunner.debugOnFailure = true;
}
// logFile to write our results
if (params.logFile) {
var spl = new SpecialPowersLogger(params.logFile);
TestRunner.logger.addListener("mozLogger", fileLevel + "", spl.getLogCallback());
}
// A temporary hack for android 4.0 where Fennec utilizes the pandaboard so much it reboots
if (params.runSlower) {
TestRunner.runSlower = true;
}
if (params.dumpOutputDirectory) {
TestRunner.dumpOutputDirectory = params.dumpOutputDirectory;
}
if (params.dumpAboutMemoryAfterTest) {
TestRunner.dumpAboutMemoryAfterTest = true;
}
if (params.dumpDMDAfterTest) {
TestRunner.dumpDMDAfterTest = true;
}
if (params.interactiveDebugger) {
TestRunner.interactiveDebugger = true;
}
if (params.maxTimeouts) {
TestRunner.maxTimeouts = params.maxTimeouts;
}
// Log things to the console if appropriate.
TestRunner.logger.addListener("dumpListener", consoleLevel + "", function(msg) {
dump(msg.info.join(' ') + "\n");
});
var gTestList = [];
var RunSet = {};
RunSet.runall = function(e) {
// Filter tests to include|exclude tests based on data in params.filter.
// This allows for including or excluding tests from the gTestList
// TODO Only used by ipc tests, remove once those are implemented sanely
if (params.testManifest) {
getTestManifest("http://mochi.test:8888/" + params.testManifest, params, function(filter) { gTestList = filterTests(filter, gTestList, params.runOnly); RunSet.runtests(); });
} else {
RunSet.runtests();
}
}
RunSet.runtests = function(e) {
// Which tests we're going to run
var my_tests = gTestList;
if (params.startAt || params.endAt) {
my_tests = skipTests(my_tests, params.startAt, params.endAt);
}
if (params.shuffle) {
for (var i = my_tests.length-1; i > 0; --i) {
var j = Math.floor(Math.random() * i);
var tmp = my_tests[j];
my_tests[j] = my_tests[i];
my_tests[i] = tmp;
}
}
TestRunner.setParameterInfo(params);
TestRunner.runTests(my_tests);
}
RunSet.reloadAndRunAll = function(e) {
e.preventDefault();
//window.location.hash = "";
var addParam = "";
if (params.autorun) {
window.location.search += "";
window.location.href = window.location.href;
} else if (window.location.search) {
window.location.href += "&autorun=1";
} else {
window.location.href += "?autorun=1";
}
};
// UI Stuff
function toggleVisible(elem) {
toggleElementClass("invisible", elem);
}
function makeVisible(elem) {
removeElementClass(elem, "invisible");
}
function makeInvisible(elem) {
addElementClass(elem, "invisible");
}
function isVisible(elem) {
// you may also want to check for
// getElement(elem).style.display == "none"
return !hasElementClass(elem, "invisible");
};
function toggleNonTests (e) {
e.preventDefault();
var elems = document.getElementsByClassName("non-test");
for (var i="0"; i<elems.length; i++) {
toggleVisible(elems[i]);
}
if (isVisible(elems[0])) {
$("toggleNonTests").innerHTML = "Hide Non-Tests";
} else {
$("toggleNonTests").innerHTML = "Show Non-Tests";
}
}
// hook up our buttons
function hookup() {
if (params.manifestFile) {
getTestManifest("http://mochi.test:8888/" + params.manifestFile, params, hookupTests);
} else {
hookupTests(gTestList);
}
}
function hookupTests(testList) {
if (testList.length > 0) {
gTestList = testList;
} else {
gTestList = [];
for (var obj in testList) {
gTestList.push(testList[obj]);
}
}
document.getElementById('runtests').onclick = RunSet.reloadAndRunAll;
document.getElementById('toggleNonTests').onclick = toggleNonTests;
// run automatically if autorun specified
if (params.autorun) {
RunSet.runall();
}
}

View file

@ -0,0 +1,43 @@
.test_ok {
color: #0d0;
display: none;
}
.test_not_ok {
color: red;
display: block;
}
.test_todo {
/* color: orange; */
display: block;
}
.test_ok, .test_not_ok, .test_todo {
border-bottom-width: 2px;
border-bottom-style: solid;
border-bottom-color: black;
}
.all_pass {
background-color: #0d0;
}
.some_fail {
background-color: red;
}
.todo_only {
background-color: orange;
}
.tests_report {
border-width: 2px;
border-style: solid;
width: 20em;
display: table;
}
browser[remote="true"] {
-moz-binding: url("chrome://global/content/bindings/remote-browser.xml#remote-browser");
}

Some files were not shown because too many files have changed in this diff Show more