org.apache.myfaces.custom.dojo.resource.dojo.js.uncompressed.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tomahawk Show documentation
Show all versions of tomahawk Show documentation
JSF components and utilities that can be used with any JSF implementation.
This library is compatible with both JSF1.1 and JSF1.2; however for JSF1.2 users there
is an alternative build of Tomahawk available that takes advantage of JSF1.2 features to
offer some additional benefits.
if(typeof dojo == "undefined"){
/**
* @file bootstrap1.js
*
* summary: First file that is loaded that 'bootstraps' the entire dojo library suite.
* note: Must run before hostenv_*.js file.
*
* @author Copyright 2004 Mark D. Anderson ([email protected])
* TODOC: should the copyright be changed to Dojo Foundation?
* @license Licensed under the Academic Free License 2.1 http://www.opensource.org/licenses/afl-2.1.php
*
* $Id: bootstrap1.js 6824 2006-12-06 09:34:32Z alex $
*/
// TODOC: HOW TO DOC THE BELOW?
// @global: djConfig
// summary:
// Application code can set the global 'djConfig' prior to loading
// the library to override certain global settings for how dojo works.
// description: The variables that can be set are as follows:
// - isDebug: false
// - allowQueryConfig: false
// - baseScriptUri: ""
// - baseRelativePath: ""
// - libraryScriptUri: ""
// - iePreventClobber: false
// - ieClobberMinimal: true
// - locale: undefined
// - extraLocale: undefined
// - preventBackButtonFix: true
// - searchIds: []
// - parseWidgets: true
// TODOC: HOW TO DOC THESE VARIABLES?
// TODOC: IS THIS A COMPLETE LIST?
// note:
// 'djConfig' does not exist under 'dojo.*' so that it can be set before the
// 'dojo' variable exists.
// note:
// Setting any of these variables *after* the library has loaded does nothing at all.
// TODOC: is this still true? Release notes for 0.3 indicated they could be set after load.
//
//TODOC: HOW TO DOC THIS?
// @global: dj_global
// summary:
// an alias for the top-level global object in the host environment
// (e.g., the window object in a browser).
// description:
// Refer to 'dj_global' rather than referring to window to ensure your
// code runs correctly in contexts other than web browsers (eg: Rhino on a server).
var dj_global = this;
//TODOC: HOW TO DOC THIS?
// @global: dj_currentContext
// summary:
// Private global context object. Where 'dj_global' always refers to the boot-time
// global context, 'dj_currentContext' can be modified for temporary context shifting.
// dojo.global() returns dj_currentContext.
// description:
// Refer to dojo.global() rather than referring to dj_global to ensure your
// code runs correctly in managed contexts.
var dj_currentContext = this;
// ****************************************************************
// global public utils
// TODOC: DO WE WANT TO NOTE THAT THESE ARE GLOBAL PUBLIC UTILS?
// ****************************************************************
function dj_undef(/*String*/ name, /*Object?*/ object){
//summary: Returns true if 'name' is defined on 'object' (or globally if 'object' is null).
//description: Note that 'defined' and 'exists' are not the same concept.
return (typeof (object || dj_currentContext)[name] == "undefined"); // Boolean
}
// make sure djConfig is defined
if(dj_undef("djConfig", this)){
var djConfig = {};
}
//TODOC: HOW TO DOC THIS?
// dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
if(dj_undef("dojo", this)){
var dojo = {};
}
dojo.global = function(){
// summary:
// return the current global context object
// (e.g., the window object in a browser).
// description:
// Refer to 'dojo.global()' rather than referring to window to ensure your
// code runs correctly in contexts other than web browsers (eg: Rhino on a server).
return dj_currentContext;
}
// Override locale setting, if specified
dojo.locale = djConfig.locale;
//TODOC: HOW TO DOC THIS?
dojo.version = {
// summary: version number of this instance of dojo.
major: 0, minor: 4, patch: 1, flag: "",
revision: Number("$Rev: 6824 $".match(/[0-9]+/)[0]),
toString: function(){
with(dojo.version){
return major + "." + minor + "." + patch + flag + " (" + revision + ")"; // String
}
}
}
dojo.evalProp = function(/*String*/ name, /*Object*/ object, /*Boolean?*/ create){
// summary: Returns 'object[name]'. If not defined and 'create' is true, will return a new Object.
// description:
// Returns null if 'object[name]' is not defined and 'create' is not true.
// Note: 'defined' and 'exists' are not the same concept.
if((!object)||(!name)) return undefined; // undefined
if(!dj_undef(name, object)) return object[name]; // mixed
return (create ? (object[name]={}) : undefined); // mixed
}
dojo.parseObjPath = function(/*String*/ path, /*Object?*/ context, /*Boolean?*/ create){
// summary: Parse string path to an object, and return corresponding object reference and property name.
// description:
// Returns an object with two properties, 'obj' and 'prop'.
// 'obj[prop]' is the reference indicated by 'path'.
// path: Path to an object, in the form "A.B.C".
// context: Object to use as root of path. Defaults to 'dojo.global()'.
// create: If true, Objects will be created at any point along the 'path' that is undefined.
var object = (context || dojo.global());
var names = path.split('.');
var prop = names.pop();
for (var i=0,l=names.length;i 1) {
dh.modulesLoadedListeners.push(function() {
obj[functionName]();
});
}
//Added for xdomain loading. dojo.addOnLoad is used to
//indicate callbacks after doing some dojo.require() statements.
//In the xdomain case, if all the requires are loaded (after initial
//page load), then immediately call any listeners.
if(dh.post_load_ && dh.inFlightCount == 0 && !dh.loadNotifying){
dh.callLoaded();
}
}
dojo.addOnUnload = function(/*Object?*/obj, /*String|Function?*/functionName){
// summary: registers a function to be triggered when the page unloads
//
// usage:
// dojo.addOnLoad(functionPointer)
// dojo.addOnLoad(object, "functionName")
var dh = dojo.hostenv;
if(arguments.length == 1){
dh.unloadListeners.push(obj);
} else if(arguments.length > 1) {
dh.unloadListeners.push(function() {
obj[functionName]();
});
}
}
dojo.hostenv.modulesLoaded = function(){
if(this.post_load_){ return; }
if(this.loadUriStack.length==0 && this.getTextStack.length==0){
if(this.inFlightCount > 0){
dojo.debug("files still in flight!");
return;
}
dojo.hostenv.callLoaded();
}
}
dojo.hostenv.callLoaded = function(){
if(typeof setTimeout == "object"){
setTimeout("dojo.hostenv.loaded();", 0);
}else{
dojo.hostenv.loaded();
}
}
dojo.hostenv.getModuleSymbols = function(/*String*/modulename){
// summary:
// Converts a module name in dotted JS notation to an array representing the path in the source tree
var syms = modulename.split(".");
for(var i = syms.length; i>0; i--){
var parentModule = syms.slice(0, i).join(".");
if((i==1) && !this.moduleHasPrefix(parentModule)){
// Support default module directory (sibling of dojo) for top-level modules
syms[0] = "../" + syms[0];
}else{
var parentModulePath = this.getModulePrefix(parentModule);
if(parentModulePath != parentModule){
syms.splice(0, i, parentModulePath);
break;
}
}
}
return syms; // Array
}
dojo.hostenv._global_omit_module_check = false;
dojo.hostenv.loadModule = function(/*String*/moduleName, /*Boolean?*/exactOnly, /*Boolean?*/omitModuleCheck){
// summary:
// loads a Javascript module from the appropriate URI
//
// description:
// loadModule("A.B") first checks to see if symbol A.B is defined.
// If it is, it is simply returned (nothing to do).
//
// If it is not defined, it will look for "A/B.js" in the script root directory,
// followed by "A.js".
//
// It throws if it cannot find a file to load, or if the symbol A.B is not
// defined after loading.
//
// It returns the object A.B.
//
// This does nothing about importing symbols into the current package.
// It is presumed that the caller will take care of that. For example, to import
// all symbols:
//
// with (dojo.hostenv.loadModule("A.B")) {
// ...
// }
//
// And to import just the leaf symbol:
//
// var B = dojo.hostenv.loadModule("A.B");
// ...
//
// dj_load is an alias for dojo.hostenv.loadModule
if(!moduleName){ return; }
omitModuleCheck = this._global_omit_module_check || omitModuleCheck;
var module = this.findModule(moduleName, false);
if(module){
return module;
}
// protect against infinite recursion from mutual dependencies
if(dj_undef(moduleName, this.loading_modules_)){
this.addedToLoadingCount.push(moduleName);
}
this.loading_modules_[moduleName] = 1;
// convert periods to slashes
var relpath = moduleName.replace(/\./g, '/') + '.js';
var nsyms = moduleName.split(".");
// this line allowed loading of a module manifest as if it were a namespace
// it's an interesting idea, but shouldn't be combined with 'namespaces' proper
// and leads to unwanted dependencies
// the effect can be achieved in other (albeit less-flexible) ways now, so I am
// removing this pending further design work
// perhaps we can explicitly define this idea of a 'module manifest', and subclass
// 'namespace manifest' from that
//dojo.getNamespace(nsyms[0]);
var syms = this.getModuleSymbols(moduleName);
var startedRelative = ((syms[0].charAt(0) != '/') && !syms[0].match(/^\w+:/));
var last = syms[syms.length - 1];
var ok;
// figure out if we're looking for a full package, if so, we want to do
// things slightly diffrently
if(last=="*"){
moduleName = nsyms.slice(0, -1).join('.');
while(syms.length){
syms.pop();
syms.push(this.pkgFileName);
relpath = syms.join("/") + '.js';
if(startedRelative && relpath.charAt(0)=="/"){
relpath = relpath.slice(1);
}
ok = this.loadPath(relpath, !omitModuleCheck ? moduleName : null);
if(ok){ break; }
syms.pop();
}
}else{
relpath = syms.join("/") + '.js';
moduleName = nsyms.join('.');
var modArg = !omitModuleCheck ? moduleName : null;
ok = this.loadPath(relpath, modArg);
if(!ok && !exactOnly){
syms.pop();
while(syms.length){
relpath = syms.join('/') + '.js';
ok = this.loadPath(relpath, modArg);
if(ok){ break; }
syms.pop();
relpath = syms.join('/') + '/'+this.pkgFileName+'.js';
if(startedRelative && relpath.charAt(0)=="/"){
relpath = relpath.slice(1);
}
ok = this.loadPath(relpath, modArg);
if(ok){ break; }
}
}
if(!ok && !omitModuleCheck){
dojo.raise("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
}
}
// check that the symbol was defined
//Don't bother if we're doing xdomain (asynchronous) loading.
if(!omitModuleCheck && !this["isXDomain"]){
// pass in false so we can give better error
module = this.findModule(moduleName, false);
if(!module){
dojo.raise("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'");
}
}
return module;
}
dojo.hostenv.startPackage = function(/*String*/packageName){
// summary:
// Creates a JavaScript package
//
// description:
// startPackage("A.B") follows the path, and at each level creates a new empty
// object or uses what already exists. It returns the result.
//
// packageName: the package to be created as a String in dot notation
//Make sure we have a string.
var fullPkgName = String(packageName);
var strippedPkgName = fullPkgName;
var syms = packageName.split(/\./);
if(syms[syms.length-1]=="*"){
syms.pop();
strippedPkgName = syms.join(".");
}
var evaledPkg = dojo.evalObjPath(strippedPkgName, true);
this.loaded_modules_[fullPkgName] = evaledPkg;
this.loaded_modules_[strippedPkgName] = evaledPkg;
return evaledPkg; // Object
}
dojo.hostenv.findModule = function(/*String*/moduleName, /*Boolean?*/mustExist){
// summary:
// Returns the Object representing the module, if it exists, otherwise null.
//
// moduleName A fully qualified module including package name, like 'A.B'.
// mustExist Optional, default false. throw instead of returning null
// if the module does not currently exist.
var lmn = String(moduleName);
if(this.loaded_modules_[lmn]){
return this.loaded_modules_[lmn]; // Object
}
if(mustExist){
dojo.raise("no loaded module named '" + moduleName + "'");
}
return null; // null
}
//Start of old bootstrap2:
dojo.kwCompoundRequire = function(/*Object containing Arrays*/modMap){
// description:
// This method taks a "map" of arrays which one can use to optionally load dojo
// modules. The map is indexed by the possible dojo.hostenv.name_ values, with
// two additional values: "default" and "common". The items in the "default"
// array will be loaded if none of the other items have been choosen based on
// the hostenv.name_ item. The items in the "common" array will _always_ be
// loaded, regardless of which list is chosen. Here's how it's normally
// called:
//
// dojo.kwCompoundRequire({
// browser: [
// ["foo.bar.baz", true, true], // an example that passes multiple args to loadModule()
// "foo.sample.*",
// "foo.test,
// ],
// default: [ "foo.sample.*" ],
// common: [ "really.important.module.*" ]
// });
var common = modMap["common"]||[];
var result = modMap[dojo.hostenv.name_] ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);
for(var x=0; x,
// relative to Dojo root. For example, module acme is mapped to ../acme.
// If you want to use a different module name, use dojo.registerModulePath.
return dojo.hostenv.setModulePrefix(module, prefix);
}
dojo.setModulePrefix = function(/*String*/module, /*String*/prefix){
// summary: maps a module name to a path
dojo.deprecated('dojo.setModulePrefix("' + module + '", "' + prefix + '")', "replaced by dojo.registerModulePath", "0.5");
return dojo.registerModulePath(module, prefix);
}
dojo.exists = function(/*Object*/obj, /*String*/name){
// summary: determine if an object supports a given method
// description: useful for longer api chains where you have to test each object in the chain
var p = name.split(".");
for(var i = 0; i < p.length; i++){
if(!obj[p[i]]){ return false; } // Boolean
obj = obj[p[i]];
}
return true; // Boolean
}
// Localization routines
dojo.hostenv.normalizeLocale = function(/*String?*/locale){
// summary:
// Returns canonical form of locale, as used by Dojo. All variants are case-insensitive and are separated by '-'
// as specified in RFC 3066. If no locale is specified, the user agent's default is returned.
var result = locale ? locale.toLowerCase() : dojo.locale;
if(result == "root"){
result = "ROOT";
}
return result;// String
};
dojo.hostenv.searchLocalePath = function(/*String*/locale, /*Boolean*/down, /*Function*/searchFunc){
// summary:
// A helper method to assist in searching for locale-based resources. Will iterate through
// the variants of a particular locale, either up or down, executing a callback function.
// For example, "en-us" and true will try "en-us" followed by "en" and finally "ROOT".
locale = dojo.hostenv.normalizeLocale(locale);
var elements = locale.split('-');
var searchlist = [];
for(var i = elements.length; i > 0; i--){
searchlist.push(elements.slice(0, i).join('-'));
}
searchlist.push(false);
if(down){searchlist.reverse();}
for(var j = searchlist.length - 1; j >= 0; j--){
var loc = searchlist[j] || "ROOT";
var stop = searchFunc(loc);
if(stop){ break; }
}
}
//These two functions are placed outside of preloadLocalizations
//So that the xd loading can use/override them.
dojo.hostenv.localesGenerated /***BUILD:localesGenerated***/; // value will be inserted here at build time, if necessary
dojo.hostenv.registerNlsPrefix = function(){
// summary:
// Register module "nls" to point where Dojo can find pre-built localization files
dojo.registerModulePath("nls","nls");
}
dojo.hostenv.preloadLocalizations = function(){
// summary:
// Load built, flattened resource bundles, if available for all locales used in the page.
// Execute only once. Note that this is a no-op unless there is a build.
if(dojo.hostenv.localesGenerated){
dojo.hostenv.registerNlsPrefix();
function preload(locale){
locale = dojo.hostenv.normalizeLocale(locale);
dojo.hostenv.searchLocalePath(locale, true, function(loc){
for(var i=0; i bestLocale.length){
bestLocale = flatLocales[i];
}
}
}
if(!bestLocale){
bestLocale = "ROOT";
}
}
//See if the desired locale is already loaded.
var tempLocale = availableFlatLocales ? bestLocale : targetLocale;
var bundle = dojo.hostenv.findModule(bundlePackage);
var localizedBundle = null;
if(bundle){
if(djConfig.localizationComplete && bundle._built){return;}
var jsLoc = tempLocale.replace('-', '_');
var translationPackage = bundlePackage+"."+jsLoc;
localizedBundle = dojo.hostenv.findModule(translationPackage);
}
if(!localizedBundle){
bundle = dojo.hostenv.startPackage(bundlePackage);
var syms = dojo.hostenv.getModuleSymbols(moduleName);
var modpath = syms.concat("nls").join("/");
var parent;
dojo.hostenv.searchLocalePath(tempLocale, availableFlatLocales, function(loc){
var jsLoc = loc.replace('-', '_');
var translationPackage = bundlePackage + "." + jsLoc;
var loaded = false;
if(!dojo.hostenv.findModule(translationPackage)){
// Mark loaded whether it's found or not, so that further load attempts will not be made
dojo.hostenv.startPackage(translationPackage);
var module = [modpath];
if(loc != "ROOT"){module.push(loc);}
module.push(bundleName);
var filespec = module.join("/") + '.js';
loaded = dojo.hostenv.loadPath(filespec, null, function(hash){
// Use singleton with prototype to point to parent bundle, then mix-in result from loadPath
var clazz = function(){};
clazz.prototype = parent;
bundle[jsLoc] = new clazz();
for(var j in hash){ bundle[jsLoc][j] = hash[j]; }
});
}else{
loaded = true;
}
if(loaded && bundle[jsLoc]){
parent = bundle[jsLoc];
}else{
bundle[jsLoc] = parent;
}
if(availableFlatLocales){
//Stop the locale path searching if we know the availableFlatLocales, since
//the first call to this function will load the only bundle that is needed.
return true;
}
});
}
//Save the best locale bundle as the target locale bundle when we know the
//the available bundles.
if(availableFlatLocales && targetLocale != bestLocale){
bundle[targetLocale.replace('-', '_')] = bundle[bestLocale.replace('-', '_')];
}
};
(function(){
// If other locales are used, dojo.requireLocalization should load them as well, by default.
// Override dojo.requireLocalization to do load the default bundle, then iterate through the
// extraLocale list and load those translations as well, unless a particular locale was requested.
var extra = djConfig.extraLocale;
if(extra){
if(!extra instanceof Array){
extra = [extra];
}
var req = dojo.requireLocalization;
dojo.requireLocalization = function(m, b, locale, availableFlatLocales){
req(m,b,locale, availableFlatLocales);
if(locale){return;}
for(var i=0; i 1){
var paramStr = params[1];
var pairs = paramStr.split("&");
for(var x in pairs){
var sp = pairs[x].split("=");
// FIXME: is this eval dangerous?
if((sp[0].length > 9)&&(sp[0].substr(0, 9) == "djConfig.")){
var opt = sp[0].substr(9);
try{
djConfig[opt]=eval(sp[1]);
}catch(e){
djConfig[opt]=sp[1];
}
}
}
}
}
if(
((djConfig["baseScriptUri"] == "")||(djConfig["baseRelativePath"] == "")) &&
(document && document.getElementsByTagName)
){
var scripts = document.getElementsByTagName("script");
var rePkg = /(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i;
for(var i = 0; i < scripts.length; i++) {
var src = scripts[i].getAttribute("src");
if(!src) { continue; }
var m = src.match(rePkg);
if(m) {
var root = src.substring(0, m.index);
if(src.indexOf("bootstrap1") > -1) { root += "../"; }
if(!this["djConfig"]) { djConfig = {}; }
if(djConfig["baseScriptUri"] == "") { djConfig["baseScriptUri"] = root; }
if(djConfig["baseRelativePath"] == "") { djConfig["baseRelativePath"] = root; }
break;
}
}
}
// fill in the rendering support information in dojo.render.*
var dr = dojo.render;
var drh = dojo.render.html;
var drs = dojo.render.svg;
var dua = (drh.UA = navigator.userAgent);
var dav = (drh.AV = navigator.appVersion);
var t = true;
var f = false;
drh.capable = t;
drh.support.builtin = t;
dr.ver = parseFloat(drh.AV);
dr.os.mac = dav.indexOf("Macintosh") >= 0;
dr.os.win = dav.indexOf("Windows") >= 0;
// could also be Solaris or something, but it's the same browser
dr.os.linux = dav.indexOf("X11") >= 0;
drh.opera = dua.indexOf("Opera") >= 0;
drh.khtml = (dav.indexOf("Konqueror") >= 0)||(dav.indexOf("Safari") >= 0);
drh.safari = dav.indexOf("Safari") >= 0;
var geckoPos = dua.indexOf("Gecko");
drh.mozilla = drh.moz = (geckoPos >= 0)&&(!drh.khtml);
if (drh.mozilla) {
// gecko version is YYYYMMDD
drh.geckoVersion = dua.substring(geckoPos + 6, geckoPos + 14);
}
drh.ie = (document.all)&&(!drh.opera);
drh.ie50 = drh.ie && dav.indexOf("MSIE 5.0")>=0;
drh.ie55 = drh.ie && dav.indexOf("MSIE 5.5")>=0;
drh.ie60 = drh.ie && dav.indexOf("MSIE 6.0")>=0;
drh.ie70 = drh.ie && dav.indexOf("MSIE 7.0")>=0;
var cm = document["compatMode"];
drh.quirks = (cm == "BackCompat")||(cm == "QuirksMode")||drh.ie55||drh.ie50;
// TODO: is the HTML LANG attribute relevant?
dojo.locale = dojo.locale || (drh.ie ? navigator.userLanguage : navigator.language).toLowerCase();
dr.vml.capable=drh.ie;
drs.capable = f;
drs.support.plugin = f;
drs.support.builtin = f;
var tdoc = window["document"];
var tdi = tdoc["implementation"];
if((tdi)&&(tdi["hasFeature"])&&(tdi.hasFeature("org.w3c.dom.svg", "1.0"))){
drs.capable = t;
drs.support.builtin = t;
drs.support.plugin = f;
}
// webkits after 420 support SVG natively. The test string is "AppleWebKit/420+"
if(drh.safari){
var tmp = dua.split("AppleWebKit/")[1];
var ver = parseFloat(tmp.split(" ")[0]);
if(ver >= 420){
drs.capable = t;
drs.support.builtin = t;
drs.support.plugin = f;
}
}else{
}
})();
dojo.hostenv.startPackage("dojo.hostenv");
dojo.render.name = dojo.hostenv.name_ = 'browser';
dojo.hostenv.searchIds = [];
// These are in order of decreasing likelihood; this will change in time.
dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
dojo.hostenv.getXmlhttpObject = function(){
// summary: does the work of portably generating a new XMLHTTPRequest object.
var http = null;
var last_e = null;
try{ http = new XMLHttpRequest(); }catch(e){}
if(!http){
for(var i=0; i<3; ++i){
var progid = dojo.hostenv._XMLHTTP_PROGIDS[i];
try{
http = new ActiveXObject(progid);
}catch(e){
last_e = e;
}
if(http){
dojo.hostenv._XMLHTTP_PROGIDS = [progid]; // so faster next time
break;
}
}
/*if(http && !http.toString) {
http.toString = function() { "[object XMLHttpRequest]"; }
}*/
}
if(!http){
return dojo.raise("XMLHTTP not available", last_e);
}
return http; // XMLHTTPRequest instance
}
dojo.hostenv._blockAsync = false;
dojo.hostenv.getText = function(uri, async_cb, fail_ok){
// summary: Read the contents of the specified uri and return those contents.
// uri:
// A relative or absolute uri. If absolute, it still must be in
// the same "domain" as we are.
// async_cb:
// If not specified, load synchronously. If specified, load
// asynchronously, and use async_cb as the progress handler which
// takes the xmlhttp object as its argument. If async_cb, this
// function returns null.
// fail_ok:
// Default false. If fail_ok and !async_cb and loading fails,
// return null instead of throwing.
// need to block async callbacks from snatching this thread as the result
// of an async callback might call another sync XHR, this hangs khtml forever
// hostenv._blockAsync must also be checked in BrowserIO's watchInFlight()
// NOTE: must be declared before scope switches ie. this.getXmlhttpObject()
if(!async_cb){ this._blockAsync = true; }
var http = this.getXmlhttpObject();
function isDocumentOk(http){
var stat = http["status"];
// allow a 304 use cache, needed in konq (is this compliant with the http spec?)
return Boolean((!stat)||((200 <= stat)&&(300 > stat))||(stat==304));
}
if(async_cb){
var _this = this, timer = null, gbl = dojo.global();
var xhr = dojo.evalObjPath("dojo.io.XMLHTTPTransport");
http.onreadystatechange = function(){
if(timer){ gbl.clearTimeout(timer); timer = null; }
if(_this._blockAsync || (xhr && xhr._blockAsync)){
timer = gbl.setTimeout(function () { http.onreadystatechange.apply(this); }, 10);
}else{
if(4==http.readyState){
if(isDocumentOk(http)){
// dojo.debug("LOADED URI: "+uri);
async_cb(http.responseText);
}
}
}
}
}
http.open('GET', uri, async_cb ? true : false);
try{
http.send(null);
if(async_cb){
return null;
}
if(!isDocumentOk(http)){
var err = Error("Unable to load "+uri+" status:"+ http.status);
err.status = http.status;
err.responseText = http.responseText;
throw err;
}
}catch(e){
this._blockAsync = false;
if((fail_ok)&&(!async_cb)){
return null;
}else{
throw e;
}
}
this._blockAsync = false;
return http.responseText; // String
}
dojo.hostenv.defaultDebugContainerId = 'dojoDebug';
dojo.hostenv._println_buffer = [];
dojo.hostenv._println_safe = false;
dojo.hostenv.println = function(/*String*/line){
// summary:
// prints the provided line to whatever logging container is
// available. If the page isn't loaded yet, the line may be added
// to a buffer for printing later.
if(!dojo.hostenv._println_safe){
dojo.hostenv._println_buffer.push(line);
}else{
try {
var console = document.getElementById(djConfig.debugContainerId ?
djConfig.debugContainerId : dojo.hostenv.defaultDebugContainerId);
if(!console) { console = dojo.body(); }
var div = document.createElement("div");
div.appendChild(document.createTextNode(line));
console.appendChild(div);
} catch (e) {
try{
// safari needs the output wrapped in an element for some reason
document.write("" + line + "");
}catch(e2){
window.status = line;
}
}
}
}
dojo.addOnLoad(function(){
dojo.hostenv._println_safe = true;
while(dojo.hostenv._println_buffer.length > 0){
dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
}
});
function dj_addNodeEvtHdlr(/*DomNode*/node, /*String*/evtName, /*Function*/fp){
// summary:
// non-destructively adds the specified function to the node's
// evtName handler.
// node: the DomNode to add the handler to
// evtName: should be in the form "click" for "onclick" handlers
var oldHandler = node["on"+evtName] || function(){};
node["on"+evtName] = function(){
fp.apply(node, arguments);
oldHandler.apply(node, arguments);
}
return true;
}
// BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/)
function dj_load_init(e){
// allow multiple calls, only first one will take effect
// A bug in khtml calls events callbacks for document for event which isnt supported
// for example a created contextmenu event calls DOMContentLoaded, workaround
var type = (e && e.type) ? e.type.toLowerCase() : "load";
if(arguments.callee.initialized || (type!="domcontentloaded" && type!="load")){ return; }
arguments.callee.initialized = true;
if(typeof(_timer) != 'undefined'){
clearInterval(_timer);
delete _timer;
}
var initFunc = function(){
//perform initialization
if(dojo.render.html.ie){
dojo.hostenv.makeWidgets();
}
};
if(dojo.hostenv.inFlightCount == 0){
initFunc();
dojo.hostenv.modulesLoaded();
}else{
//This else case should be xdomain loading.
//Make sure this is the first thing in the load listener array.
//Part of the dojo.addOnLoad guarantee is that when the listeners are notified,
//It means the DOM (or page) has loaded and that widgets have been parsed.
dojo.hostenv.modulesLoadedListeners.unshift(initFunc);
}
}
// START DOMContentLoaded
// Mozilla and Opera 9 expose the event we could use
if(document.addEventListener){
if(dojo.render.html.opera || (dojo.render.html.moz && !djConfig.delayMozLoadingFix)){
document.addEventListener("DOMContentLoaded", dj_load_init, null);
}
// mainly for Opera 8.5, won't be fired if DOMContentLoaded fired already.
// also used for Mozilla because of trac #1640
window.addEventListener("load", dj_load_init, null);
}
// for Internet Explorer. readyState will not be achieved on init call, but dojo doesn't need it
// however, we'll include it because we don't know if there are other functions added that might.
// Note that this has changed because the build process strips all comments--including conditional
// ones.
if(dojo.render.html.ie && dojo.render.os.win){
document.attachEvent("onreadystatechange", function(e){
if(document.readyState == "complete"){
dj_load_init();
}
});
}
if (/(WebKit|khtml)/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
dj_load_init(); // call the onload handler
}
}, 10);
}
// END DOMContentLoaded
// IE WebControl hosted in an application can fire "beforeunload" and "unload"
// events when control visibility changes, causing Dojo to unload too soon. The
// following code fixes the problem
// Reference: http://support.microsoft.com/default.aspx?scid=kb;en-us;199155
if(dojo.render.html.ie){
dj_addNodeEvtHdlr(window, "beforeunload", function(){
dojo.hostenv._unloading = true;
window.setTimeout(function() {
dojo.hostenv._unloading = false;
}, 0);
});
}
dj_addNodeEvtHdlr(window, "unload", function(){
dojo.hostenv.unloaded();
if((!dojo.render.html.ie)||(dojo.render.html.ie && dojo.hostenv._unloading)){
dojo.hostenv.unloaded();
}
});
dojo.hostenv.makeWidgets = function(){
// you can put searchIds in djConfig and dojo.hostenv at the moment
// we should probably eventually move to one or the other
var sids = [];
if(djConfig.searchIds && djConfig.searchIds.length > 0) {
sids = sids.concat(djConfig.searchIds);
}
if(dojo.hostenv.searchIds && dojo.hostenv.searchIds.length > 0) {
sids = sids.concat(dojo.hostenv.searchIds);
}
if((djConfig.parseWidgets)||(sids.length > 0)){
if(dojo.evalObjPath("dojo.widget.Parse")){
// we must do this on a delay to avoid:
// http://www.shaftek.org/blog/archives/000212.html
// (IE bug)
var parser = new dojo.xml.Parse();
if(sids.length > 0){
for(var x=0; x");
} catch (e) {
var script = document.createElement("script");
script.src = spath;
document.getElementsByTagName("head")[0].appendChild(script);
}
}
}
})();
dojo.provide("dojo.lang.common");
dojo.lang.inherits = function(/*Function*/subclass, /*Function*/superclass){
// summary: Set up inheritance between two classes.
if(!dojo.lang.isFunction(superclass)){
dojo.raise("dojo.inherits: superclass argument ["+superclass+"] must be a function (subclass: ["+subclass+"']");
}
subclass.prototype = new superclass();
subclass.prototype.constructor = subclass;
subclass.superclass = superclass.prototype;
// DEPRECATED: super is a reserved word, use 'superclass'
subclass['super'] = superclass.prototype;
}
dojo.lang._mixin = function(/*Object*/ obj, /*Object*/ props){
// summary:
// Adds all properties and methods of props to obj. This addition is
// "prototype extension safe", so that instances of objects will not
// pass along prototype defaults.
var tobj = {};
for(var x in props){
// the "tobj" condition avoid copying properties in "props"
// inherited from Object.prototype. For example, if obj has a custom
// toString() method, don't overwrite it with the toString() method
// that props inherited from Object.protoype
if((typeof tobj[x] == "undefined") || (tobj[x] != props[x])){
obj[x] = props[x];
}
}
// IE doesn't recognize custom toStrings in for..in
if(dojo.render.html.ie
&& (typeof(props["toString"]) == "function")
&& (props["toString"] != obj["toString"])
&& (props["toString"] != tobj["toString"]))
{
obj.toString = props.toString;
}
return obj; // Object
}
dojo.lang.mixin = function(/*Object*/obj, /*Object...*/props){
// summary: Adds all properties and methods of props to obj.
for(var i=1, l=arguments.length; i -1; // boolean
}
/**
* Partial implmentation of is* functions from
* http://www.crockford.com/javascript/recommend.html
* NOTE: some of these may not be the best thing to use in all situations
* as they aren't part of core JS and therefore can't work in every case.
* See WARNING messages inline for tips.
*
* The following is* functions are fairly "safe"
*/
dojo.lang.isObject = function(/*anything*/ it){
// summary: Return true if it is an Object, Array or Function.
if(typeof it == "undefined"){ return false; }
return (typeof it == "object" || it === null || dojo.lang.isArray(it) || dojo.lang.isFunction(it)); // Boolean
}
dojo.lang.isArray = function(/*anything*/ it){
// summary: Return true if it is an Array.
return (it && it instanceof Array || typeof it == "array"); // Boolean
}
dojo.lang.isArrayLike = function(/*anything*/ it){
// summary:
// Return true if it can be used as an array (i.e. is an object with
// an integer length property).
if((!it)||(dojo.lang.isUndefined(it))){ return false; }
if(dojo.lang.isString(it)){ return false; }
if(dojo.lang.isFunction(it)){ return false; } // keeps out built-in constructors (Number, String, ...) which have length properties
if(dojo.lang.isArray(it)){ return true; }
// form node itself is ArrayLike, but not always iterable. Use form.elements instead.
if((it.tagName)&&(it.tagName.toLowerCase()=='form')){ return false; }
if(dojo.lang.isNumber(it.length) && isFinite(it.length)){ return true; }
return false; // Boolean
}
dojo.lang.isFunction = function(/*anything*/ it){
// summary: Return true if it is a Function.
return (it instanceof Function || typeof it == "function"); // Boolean
};
(function(){
// webkit treats NodeList as a function, which is bad
if((dojo.render.html.capable)&&(dojo.render.html["safari"])){
dojo.lang.isFunction = function(/*anything*/ it){
if((typeof(it) == "function") && (it == "[object NodeList]")) { return false; }
return (it instanceof Function || typeof it == "function"); // Boolean
}
}
})();
dojo.lang.isString = function(/*anything*/ it){
// summary: Return true if it is a String.
return (typeof it == "string" || it instanceof String);
}
dojo.lang.isAlien = function(/*anything*/ it){
// summary: Return true if it is not a built-in function. False if not.
if(!it){ return false; }
return !dojo.lang.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
}
dojo.lang.isBoolean = function(/*anything*/ it){
// summary: Return true if it is a Boolean.
return (it instanceof Boolean || typeof it == "boolean"); // Boolean
}
/**
* The following is***() functions are somewhat "unsafe". Fortunately,
* there are workarounds the the language provides and are mentioned
* in the WARNING messages.
*
*/
dojo.lang.isNumber = function(/*anything*/ it){
// summary: Return true if it is a number.
// description:
// WARNING - In most cases, isNaN(it) is sufficient to determine whether or not
// something is a number or can be used as such. For example, a number or string
// can be used interchangably when accessing array items (array["1"] is the same as
// array[1]) and isNaN will return false for both values ("1" and 1). However,
// isNumber("1") will return false, which is generally not too useful.
// Also, isNumber(NaN) returns true, again, this isn't generally useful, but there
// are corner cases (like when you want to make sure that two things are really
// the same type of thing). That is really where isNumber "shines".
//
// Recommendation - Use isNaN(it) when possible
return (it instanceof Number || typeof it == "number"); // Boolean
}
/*
* FIXME: Should isUndefined go away since it is error prone?
*/
dojo.lang.isUndefined = function(/*anything*/ it){
// summary: Return true if it is not defined.
// description:
// WARNING - In some cases, isUndefined will not behave as you
// might expect. If you do isUndefined(foo) and there is no earlier
// reference to foo, an error will be thrown before isUndefined is
// called. It behaves correctly if you scope yor object first, i.e.
// isUndefined(foo.bar) where foo is an object and bar isn't a
// property of the object.
//
// Recommendation - Use typeof foo == "undefined" when possible
return ((typeof(it) == "undefined")&&(it == undefined)); // Boolean
}
// end Crockford functions
dojo.provide("dojo.lang");
dojo.deprecated("dojo.lang", "replaced by dojo.lang.common", "0.5");
dojo.provide("dojo.dom");
dojo.dom.ELEMENT_NODE = 1;
dojo.dom.ATTRIBUTE_NODE = 2;
dojo.dom.TEXT_NODE = 3;
dojo.dom.CDATA_SECTION_NODE = 4;
dojo.dom.ENTITY_REFERENCE_NODE = 5;
dojo.dom.ENTITY_NODE = 6;
dojo.dom.PROCESSING_INSTRUCTION_NODE = 7;
dojo.dom.COMMENT_NODE = 8;
dojo.dom.DOCUMENT_NODE = 9;
dojo.dom.DOCUMENT_TYPE_NODE = 10;
dojo.dom.DOCUMENT_FRAGMENT_NODE = 11;
dojo.dom.NOTATION_NODE = 12;
dojo.dom.dojoml = "http://www.dojotoolkit.org/2004/dojoml";
/**
* comprehensive list of XML namespaces
**/
dojo.dom.xmlns = {
// summary
// aliases for various common XML namespaces
svg : "http://www.w3.org/2000/svg",
smil : "http://www.w3.org/2001/SMIL20/",
mml : "http://www.w3.org/1998/Math/MathML",
cml : "http://www.xml-cml.org",
xlink : "http://www.w3.org/1999/xlink",
xhtml : "http://www.w3.org/1999/xhtml",
xul : "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
xbl : "http://www.mozilla.org/xbl",
fo : "http://www.w3.org/1999/XSL/Format",
xsl : "http://www.w3.org/1999/XSL/Transform",
xslt : "http://www.w3.org/1999/XSL/Transform",
xi : "http://www.w3.org/2001/XInclude",
xforms : "http://www.w3.org/2002/01/xforms",
saxon : "http://icl.com/saxon",
xalan : "http://xml.apache.org/xslt",
xsd : "http://www.w3.org/2001/XMLSchema",
dt: "http://www.w3.org/2001/XMLSchema-datatypes",
xsi : "http://www.w3.org/2001/XMLSchema-instance",
rdf : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
rdfs : "http://www.w3.org/2000/01/rdf-schema#",
dc : "http://purl.org/dc/elements/1.1/",
dcq: "http://purl.org/dc/qualifiers/1.0",
"soap-env" : "http://schemas.xmlsoap.org/soap/envelope/",
wsdl : "http://schemas.xmlsoap.org/wsdl/",
AdobeExtensions : "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
};
dojo.dom.isNode = function(/* object */wh){
// summary:
// checks to see if wh is actually a node.
if(typeof Element == "function") {
try {
return wh instanceof Element; // boolean
} catch(e) {}
} else {
// best-guess
return wh && !isNaN(wh.nodeType); // boolean
}
}
dojo.dom.getUniqueId = function(){
// summary:
// returns a unique string for use with any DOM element
var _document = dojo.doc();
do {
var id = "dj_unique_" + (++arguments.callee._idIncrement);
}while(_document.getElementById(id));
return id; // string
}
dojo.dom.getUniqueId._idIncrement = 0;
dojo.dom.firstElement = dojo.dom.getFirstChildElement = function(/* Element */parentNode, /* string? */tagName){
// summary:
// returns the first child element matching tagName
var node = parentNode.firstChild;
while(node && node.nodeType != dojo.dom.ELEMENT_NODE){
node = node.nextSibling;
}
if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
node = dojo.dom.nextElement(node, tagName);
}
return node; // Element
}
dojo.dom.lastElement = dojo.dom.getLastChildElement = function(/* Element */parentNode, /* string? */tagName){
// summary:
// returns the last child element matching tagName
var node = parentNode.lastChild;
while(node && node.nodeType != dojo.dom.ELEMENT_NODE) {
node = node.previousSibling;
}
if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
node = dojo.dom.prevElement(node, tagName);
}
return node; // Element
}
dojo.dom.nextElement = dojo.dom.getNextSiblingElement = function(/* Node */node, /* string? */tagName){
// summary:
// returns the next sibling element matching tagName
if(!node) { return null; }
do {
node = node.nextSibling;
} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
return dojo.dom.nextElement(node, tagName);
}
return node; // Element
}
dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement = function(/* Node */node, /* string? */tagName){
// summary:
// returns the previous sibling element matching tagName
if(!node) { return null; }
if(tagName) { tagName = tagName.toLowerCase(); }
do {
node = node.previousSibling;
} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
return dojo.dom.prevElement(node, tagName);
}
return node; // Element
}
// TODO: hmph
/*this.forEachChildTag = function(node, unaryFunc) {
var child = this.getFirstChildTag(node);
while(child) {
if(unaryFunc(child) == "break") { break; }
child = this.getNextSiblingTag(child);
}
}*/
dojo.dom.moveChildren = function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim){
// summary:
// Moves children from srcNode to destNode and returns the count of
// children moved; will trim off text nodes if trim == true
var count = 0;
if(trim) {
while(srcNode.hasChildNodes() &&
srcNode.firstChild.nodeType == dojo.dom.TEXT_NODE) {
srcNode.removeChild(srcNode.firstChild);
}
while(srcNode.hasChildNodes() &&
srcNode.lastChild.nodeType == dojo.dom.TEXT_NODE) {
srcNode.removeChild(srcNode.lastChild);
}
}
while(srcNode.hasChildNodes()){
destNode.appendChild(srcNode.firstChild);
count++;
}
return count; // number
}
dojo.dom.copyChildren = function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim){
// summary:
// Copies children from srcNde to destNode and returns the count of
// children copied; will trim off text nodes if trim == true
var clonedNode = srcNode.cloneNode(true);
return this.moveChildren(clonedNode, destNode, trim); // number
}
dojo.dom.replaceChildren = function(/*Element*/node, /*Node*/newChild){
// summary:
// Removes all children of node and appends newChild. All the existing
// children will be destroyed.
// FIXME: what if newChild is an array-like object?
var nodes = [];
if(dojo.render.html.ie){
for(var i=0;i 0){
return ancestors[0]; // Node
}
node = node.parentNode;
}
if(returnFirstHit){ return null; }
return ancestors; // array
}
dojo.dom.getAncestorsByTag = function(/*Node*/node, /*String*/tag, /*boolean?*/returnFirstHit){
// summary:
// returns all ancestors matching tag (as tagName), will only return
// first one if returnFirstHit
tag = tag.toLowerCase();
return dojo.dom.getAncestors(node, function(el){
return ((el.tagName)&&(el.tagName.toLowerCase() == tag));
}, returnFirstHit); // Node || array
}
dojo.dom.getFirstAncestorByTag = function(/*Node*/node, /*string*/tag){
// summary:
// Returns first ancestor of node with tag tagName
return dojo.dom.getAncestorsByTag(node, tag, true); // Node
}
dojo.dom.isDescendantOf = function(/* Node */node, /* Node */ancestor, /* boolean? */guaranteeDescendant){
// summary
// Returns boolean if node is a descendant of ancestor
// guaranteeDescendant allows us to be a "true" isDescendantOf function
if(guaranteeDescendant && node) { node = node.parentNode; }
while(node) {
if(node == ancestor){
return true; // boolean
}
node = node.parentNode;
}
return false; // boolean
}
dojo.dom.innerXML = function(/*Node*/node){
// summary:
// Implementation of MS's innerXML function.
if(node.innerXML){
return node.innerXML; // string
}else if (node.xml){
return node.xml; // string
}else if(typeof XMLSerializer != "undefined"){
return (new XMLSerializer()).serializeToString(node); // string
}
}
dojo.dom.createDocument = function(){
// summary:
// cross-browser implementation of creating an XML document object.
var doc = null;
var _document = dojo.doc();
if(!dj_undef("ActiveXObject")){
var prefixes = [ "MSXML2", "Microsoft", "MSXML", "MSXML3" ];
for(var i = 0; i1) {
var _document = dojo.doc();
dojo.dom.replaceChildren(node, _document.createTextNode(text));
return text; // string
} else {
if(node.textContent != undefined){ //FF 1.5
return node.textContent; // string
}
var _result = "";
if (node == null) { return _result; }
for (var i = 0; i < node.childNodes.length; i++) {
switch (node.childNodes[i].nodeType) {
case 1: // ELEMENT_NODE
case 5: // ENTITY_REFERENCE_NODE
_result += dojo.dom.textContent(node.childNodes[i]);
break;
case 3: // TEXT_NODE
case 2: // ATTRIBUTE_NODE
case 4: // CDATA_SECTION_NODE
_result += node.childNodes[i].nodeValue;
break;
default:
break;
}
}
return _result; // string
}
}
dojo.dom.hasParent = function(/*Node*/node){
// summary:
// returns whether or not node is a child of another node.
return Boolean(node && node.parentNode && dojo.dom.isNode(node.parentNode)); // boolean
}
/**
* Examples:
*
* myFooNode =
* isTag(myFooNode, "foo"); // returns "foo"
* isTag(myFooNode, "bar"); // returns ""
* isTag(myFooNode, "FOO"); // returns ""
* isTag(myFooNode, "hey", "foo", "bar"); // returns "foo"
**/
dojo.dom.isTag = function(/* Node */node /* ... */){
// summary:
// determines if node has any of the provided tag names and returns
// the tag name that matches, empty string otherwise.
if(node && node.tagName) {
for(var i=1; i,
//which will be treated as an external javascript file in IE
var xscript = dojo.doc().createElement('script');
xscript.src = "javascript:'dojo.html.createExternalElement=function(doc, tag){ return doc.createElement(tag); }'";
dojo.doc().getElementsByTagName("head")[0].appendChild(xscript);
})();
}
}else{
//for other browsers, simply use document.createElement
//is enough
dojo.html.createExternalElement = function(/* HTMLDocument */doc, /* string */tag){
// summary
// Creates an element in the HTML document, here for ActiveX activation workaround.
return doc.createElement(tag); // HTMLElement
}
}
dojo.html._callDeprecated = function(inFunc, replFunc, args, argName, retValue){
dojo.deprecated("dojo.html." + inFunc,
"replaced by dojo.html." + replFunc + "(" + (argName ? "node, {"+ argName + ": " + argName + "}" : "" ) + ")" + (retValue ? "." + retValue : ""), "0.5");
var newArgs = [];
if(argName){ var argsIn = {}; argsIn[argName] = args[1]; newArgs.push(args[0]); newArgs.push(argsIn); }
else { newArgs = args }
var ret = dojo.html[replFunc].apply(dojo.html, args);
if(retValue){ return ret[retValue]; }
else { return ret; }
}
dojo.html.getViewportWidth = function(){
return dojo.html._callDeprecated("getViewportWidth", "getViewport", arguments, null, "width");
}
dojo.html.getViewportHeight = function(){
return dojo.html._callDeprecated("getViewportHeight", "getViewport", arguments, null, "height");
}
dojo.html.getViewportSize = function(){
return dojo.html._callDeprecated("getViewportSize", "getViewport", arguments);
}
dojo.html.getScrollTop = function(){
return dojo.html._callDeprecated("getScrollTop", "getScroll", arguments, null, "top");
}
dojo.html.getScrollLeft = function(){
return dojo.html._callDeprecated("getScrollLeft", "getScroll", arguments, null, "left");
}
dojo.html.getScrollOffset = function(){
return dojo.html._callDeprecated("getScrollOffset", "getScroll", arguments, null, "offset");
}
dojo.provide("dojo.uri.Uri");
dojo.uri = new function() {
this.dojoUri = function (/*dojo.uri.Uri||String*/uri) {
// summary: returns a Uri object resolved relative to the dojo root
return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
}
this.moduleUri = function(/*String*/module, /*dojo.uri.Uri||String*/uri){
// summary: returns a Uri object relative to a module
// description: Examples: dojo.uri.moduleUri("dojo","Editor"), or dojo.uri.moduleUri("acme","someWidget")
var loc = dojo.hostenv.getModuleSymbols(module).join('/');
//var loc = dojo.hostenv.getModulePrefix(module);
if(!loc){return null;}
if(loc.lastIndexOf("/") != loc.length-1){loc += "/";}
return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri()+loc,uri);
}
this.Uri = function (/*dojo.uri.Uri||String...*/) {
// summary: Constructor to create an object representing a URI.
// description:
// Each argument is evaluated in order relative to the next until
// a canonical uri is produced. To get an absolute Uri relative
// to the current document use
// new dojo.uri.Uri(document.baseURI, uri)
// TODO: support for IPv6, see RFC 2732
// resolve uri components relative to each other
var uri = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if(!arguments[i]) { continue; }
// Safari doesn't support this.constructor so we have to be explicit
var relobj = new dojo.uri.Uri(arguments[i].toString());
var uriobj = new dojo.uri.Uri(uri.toString());
if ((relobj.path=="")&&(relobj.scheme==null)&&(relobj.authority==null)&&(relobj.query==null)) {
if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; }
relobj = uriobj;
} else if (relobj.scheme == null) {
relobj.scheme = uriobj.scheme;
if (relobj.authority == null) {
relobj.authority = uriobj.authority;
if (relobj.path.charAt(0) != "/") {
var path = uriobj.path.substring(0,
uriobj.path.lastIndexOf("/") + 1) + relobj.path;
var segs = path.split("/");
for (var j = 0; j < segs.length; j++) {
if (segs[j] == ".") {
if (j == segs.length - 1) { segs[j] = ""; }
else { segs.splice(j, 1); j--; }
} else if (j > 0 && !(j == 1 && segs[0] == "") &&
segs[j] == ".." && segs[j-1] != "..") {
if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; }
else { segs.splice(j - 1, 2); j -= 2; }
}
}
relobj.path = segs.join("/");
}
}
}
uri = "";
if (relobj.scheme != null) { uri += relobj.scheme + ":"; }
if (relobj.authority != null) { uri += "//" + relobj.authority; }
uri += relobj.path;
if (relobj.query != null) { uri += "?" + relobj.query; }
if (relobj.fragment != null) { uri += "#" + relobj.fragment; }
}
this.uri = uri.toString();
// break the uri into its main components
var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
var r = this.uri.match(new RegExp(regexp));
this.scheme = r[2] || (r[1] ? "" : null);
this.authority = r[4] || (r[3] ? "" : null);
this.path = r[5]; // can never be undefined
this.query = r[7] || (r[6] ? "" : null);
this.fragment = r[9] || (r[8] ? "" : null);
if (this.authority != null) {
// server based naming authority
regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
r = this.authority.match(new RegExp(regexp));
this.user = r[3] || null;
this.password = r[4] || null;
this.host = r[5];
this.port = r[7] || null;
}
this.toString = function(){ return this.uri; }
}
};
dojo.provide("dojo.html.style");
dojo.html.getClass = function(/* HTMLElement */node){
// summary
// Returns the string value of the list of CSS classes currently assigned directly
// to the node in question. Returns an empty string if no class attribute is found;
node = dojo.byId(node);
if(!node){ return ""; }
var cs = "";
if(node.className){
cs = node.className;
}else if(dojo.html.hasAttribute(node, "class")){
cs = dojo.html.getAttribute(node, "class");
}
return cs.replace(/^\s+|\s+$/g, ""); // string
}
dojo.html.getClasses = function(/* HTMLElement */node) {
// summary
// Returns an array of CSS classes currently assigned directly to the node in question.
// Returns an empty array if no classes are found;
var c = dojo.html.getClass(node);
return (c == "") ? [] : c.split(/\s+/g); // array
}
dojo.html.hasClass = function(/* HTMLElement */node, /* string */classname){
// summary
// Returns whether or not the specified classname is a portion of the
// class list currently applied to the node. Does not cover cascaded
// styles, only classes directly applied to the node.
return (new RegExp('(^|\\s+)'+classname+'(\\s+|$)')).test(dojo.html.getClass(node)) // boolean
}
dojo.html.prependClass = function(/* HTMLElement */node, /* string */classStr){
// summary
// Adds the specified class to the beginning of the class list on the
// passed node. This gives the specified class the highest precidence
// when style cascading is calculated for the node. Returns true or
// false; indicating success or failure of the operation, respectively.
classStr += " " + dojo.html.getClass(node);
return dojo.html.setClass(node, classStr); // boolean
}
dojo.html.addClass = function(/* HTMLElement */node, /* string */classStr){
// summary
// Adds the specified class to the end of the class list on the
// passed &node;. Returns &true; or &false; indicating success or failure.
if (dojo.html.hasClass(node, classStr)) {
return false;
}
classStr = (dojo.html.getClass(node) + " " + classStr).replace(/^\s+|\s+$/g,"");
return dojo.html.setClass(node, classStr); // boolean
}
dojo.html.setClass = function(/* HTMLElement */node, /* string */classStr){
// summary
// Clobbers the existing list of classes for the node, replacing it with
// the list given in the 2nd argument. Returns true or false
// indicating success or failure.
node = dojo.byId(node);
var cs = new String(classStr);
try{
if(typeof node.className == "string"){
node.className = cs;
}else if(node.setAttribute){
node.setAttribute("class", classStr);
node.className = cs;
}else{
return false;
}
}catch(e){
dojo.debug("dojo.html.setClass() failed", e);
}
return true;
}
dojo.html.removeClass = function(/* HTMLElement */node, /* string */classStr, /* boolean? */allowPartialMatches){
// summary
// Removes the className from the node;. Returns true or false indicating success or failure.
try{
if (!allowPartialMatches) {
var newcs = dojo.html.getClass(node).replace(new RegExp('(^|\\s+)'+classStr+'(\\s+|$)'), "$1$2");
} else {
var newcs = dojo.html.getClass(node).replace(classStr,'');
}
dojo.html.setClass(node, newcs);
}catch(e){
dojo.debug("dojo.html.removeClass() failed", e);
}
return true; // boolean
}
dojo.html.replaceClass = function(/* HTMLElement */node, /* string */newClass, /* string */oldClass) {
// summary
// Replaces 'oldClass' and adds 'newClass' to node
dojo.html.removeClass(node, oldClass);
dojo.html.addClass(node, newClass);
}
// Enum type for getElementsByClass classMatchType arg:
dojo.html.classMatchType = {
ContainsAll : 0, // all of the classes are part of the node's class (default)
ContainsAny : 1, // any of the classes are part of the node's class
IsOnly : 2 // only all of the classes are part of the node's class
}
dojo.html.getElementsByClass = function(
/* string */classStr,
/* HTMLElement? */parent,
/* string? */nodeType,
/* integer? */classMatchType,
/* boolean? */useNonXpath
){
// summary
// Returns an array of nodes for the given classStr, children of a
// parent, and optionally of a certain nodeType
// FIXME: temporarily set to false because of several dojo tickets related
// to the xpath version not working consistently in firefox.
useNonXpath = false;
var _document = dojo.doc();
parent = dojo.byId(parent) || _document;
var classes = classStr.split(/\s+/g);
var nodes = [];
if( classMatchType != 1 && classMatchType != 2 ) classMatchType = 0; // make it enum
var reClass = new RegExp("(\\s|^)((" + classes.join(")|(") + "))(\\s|$)");
var srtLength = classes.join(" ").length;
var candidateNodes = [];
if(!useNonXpath && _document.evaluate) { // supports dom 3 xpath
var xpath = ".//" + (nodeType || "*") + "[contains(";
if(classMatchType != dojo.html.classMatchType.ContainsAny){
xpath += "concat(' ',@class,' '), ' " +
classes.join(" ') and contains(concat(' ',@class,' '), ' ") +
" ')";
if (classMatchType == 2) {
xpath += " and string-length(@class)="+srtLength+"]";
}else{
xpath += "]";
}
}else{
xpath += "concat(' ',@class,' '), ' " +
classes.join(" ') or contains(concat(' ',@class,' '), ' ") +
" ')]";
}
var xpathResult = _document.evaluate(xpath, parent, null, XPathResult.ANY_TYPE, null);
var result = xpathResult.iterateNext();
while(result){
try{
candidateNodes.push(result);
result = xpathResult.iterateNext();
}catch(e){ break; }
}
return candidateNodes; // NodeList
}else{
if(!nodeType){
nodeType = "*";
}
candidateNodes = parent.getElementsByTagName(nodeType);
var node, i = 0;
outer:
while(node = candidateNodes[i++]){
var nodeClasses = dojo.html.getClasses(node);
if(nodeClasses.length == 0){ continue outer; }
var matches = 0;
for(var j = 0; j < nodeClasses.length; j++){
if(reClass.test(nodeClasses[j])){
if(classMatchType == dojo.html.classMatchType.ContainsAny){
nodes.push(node);
continue outer;
}else{
matches++;
}
}else{
if(classMatchType == dojo.html.classMatchType.IsOnly){
continue outer;
}
}
}
if(matches == classes.length){
if( (classMatchType == dojo.html.classMatchType.IsOnly)&&
(matches == nodeClasses.length)){
nodes.push(node);
}else if(classMatchType == dojo.html.classMatchType.ContainsAll){
nodes.push(node);
}
}
}
return nodes; // NodeList
}
}
dojo.html.getElementsByClassName = dojo.html.getElementsByClass;
dojo.html.toCamelCase = function(/* string */selector){
// summary
// Translates a CSS selector string to a camel-cased one.
var arr = selector.split('-'), cc = arr[0];
for(var i = 1; i < arr.length; i++) {
cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
}
return cc; // string
}
dojo.html.toSelectorCase = function(/* string */selector){
// summary
// Translates a camel cased string to a selector cased one.
return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase(); // string
}
dojo.html.getComputedStyle = function(/* HTMLElement */node, /* string */cssSelector, /* integer? */inValue){
// summary
// Returns the computed style of cssSelector on node.
node = dojo.byId(node);
// cssSelector may actually be in camel case, so force selector version
var cssSelector = dojo.html.toSelectorCase(cssSelector);
var property = dojo.html.toCamelCase(cssSelector);
if(!node || !node.style){
return inValue;
} else if (document.defaultView && dojo.html.isDescendantOf(node, node.ownerDocument)){ // W3, gecko, KHTML
try{
// mozilla segfaults when margin-* and node is removed from doc
// FIXME: need to figure out a if there is quicker workaround
var cs = document.defaultView.getComputedStyle(node, "");
if(cs){
return cs.getPropertyValue(cssSelector); // integer
}
}catch(e){ // reports are that Safari can throw an exception above
if(node.style.getPropertyValue){ // W3
return node.style.getPropertyValue(cssSelector); // integer
} else {
return inValue; // integer
}
}
} else if(node.currentStyle){ // IE
return node.currentStyle[property]; // integer
}
if(node.style.getPropertyValue){ // W3
return node.style.getPropertyValue(cssSelector); // integer
}else{
return inValue; // integer
}
}
dojo.html.getStyleProperty = function(/* HTMLElement */node, /* string */cssSelector){
// summary
// Returns the value of the passed style
node = dojo.byId(node);
return (node && node.style ? node.style[dojo.html.toCamelCase(cssSelector)] : undefined); // string
}
dojo.html.getStyle = function(/* HTMLElement */node, /* string */cssSelector){
// summary
// Returns the computed value of the passed style
var value = dojo.html.getStyleProperty(node, cssSelector);
return (value ? value : dojo.html.getComputedStyle(node, cssSelector)); // string || integer
}
dojo.html.setStyle = function(/* HTMLElement */node, /* string */cssSelector, /* string */value){
// summary
// Set the value of passed style on node
node = dojo.byId(node);
if(node && node.style){
var camelCased = dojo.html.toCamelCase(cssSelector);
node.style[camelCased] = value;
}
}
dojo.html.setStyleText = function (/* HTMLElement */target, /* string */text) {
// summary
// Try to set the entire cssText property of the passed target; equiv of setting style attribute.
try {
target.style.cssText = text;
} catch (e) {
target.setAttribute("style", text);
}
}
dojo.html.copyStyle = function(/* HTMLElement */target, /* HTMLElement */source){
// summary
// work around for opera which doesn't have cssText, and for IE which fails on setAttribute
if(!source.style.cssText){
target.setAttribute("style", source.getAttribute("style"));
}else{
target.style.cssText = source.style.cssText;
}
dojo.html.addClass(target, dojo.html.getClass(source));
}
dojo.html.getUnitValue = function(/* HTMLElement */node, /* string */cssSelector, /* boolean? */autoIsZero){
// summary
// Get the value of passed selector, with the specific units used
var s = dojo.html.getComputedStyle(node, cssSelector);
if((!s)||((s == 'auto')&&(autoIsZero))){
return { value: 0, units: 'px' }; // object
}
// FIXME: is regex inefficient vs. parseInt or some manual test?
var match = s.match(/(\-?[\d.]+)([a-z%]*)/i);
if (!match){return dojo.html.getUnitValue.bad;}
return { value: Number(match[1]), units: match[2].toLowerCase() }; // object
}
dojo.html.getUnitValue.bad = { value: NaN, units: '' };
dojo.html.getPixelValue = function(/* HTMLElement */node, /* string */cssSelector, /* boolean? */autoIsZero){
// summary
// Get the value of passed selector in pixels.
var result = dojo.html.getUnitValue(node, cssSelector, autoIsZero);
// FIXME: there is serious debate as to whether or not this is the right solution
if(isNaN(result.value)){
return 0; // integer
}
// FIXME: code exists for converting other units to px (see Dean Edward's IE7)
// but there are cross-browser complexities
if((result.value)&&(result.units != 'px')){
return NaN; // integer
}
return result.value; // integer
}
dojo.html.setPositivePixelValue = function(/* HTMLElement */node, /* string */selector, /* integer */value){
// summary
// Attempt to set the value of selector on node as a positive pixel value.
if(isNaN(value)){return false;}
node.style[selector] = Math.max(0, value) + 'px';
return true; // boolean
}
dojo.html.styleSheet = null;
// FIXME: this is a really basic stub for adding and removing cssRules, but
// it assumes that you know the index of the cssRule that you want to add
// or remove, making it less than useful. So we need something that can
// search for the selector that you you want to remove.
dojo.html.insertCssRule = function(/* string */selector, /* string */declaration, /* integer? */index) {
// summary
// Attempt to insert declaration as selector on the internal stylesheet; if index try to set it there.
if (!dojo.html.styleSheet) {
if (document.createStyleSheet) { // IE
dojo.html.styleSheet = document.createStyleSheet();
} else if (document.styleSheets[0]) { // rest
// FIXME: should create a new style sheet here
// fall back on an exsiting style sheet
dojo.html.styleSheet = document.styleSheets[0];
} else {
return null; // integer
} // fail
}
if (arguments.length < 3) { // index may == 0
if (dojo.html.styleSheet.cssRules) { // W3
index = dojo.html.styleSheet.cssRules.length;
} else if (dojo.html.styleSheet.rules) { // IE
index = dojo.html.styleSheet.rules.length;
} else {
return null; // integer
} // fail
}
if (dojo.html.styleSheet.insertRule) { // W3
var rule = selector + " { " + declaration + " }";
return dojo.html.styleSheet.insertRule(rule, index); // integer
} else if (dojo.html.styleSheet.addRule) { // IE
return dojo.html.styleSheet.addRule(selector, declaration, index); // integer
} else {
return null; // integer
} // fail
}
dojo.html.removeCssRule = function(/* integer? */index){
// summary
// Attempt to remove the rule at index.
if(!dojo.html.styleSheet){
dojo.debug("no stylesheet defined for removing rules");
return false;
}
if(dojo.render.html.ie){
if(!index){
index = dojo.html.styleSheet.rules.length;
dojo.html.styleSheet.removeRule(index);
}
}else if(document.styleSheets[0]){
if(!index){
index = dojo.html.styleSheet.cssRules.length;
}
dojo.html.styleSheet.deleteRule(index);
}
return true; // boolean
}
dojo.html._insertedCssFiles = []; // cache container needed because IE reformats cssText when added to DOM
dojo.html.insertCssFile = function(/* string */URI, /* HTMLDocument? */doc, /* boolean? */checkDuplicates, /* boolean */fail_ok){
// summary
// calls css by XmlHTTP and inserts it into DOM as
if(!URI){ return; }
if(!doc){ doc = document; }
var cssStr = dojo.hostenv.getText(URI, false, fail_ok);
if(cssStr===null){ return; }
cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
if(checkDuplicates){
var idx = -1, node, ent = dojo.html._insertedCssFiles;
for(var i = 0; i < ent.length; i++){
if((ent[i].doc == doc) && (ent[i].cssText == cssStr)){
idx = i; node = ent[i].nodeRef;
break;
}
}
// make sure we havent deleted our node
if(node){
var styles = doc.getElementsByTagName("style");
for(var i = 0; i < styles.length; i++){
if(styles[i] == node){
return;
}
}
// delete this entry
dojo.html._insertedCssFiles.shift(idx, 1);
}
}
var style = dojo.html.insertCssText(cssStr, doc);
dojo.html._insertedCssFiles.push({'doc': doc, 'cssText': cssStr, 'nodeRef': style});
// insert custom attribute ex dbgHref="../foo.css" usefull when debugging in DOM inspectors, no?
if(style && djConfig.isDebug){
style.setAttribute("dbgHref", URI);
}
return style; // HTMLStyleElement
}
dojo.html.insertCssText = function(/* string */cssStr, /* HTMLDocument? */doc, /* string? */URI){
// summary
// Attempt to insert CSS rules into the document through inserting a style element
// DomNode Style = insertCssText(String ".dojoMenu {color: green;}"[, DomDoc document, dojo.uri.Uri Url ])
if(!cssStr){
return; // HTMLStyleElement
}
if(!doc){ doc = document; }
if(URI){// fix paths in cssStr
cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
}
var style = doc.createElement("style");
style.setAttribute("type", "text/css");
// IE is b0rken enough to require that we add the element to the doc
// before changing it's properties
var head = doc.getElementsByTagName("head")[0];
if(!head){ // must have a head tag
dojo.debug("No head tag in document, aborting styles");
return; // HTMLStyleElement
}else{
head.appendChild(style);
}
if(style.styleSheet){// IE
var setFunc = function(){
try{
style.styleSheet.cssText = cssStr;
}catch(e){ dojo.debug(e); }
};
if(style.styleSheet.disabled){
setTimeout(setFunc, 10);
}else{
setFunc();
}
}else{ // w3c
var cssText = doc.createTextNode(cssStr);
style.appendChild(cssText);
}
return style; // HTMLStyleElement
}
dojo.html.fixPathsInCssText = function(/* string */cssStr, /* string */URI){
// summary
// usage: cssText comes from dojoroot/src/widget/templates/Foobar.css
// it has .dojoFoo { background-image: url(images/bar.png);} then uri should point to dojoroot/src/widget/templates/
if(!cssStr || !URI){ return; }
var match, str = "", url = "", urlChrs = "[\\t\\s\\w\\(\\)\\/\\.\\\\'\"-:#=&?~]+";
var regex = new RegExp('url\\(\\s*('+urlChrs+')\\s*\\)');
var regexProtocol = /(file|https?|ftps?):\/\//;
regexTrim = new RegExp("^[\\s]*(['\"]?)("+urlChrs+")\\1[\\s]*?$");
if(dojo.render.html.ie55 || dojo.render.html.ie60){
var regexIe = new RegExp("AlphaImageLoader\\((.*)src\=['\"]("+urlChrs+")['\"]");
// TODO: need to decide how to handle relative paths and AlphaImageLoader see #1441
// current implementation breaks on build with intern_strings
while(match = regexIe.exec(cssStr)){
url = match[2].replace(regexTrim, "$2");
if(!regexProtocol.exec(url)){
url = (new dojo.uri.Uri(URI, url).toString());
}
str += cssStr.substring(0, match.index) + "AlphaImageLoader(" + match[1] + "src='" + url + "'";
cssStr = cssStr.substr(match.index + match[0].length);
}
cssStr = str + cssStr;
str = "";
}
while(match = regex.exec(cssStr)){
url = match[1].replace(regexTrim, "$2");
if(!regexProtocol.exec(url)){
url = (new dojo.uri.Uri(URI, url).toString());
}
str += cssStr.substring(0, match.index) + "url(" + url + ")";
cssStr = cssStr.substr(match.index + match[0].length);
}
return str + cssStr; // string
}
dojo.html.setActiveStyleSheet = function(/* string */title){
// summary
// Activate style sheet with specified title.
var i = 0, a, els = dojo.doc().getElementsByTagName("link");
while (a = els[i++]) {
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")){
a.disabled = true;
if (a.getAttribute("title") == title) { a.disabled = false; }
}
}
}
dojo.html.getActiveStyleSheet = function(){
// summary
// return the title of the currently active stylesheet
var i = 0, a, els = dojo.doc().getElementsByTagName("link");
while (a = els[i++]) {
if (a.getAttribute("rel").indexOf("style") != -1
&& a.getAttribute("title")
&& !a.disabled
){
return a.getAttribute("title"); // string
}
}
return null; // string
}
dojo.html.getPreferredStyleSheet = function(){
// summary
// Return the preferred stylesheet title (i.e. link without alt attribute)
var i = 0, a, els = dojo.doc().getElementsByTagName("link");
while (a = els[i++]) {
if(a.getAttribute("rel").indexOf("style") != -1
&& a.getAttribute("rel").indexOf("alt") == -1
&& a.getAttribute("title")
){
return a.getAttribute("title"); // string
}
}
return null; // string
}
dojo.html.applyBrowserClass = function(/* HTMLElement */node){
// summary
// Applies pre-set class names based on browser & version to the passed node.
// Modified version of Morris' CSS hack.
var drh=dojo.render.html;
var classes = {
dj_ie: drh.ie,
dj_ie55: drh.ie55,
dj_ie6: drh.ie60,
dj_ie7: drh.ie70,
dj_iequirks: drh.ie && drh.quirks,
dj_opera: drh.opera,
dj_opera8: drh.opera && (Math.floor(dojo.render.version)==8),
dj_opera9: drh.opera && (Math.floor(dojo.render.version)==9),
dj_khtml: drh.khtml,
dj_safari: drh.safari,
dj_gecko: drh.mozilla
}; // no dojo unsupported browsers
for(var p in classes){
if(classes[p]){
dojo.html.addClass(node, p);
}
}
};
dojo.provide("dojo.html.*");
dojo.provide("dojo.html.display");
dojo.html._toggle = function(node, tester, setter){
node = dojo.byId(node);
setter(node, !tester(node));
return tester(node);
}
dojo.html.show = function(/* HTMLElement */node){
// summary
// Show the passed element by reverting display property set by dojo.html.hide
node = dojo.byId(node);
if(dojo.html.getStyleProperty(node, 'display')=='none'){
dojo.html.setStyle(node, 'display', (node.dojoDisplayCache||''));
node.dojoDisplayCache = undefined; // cannot use delete on a node in IE6
}
}
dojo.html.hide = function(/* HTMLElement */node){
// summary
// Hide the passed element by setting display:none
node = dojo.byId(node);
if(typeof node["dojoDisplayCache"] == "undefined"){ // it could == '', so we cannot say !node.dojoDisplayCount
var d = dojo.html.getStyleProperty(node, 'display')
if(d!='none'){
node.dojoDisplayCache = d;
}
}
dojo.html.setStyle(node, 'display', 'none');
}
dojo.html.setShowing = function(/* HTMLElement */node, /* boolean? */showing){
// summary
// Calls show() if showing is true, hide() otherwise
dojo.html[(showing ? 'show' : 'hide')](node);
}
dojo.html.isShowing = function(/* HTMLElement */node){
// summary
// Returns whether the element is displayed or not.
// FIXME: returns true if node is bad, isHidden would be easier to make correct
return (dojo.html.getStyleProperty(node, 'display') != 'none'); // boolean
}
dojo.html.toggleShowing = function(/* HTMLElement */node){
// summary
// Call setShowing() on node with the complement of isShowing(), then return the new value of isShowing()
return dojo.html._toggle(node, dojo.html.isShowing, dojo.html.setShowing); // boolean
}
// Simple mapping of tag names to display values
// FIXME: simplistic
dojo.html.displayMap = { tr: '', td: '', th: '', img: 'inline', span: 'inline', input: 'inline', button: 'inline' };
dojo.html.suggestDisplayByTagName = function(/* HTMLElement */node){
// summary
// Suggest a value for the display property that will show 'node' based on it's tag
node = dojo.byId(node);
if(node && node.tagName){
var tag = node.tagName.toLowerCase();
return (tag in dojo.html.displayMap ? dojo.html.displayMap[tag] : 'block'); // string
}
}
dojo.html.setDisplay = function(/* HTMLElement */node, /* string */display){
// summary
// Sets the value of style.display to value of 'display' parameter if it is a string.
// Otherwise, if 'display' is false, set style.display to 'none'.
// Finally, set 'display' to a suggested display value based on the node's tag
dojo.html.setStyle(node, 'display', ((display instanceof String || typeof display == "string") ? display : (display ? dojo.html.suggestDisplayByTagName(node) : 'none')));
}
dojo.html.isDisplayed = function(/* HTMLElement */node){
// summary
// Is true if the the computed display style for node is not 'none'
// FIXME: returns true if node is bad, isNotDisplayed would be easier to make correct
return (dojo.html.getComputedStyle(node, 'display') != 'none'); // boolean
}
dojo.html.toggleDisplay = function(/* HTMLElement */node){
// summary
// Call setDisplay() on node with the complement of isDisplayed(), then
// return the new value of isDisplayed()
return dojo.html._toggle(node, dojo.html.isDisplayed, dojo.html.setDisplay); // boolean
}
dojo.html.setVisibility = function(/* HTMLElement */node, /* string */visibility){
// summary
// Sets the value of style.visibility to value of 'visibility' parameter if it is a string.
// Otherwise, if 'visibility' is false, set style.visibility to 'hidden'. Finally, set style.visibility to 'visible'.
dojo.html.setStyle(node, 'visibility', ((visibility instanceof String || typeof visibility == "string") ? visibility : (visibility ? 'visible' : 'hidden')));
}
dojo.html.isVisible = function(/* HTMLElement */node){
// summary
// Returns true if the the computed visibility style for node is not 'hidden'
// FIXME: returns true if node is bad, isInvisible would be easier to make correct
return (dojo.html.getComputedStyle(node, 'visibility') != 'hidden'); // boolean
}
dojo.html.toggleVisibility = function(node){
// summary
// Call setVisibility() on node with the complement of isVisible(), then return the new value of isVisible()
return dojo.html._toggle(node, dojo.html.isVisible, dojo.html.setVisibility); // boolean
}
dojo.html.setOpacity = function(/* HTMLElement */node, /* float */opacity, /* boolean? */dontFixOpacity){
// summary
// Sets the opacity of node in a cross-browser way.
// float between 0.0 (transparent) and 1.0 (opaque)
node = dojo.byId(node);
var h = dojo.render.html;
if(!dontFixOpacity){
if( opacity >= 1.0){
if(h.ie){
dojo.html.clearOpacity(node);
return;
}else{
opacity = 0.999999;
}
}else if( opacity < 0.0){ opacity = 0; }
}
if(h.ie){
if(node.nodeName.toLowerCase() == "tr"){
// FIXME: is this too naive? will we get more than we want?
var tds = node.getElementsByTagName("td");
for(var x=0; x= 0.999999 ? 1.0 : Number(opac); // float
}
dojo.provide("dojo.html.layout");
dojo.html.sumAncestorProperties = function(/* HTMLElement */node, /* string */prop){
// summary
// Returns the sum of the passed property on all ancestors of node.
node = dojo.byId(node);
if(!node){ return 0; } // FIXME: throw an error?
var retVal = 0;
while(node){
if(dojo.html.getComputedStyle(node, 'position') == 'fixed'){
return 0;
}
var val = node[prop];
if(val){
retVal += val - 0;
if(node==dojo.body()){ break; }// opera and khtml #body & #html has the same values, we only need one value
}
node = node.parentNode;
}
return retVal; // integer
}
dojo.html.setStyleAttributes = function(/* HTMLElement */node, /* string */attributes) {
// summary
// allows a dev to pass a string similar to what you'd pass in style="", and apply it to a node.
node = dojo.byId(node);
var splittedAttribs=attributes.replace(/(;)?\s*$/, "").split(";");
for(var i=0; i0){
ret.x += isNaN(n) ? 0 : n;
}
var m = curnode["offsetTop"];
ret.y += isNaN(m) ? 0 : m;
curnode = curnode.offsetParent;
}while((curnode != endNode)&&(curnode != null));
}else if(node["x"]&&node["y"]){
ret.x += isNaN(node.x) ? 0 : node.x;
ret.y += isNaN(node.y) ? 0 : node.y;
}
}
// account for document scrolling!
if(includeScroll){
var scroll = dojo.html.getScroll();
ret.y += scroll.top;
ret.x += scroll.left;
}
var extentFuncArray=[dojo.html.getPaddingExtent, dojo.html.getBorderExtent, dojo.html.getMarginExtent];
if(nativeBoxType > targetBoxType){
for(var i=targetBoxType;inativeBoxType;--i){
ret.y -= extentFuncArray[i-1](node, 'top');
ret.x -= extentFuncArray[i-1](node, 'left');
}
}
ret.top = ret.y;
ret.left = ret.x;
return ret; // object
}
dojo.html.isPositionAbsolute = function(/* HTMLElement */node){
// summary
// Returns true if the element is absolutely positioned.
return (dojo.html.getComputedStyle(node, 'position') == 'absolute'); // boolean
}
dojo.html._sumPixelValues = function(/* HTMLElement */node, selectors, autoIsZero){
var total = 0;
for(var x=0; x 4 ) { coords.pop(); }
var ret = {
left: coords[0],
top: coords[1],
width: coords[2],
height: coords[3]
};
}else if(!coords.nodeType && !(coords instanceof String || typeof coords == "string") &&
('width' in coords || 'height' in coords || 'left' in coords ||
'x' in coords || 'top' in coords || 'y' in coords)){
// coords is a coordinate object or at least part of one
var ret = {
left: coords.left||coords.x||0,
top: coords.top||coords.y||0,
width: coords.width||0,
height: coords.height||0
};
}else{
// coords is an dom object (or dom object id); return it's coordinates
var node = dojo.byId(coords);
var pos = dojo.html.abs(node, includeScroll, boxtype);
var marginbox = dojo.html.getMarginBox(node);
var ret = {
left: pos.left,
top: pos.top,
width: marginbox.width,
height: marginbox.height
};
}
ret.x = ret.left;
ret.y = ret.top;
return ret; // object
}
dojo.html.setMarginBoxWidth = dojo.html.setOuterWidth = function(node, width){
return dojo.html._callDeprecated("setMarginBoxWidth", "setMarginBox", arguments, "width");
}
dojo.html.setMarginBoxHeight = dojo.html.setOuterHeight = function(){
return dojo.html._callDeprecated("setMarginBoxHeight", "setMarginBox", arguments, "height");
}
dojo.html.getMarginBoxWidth = dojo.html.getOuterWidth = function(){
return dojo.html._callDeprecated("getMarginBoxWidth", "getMarginBox", arguments, null, "width");
}
dojo.html.getMarginBoxHeight = dojo.html.getOuterHeight = function(){
return dojo.html._callDeprecated("getMarginBoxHeight", "getMarginBox", arguments, null, "height");
}
dojo.html.getTotalOffset = function(node, type, includeScroll){
return dojo.html._callDeprecated("getTotalOffset", "getAbsolutePosition", arguments, null, type);
}
dojo.html.getAbsoluteX = function(node, includeScroll){
return dojo.html._callDeprecated("getAbsoluteX", "getAbsolutePosition", arguments, null, "x");
}
dojo.html.getAbsoluteY = function(node, includeScroll){
return dojo.html._callDeprecated("getAbsoluteY", "getAbsolutePosition", arguments, null, "y");
}
dojo.html.totalOffsetLeft = function(node, includeScroll){
return dojo.html._callDeprecated("totalOffsetLeft", "getAbsolutePosition", arguments, null, "left");
}
dojo.html.totalOffsetTop = function(node, includeScroll){
return dojo.html._callDeprecated("totalOffsetTop", "getAbsolutePosition", arguments, null, "top");
}
dojo.html.getMarginWidth = function(node){
return dojo.html._callDeprecated("getMarginWidth", "getMargin", arguments, null, "width");
}
dojo.html.getMarginHeight = function(node){
return dojo.html._callDeprecated("getMarginHeight", "getMargin", arguments, null, "height");
}
dojo.html.getBorderWidth = function(node){
return dojo.html._callDeprecated("getBorderWidth", "getBorder", arguments, null, "width");
}
dojo.html.getBorderHeight = function(node){
return dojo.html._callDeprecated("getBorderHeight", "getBorder", arguments, null, "height");
}
dojo.html.getPaddingWidth = function(node){
return dojo.html._callDeprecated("getPaddingWidth", "getPadding", arguments, null, "width");
}
dojo.html.getPaddingHeight = function(node){
return dojo.html._callDeprecated("getPaddingHeight", "getPadding", arguments, null, "height");
}
dojo.html.getPadBorderWidth = function(node){
return dojo.html._callDeprecated("getPadBorderWidth", "getPadBorder", arguments, null, "width");
}
dojo.html.getPadBorderHeight = function(node){
return dojo.html._callDeprecated("getPadBorderHeight", "getPadBorder", arguments, null, "height");
}
dojo.html.getBorderBoxWidth = dojo.html.getInnerWidth = function(){
return dojo.html._callDeprecated("getBorderBoxWidth", "getBorderBox", arguments, null, "width");
}
dojo.html.getBorderBoxHeight = dojo.html.getInnerHeight = function(){
return dojo.html._callDeprecated("getBorderBoxHeight", "getBorderBox", arguments, null, "height");
}
dojo.html.getContentBoxWidth = dojo.html.getContentWidth = function(){
return dojo.html._callDeprecated("getContentBoxWidth", "getContentBox", arguments, null, "width");
}
dojo.html.getContentBoxHeight = dojo.html.getContentHeight = function(){
return dojo.html._callDeprecated("getContentBoxHeight", "getContentBox", arguments, null, "height");
}
dojo.html.setContentBoxWidth = dojo.html.setContentWidth = function(node, width){
return dojo.html._callDeprecated("setContentBoxWidth", "setContentBox", arguments, "width");
}
dojo.html.setContentBoxHeight = dojo.html.setContentHeight = function(node, height){
return dojo.html._callDeprecated("setContentBoxHeight", "setContentBox", arguments, "height");
}
dojo.provide("dojo.html.util");
dojo.html.getElementWindow = function(/* HTMLElement */element){
// summary
// Get the window object where the element is placed in.
return dojo.html.getDocumentWindow( element.ownerDocument ); // Window
}
dojo.html.getDocumentWindow = function(doc){
// summary
// Get window object associated with document doc
// With Safari, there is not wa to retrieve the window from the document, so we must fix it.
if(dojo.render.html.safari && !doc._parentWindow){
/*
This is a Safari specific function that fix the reference to the parent
window from the document object.
*/
var fix=function(win){
win.document._parentWindow=win;
for(var i=0; i
// If you wanted to insert a node into a DOM tree based on the mouse
// position you might use the following code:
//
// if (gravity(node, e) & gravity.NORTH) { [insert before]; }
// else { [insert after]; }
//
//
// @param node The node
// @param e The event containing the mouse coordinates
// @return The directions, NORTH or SOUTH and EAST or WEST. These
// are properties of the function.
node = dojo.byId(node);
var mouse = dojo.html.getCursorPosition(e);
with (dojo.html) {
var absolute = getAbsolutePosition(node, true);
var bb = getBorderBox(node);
var nodecenterx = absolute.x + (bb.width / 2);
var nodecentery = absolute.y + (bb.height / 2);
}
with (dojo.html.gravity) {
return ((mouse.x < nodecenterx ? WEST : EAST) | (mouse.y < nodecentery ? NORTH : SOUTH)); // integer
}
}
dojo.html.gravity.NORTH = 1;
dojo.html.gravity.SOUTH = 1 << 1;
dojo.html.gravity.EAST = 1 << 2;
dojo.html.gravity.WEST = 1 << 3;
dojo.html.overElement = function(/* HTMLElement */element, /* DOMEvent */e){
// summary
// Returns whether the mouse is over the passed element.
// Element must be display:block (ie, not a )
element = dojo.byId(element);
var mouse = dojo.html.getCursorPosition(e);
var bb = dojo.html.getBorderBox(element);
var absolute = dojo.html.getAbsolutePosition(element, true, dojo.html.boxSizing.BORDER_BOX);
var top = absolute.y;
var bottom = top + bb.height;
var left = absolute.x;
var right = left + bb.width;
return (mouse.x >= left
&& mouse.x <= right
&& mouse.y >= top
&& mouse.y <= bottom
); // boolean
}
dojo.html.renderedTextContent = function(/* HTMLElement */node){
// summary
// Attempts to return the text as it would be rendered, with the line breaks
// sorted out nicely. Unfinished.
node = dojo.byId(node);
var result = "";
if (node == null) { return result; }
for (var i = 0; i < node.childNodes.length; i++) {
switch (node.childNodes[i].nodeType) {
case 1: // ELEMENT_NODE
case 5: // ENTITY_REFERENCE_NODE
var display = "unknown";
try {
display = dojo.html.getStyle(node.childNodes[i], "display");
} catch(E) {}
switch (display) {
case "block": case "list-item": case "run-in":
case "table": case "table-row-group": case "table-header-group":
case "table-footer-group": case "table-row": case "table-column-group":
case "table-column": case "table-cell": case "table-caption":
// TODO: this shouldn't insert double spaces on aligning blocks
result += "\n";
result += dojo.html.renderedTextContent(node.childNodes[i]);
result += "\n";
break;
case "none": break;
default:
if(node.childNodes[i].tagName && node.childNodes[i].tagName.toLowerCase() == "br") {
result += "\n";
} else {
result += dojo.html.renderedTextContent(node.childNodes[i]);
}
break;
}
break;
case 3: // TEXT_NODE
case 2: // ATTRIBUTE_NODE
case 4: // CDATA_SECTION_NODE
var text = node.childNodes[i].nodeValue;
var textTransform = "unknown";
try {
textTransform = dojo.html.getStyle(node, "text-transform");
} catch(E) {}
switch (textTransform){
case "capitalize":
var words = text.split(' ');
for(var i=0; i]/i).test(txt.replace(/^\s+/))) {
txt = "" + txt + "
";
tableType = "cell";
} else if((/^]/i).test(txt.replace(/^\s+/))) {
txt = "" + txt + "
";
tableType = "row";
} else if((/^<(thead|tbody|tfoot)[\s\r\n>]/i).test(txt.replace(/^\s+/))) {
txt = "" + txt + "
";
tableType = "section";
}
tn.innerHTML = txt;
if(tn["normalize"]){
tn.normalize();
}
var parent = null;
switch(tableType) {
case "cell":
parent = tn.getElementsByTagName("tr")[0];
break;
case "row":
parent = tn.getElementsByTagName("tbody")[0];
break;
case "section":
parent = tn.getElementsByTagName("table")[0];
break;
default:
parent = tn;
break;
}
/* this doesn't make much sense, I'm assuming it just meant trim() so wrap was replaced with trim
if(wrap){
var ret = [];
// start hack
var fc = tn.firstChild;
ret[0] = ((fc.nodeValue == " ")||(fc.nodeValue == "\t")) ? fc.nextSibling : fc;
// end hack
// tn.style.display = "none";
dojo.body().removeChild(tn);
return ret;
}
*/
var nodes = [];
for(var x=0; x view.width) {
x = view.width - w;
match = false;
} else {
x = tryX;
}
x = Math.max(padding[0], x) + scroll.x;
var y = tryY + h;
if(y > view.height) {
y = view.height - h;
match = false;
} else {
y = tryY;
}
y = Math.max(padding[1], y) + scroll.y;
if(match){ //perfect match, return now
bestx = x;
besty = y;
bestDistance = 0;
bestCorner = corner;
break;
}else{
//not perfect, find out whether it is better than the saved one
var dist = Math.pow(x-tryX-scroll.x,2)+Math.pow(y-tryY-scroll.y,2);
if(bestDistance > dist){
bestDistance = dist;
bestx = x;
besty = y;
bestCorner = corner;
}
}
}
if(!tryOnly){
node.style.left = bestx + "px";
node.style.top = besty + "px";
}
return { left: bestx, top: besty, x: bestx, y: besty, dist: bestDistance, corner: bestCorner}; // object
}
dojo.html.placeOnScreenPoint = function(node, desiredX, desiredY, padding, hasScroll) {
dojo.deprecated("dojo.html.placeOnScreenPoint", "use dojo.html.placeOnScreen() instead", "0.5");
return dojo.html.placeOnScreen(node, desiredX, desiredY, padding, hasScroll, ['TL', 'TR', 'BL', 'BR']);
}
dojo.html.placeOnScreenAroundElement = function(
/* HTMLElement */node,
/* HTMLElement */aroundNode,
/* integer */padding,
/* string? */aroundType,
/* string? */aroundCorners,
/* boolean? */tryOnly
){
// summary
// Like placeOnScreen, except it accepts aroundNode instead of x,y
// and attempts to place node around it. aroundType (see
// dojo.html.boxSizing in html/layout.js) determines which box of the
// aroundNode should be used to calculate the outer box.
// aroundCorners specify Which corner of aroundNode should be
// used to place the node => which corner(s) of node to use (see the
// corners parameter in dojo.html.placeOnScreen)
// aroundCorners: {'TL': 'BL', 'BL': 'TL'}
var best, bestDistance=Infinity;
aroundNode = dojo.byId(aroundNode);
var oldDisplay = aroundNode.style.display;
aroundNode.style.display="";
var mb = dojo.html.getElementBox(aroundNode, aroundType);
var aroundNodeW = mb.width;
var aroundNodeH = mb.height;
var aroundNodePos = dojo.html.getAbsolutePosition(aroundNode, true, aroundType);
aroundNode.style.display=oldDisplay;
for(var nodeCorner in aroundCorners){
var pos, desiredX, desiredY;
var corners = aroundCorners[nodeCorner];
desiredX = aroundNodePos.x + (nodeCorner.charAt(1)=='L' ? 0 : aroundNodeW);
desiredY = aroundNodePos.y + (nodeCorner.charAt(0)=='T' ? 0 : aroundNodeH);
pos = dojo.html.placeOnScreen(node, desiredX, desiredY, padding, true, corners, true);
if(pos.dist == 0){
best = pos;
break;
}else{
//not perfect, find out whether it is better than the saved one
if(bestDistance > pos.dist){
bestDistance = pos.dist;
best = pos;
}
}
}
if(!tryOnly){
node.style.left = best.left + "px";
node.style.top = best.top + "px";
}
return best; // object
}
dojo.html.scrollIntoView = function(/* HTMLElement */node){
// summary
// Scroll the passed node into view, if it is not.
if(!node){ return; }
// don't rely on that node.scrollIntoView works just because the function is there
// it doesnt work in Konqueror or Opera even though the function is there and probably
// not safari either
// dont like browser sniffs implementations but sometimes you have to use it
if(dojo.render.html.ie){
//only call scrollIntoView if there is a scrollbar for this menu,
//otherwise, scrollIntoView will scroll the window scrollbar
if(dojo.html.getBorderBox(node.parentNode).height <= node.parentNode.scrollHeight){
node.scrollIntoView(false);
}
}else if(dojo.render.html.mozilla){
// IE, mozilla
node.scrollIntoView(false);
}else{
var parent = node.parentNode;
var parentBottom = parent.scrollTop + dojo.html.getBorderBox(parent).height;
var nodeBottom = node.offsetTop + dojo.html.getMarginBox(node).height;
if(parentBottom < nodeBottom){
parent.scrollTop += (nodeBottom - parentBottom);
}else if(parent.scrollTop > node.offsetTop){
parent.scrollTop -= (parent.scrollTop - node.offsetTop);
}
}
}
dojo.provide("dojo.lang.array");
// FIXME: Is this worthless since you can do: if(name in obj)
// is this the right place for this?
dojo.lang.mixin(dojo.lang, {
has: function(/*Object*/obj, /*String*/name){
// summary: is there a property with the passed name in obj?
try{
return typeof obj[name] != "undefined"; // Boolean
}catch(e){ return false; } // Boolean
},
isEmpty: function(/*Object*/obj){
// summary:
// can be used to determine if the passed object is "empty". In
// the case of array-like objects, the length, property is
// examined, but for other types of objects iteration is used to
// examine the iterable "surface area" to determine if any
// non-prototypal properties have been assigned. This iteration is
// prototype-extension safe.
if(dojo.lang.isObject(obj)){
var tmp = {};
var count = 0;
for(var x in obj){
if(obj[x] && (!tmp[x])){
count++;
break;
}
}
return count == 0; // boolean
}else if(dojo.lang.isArrayLike(obj) || dojo.lang.isString(obj)){
return obj.length == 0; // boolean
}
},
map: function(/*Array*/arr, /*Object|Function*/obj, /*Function?*/unary_func){
// summary:
// returns a new array constituded from the return values of
// passing each element of arr into unary_func. The obj parameter
// may be passed to enable the passed function to be called in
// that scope. In environments that support JavaScript 1.6, this
// function is a passthrough to the built-in map() function
// provided by Array instances. For details on this, see:
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map
// examples:
// dojo.lang.map([1, 2, 3, 4], function(item){ return item+1 });
// // returns [2, 3, 4, 5]
var isString = dojo.lang.isString(arr);
if(isString){
// arr: String
arr = arr.split("");
}
if(dojo.lang.isFunction(obj)&&(!unary_func)){
unary_func = obj;
obj = dj_global;
}else if(dojo.lang.isFunction(obj) && unary_func){
// ff 1.5 compat
var tmpObj = obj;
obj = unary_func;
unary_func = tmpObj;
}
if(Array.map){
var outArr = Array.map(arr, unary_func, obj);
}else{
var outArr = [];
for(var i=0;i1; });
// // returns false
// dojo.lang.every([1, 2, 3, 4], function(item){ return item>0; });
// // returns true
return this._everyOrSome(true, arr, callback, thisObject); // Boolean
},
some: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
// summary:
// determines whether or not any item in the array satisfies the
// condition implemented by callback. thisObject may be used to
// scope the call to callback. The function signature is derived
// from the JavaScript 1.6 Array.some() function. More
// information on this can be found here:
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some
// examples:
// dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
// // returns true
// dojo.lang.some([1, 2, 3, 4], function(item){ return item<1; });
// // returns false
return this._everyOrSome(false, arr, callback, thisObject); // Boolean
},
filter: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
// summary:
// returns a new Array with those items from arr that match the
// condition implemented by callback.thisObject may be used to
// scope the call to callback. The function signature is derived
// from the JavaScript 1.6 Array.filter() function, although
// special accomidation is made in our implementation for strings.
// More information on the JS 1.6 API can be found here:
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter
// examples:
// dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
// // returns [2, 3, 4]
var isString = dojo.lang.isString(arr);
if(isString){ /*arr: String*/arr = arr.split(""); }
var outArr;
if(Array.filter){
outArr = Array.filter(arr, callback, thisObject);
}else{
if(!thisObject){
if(arguments.length >= 3){ dojo.raise("thisObject doesn't exist!"); }
thisObject = dj_global;
}
outArr = [];
for(var i = 0; i < arr.length; i++){
if(callback.call(thisObject, arr[i], i, arr)){
outArr.push(arr[i]);
}
}
}
if(isString){
return outArr.join(""); // String
} else {
return outArr; // Array
}
},
unnest: function(/* ... */){
// summary:
// Creates a 1-D array out of all the arguments passed,
// unravelling any array-like objects in the process
// usage:
// unnest(1, 2, 3) ==> [1, 2, 3]
// unnest(1, [2, [3], [[[4]]]]) ==> [1, 2, 3, 4]
var out = [];
for(var i = 0; i < arguments.length; i++){
if(dojo.lang.isArrayLike(arguments[i])){
var add = dojo.lang.unnest.apply(this, arguments[i]);
out = out.concat(add);
}else{
out.push(arguments[i]);
}
}
return out; // Array
},
toArray: function(/*Object*/arrayLike, /*Number*/startOffset){
// summary:
// Converts an array-like object (i.e. arguments, DOMCollection)
// to an array. Returns a new Array object.
var array = [];
for(var i = startOffset||0; i < arrayLike.length; i++){
array.push(arrayLike[i]);
}
return array; // Array
}
});
dojo.provide("dojo.gfx.color");
// TODO: rewrite the "x2y" methods to take advantage of the parsing
// abilities of the Color object. Also, beef up the Color
// object (as possible) to parse most common formats
// takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa)
dojo.gfx.color.Color = function(r, g, b, a) {
// dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]);
if(dojo.lang.isArray(r)){
this.r = r[0];
this.g = r[1];
this.b = r[2];
this.a = r[3]||1.0;
}else if(dojo.lang.isString(r)){
var rgb = dojo.gfx.color.extractRGB(r);
this.r = rgb[0];
this.g = rgb[1];
this.b = rgb[2];
this.a = g||1.0;
}else if(r instanceof dojo.gfx.color.Color){
// why does this create a new instance if we were passed one?
this.r = r.r;
this.b = r.b;
this.g = r.g;
this.a = r.a;
}else{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
}
dojo.gfx.color.Color.fromArray = function(arr) {
return new dojo.gfx.color.Color(arr[0], arr[1], arr[2], arr[3]);
}
dojo.extend(dojo.gfx.color.Color, {
toRgb: function(includeAlpha) {
if(includeAlpha) {
return this.toRgba();
} else {
return [this.r, this.g, this.b];
}
},
toRgba: function() {
return [this.r, this.g, this.b, this.a];
},
toHex: function() {
return dojo.gfx.color.rgb2hex(this.toRgb());
},
toCss: function() {
return "rgb(" + this.toRgb().join() + ")";
},
toString: function() {
return this.toHex(); // decent default?
},
blend: function(color, weight){
var rgb = null;
if(dojo.lang.isArray(color)){
rgb = color;
}else if(color instanceof dojo.gfx.color.Color){
rgb = color.toRgb();
}else{
rgb = new dojo.gfx.color.Color(color).toRgb();
}
return dojo.gfx.color.blend(this.toRgb(), rgb, weight);
}
});
dojo.gfx.color.named = {
white: [255,255,255],
black: [0,0,0],
red: [255,0,0],
green: [0,255,0],
lime: [0,255,0],
blue: [0,0,255],
navy: [0,0,128],
gray: [128,128,128],
silver: [192,192,192]
};
dojo.gfx.color.blend = function(a, b, weight){
// summary:
// blend colors a and b (both as RGB array or hex strings) with weight
// from -1 to +1, 0 being a 50/50 blend
if(typeof a == "string"){
return dojo.gfx.color.blendHex(a, b, weight);
}
if(!weight){
weight = 0;
}
weight = Math.min(Math.max(-1, weight), 1);
// alex: this interface blows.
// map -1 to 1 to the range 0 to 1
weight = ((weight + 1)/2);
var c = [];
// var stop = (1000*weight);
for(var x = 0; x < 3; x++){
c[x] = parseInt( b[x] + ( (a[x] - b[x]) * weight) );
}
return c;
}
// very convenient blend that takes and returns hex values
// (will get called automatically by blend when blend gets strings)
dojo.gfx.color.blendHex = function(a, b, weight) {
return dojo.gfx.color.rgb2hex(dojo.gfx.color.blend(dojo.gfx.color.hex2rgb(a), dojo.gfx.color.hex2rgb(b), weight));
}
// get RGB array from css-style color declarations
dojo.gfx.color.extractRGB = function(color) {
var hex = "0123456789abcdef";
color = color.toLowerCase();
if( color.indexOf("rgb") == 0 ) {
var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
var ret = matches.splice(1, 3);
return ret;
} else {
var colors = dojo.gfx.color.hex2rgb(color);
if(colors) {
return colors;
} else {
// named color (how many do we support?)
return dojo.gfx.color.named[color] || [255, 255, 255];
}
}
}
dojo.gfx.color.hex2rgb = function(hex) {
var hexNum = "0123456789ABCDEF";
var rgb = new Array(3);
if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); }
hex = hex.toUpperCase();
if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") {
return null;
}
if( hex.length == 3 ) {
rgb[0] = hex.charAt(0) + hex.charAt(0)
rgb[1] = hex.charAt(1) + hex.charAt(1)
rgb[2] = hex.charAt(2) + hex.charAt(2);
} else {
rgb[0] = hex.substring(0, 2);
rgb[1] = hex.substring(2, 4);
rgb[2] = hex.substring(4);
}
for(var i = 0; i < rgb.length; i++) {
rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1));
}
return rgb;
}
dojo.gfx.color.rgb2hex = function(r, g, b) {
if(dojo.lang.isArray(r)) {
g = r[1] || 0;
b = r[2] || 0;
r = r[0] || 0;
}
var ret = dojo.lang.map([r, g, b], function(x) {
x = new Number(x);
var s = x.toString(16);
while(s.length < 2) { s = "0" + s; }
return s;
});
ret.unshift("#");
return ret.join("");
}
dojo.provide("dojo.lang.func");
dojo.lang.hitch = function(/*Object*/thisObject, /*Function|String*/method){
// summary:
// Returns a function that will only ever execute in the a given scope
// (thisObject). This allows for easy use of object member functions
// in callbacks and other places in which the "this" keyword may
// otherwise not reference the expected scope. Note that the order of
// arguments may be reversed in a future version.
// thisObject: the scope to run the method in
// method:
// a function to be "bound" to thisObject or the name of the method in
// thisObject to be used as the basis for the binding
// usage:
// dojo.lang.hitch(foo, "bar")(); // runs foo.bar() in the scope of foo
// dojo.lang.hitch(foo, myFunction); // returns a function that runs myFunction in the scope of foo
// FIXME:
// should this be extended to "fixate" arguments in a manner similar
// to dojo.lang.curry, but without the default execution of curry()?
var fcn = (dojo.lang.isString(method) ? thisObject[method] : method) || function(){};
return function(){
return fcn.apply(thisObject, arguments); // Function
};
}
dojo.lang.anonCtr = 0;
dojo.lang.anon = {};
dojo.lang.nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj, /*Boolean*/searchForNames){
// summary:
// Creates a reference to anonFuncPtr in thisObj with a completely
// unique name. The new name is returned as a String. If
// searchForNames is true, an effort will be made to locate an
// existing reference to anonFuncPtr in thisObj, and if one is found,
// the existing name will be returned instead. The default is for
// searchForNames to be false.
var nso = (thisObj|| dojo.lang.anon);
if( (searchForNames) ||
((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
for(var x in nso){
try{
if(nso[x] === anonFuncPtr){
return x;
}
}catch(e){} // window.external fails in IE embedded in Eclipse (Eclipse bug #151165)
}
}
var ret = "__"+dojo.lang.anonCtr++;
while(typeof nso[ret] != "undefined"){
ret = "__"+dojo.lang.anonCtr++;
}
nso[ret] = anonFuncPtr;
return ret; // String
}
dojo.lang.forward = function(funcName){
// summary:
// Returns a function that forwards a method call to
// this.funcName(...). Unlike dojo.lang.hitch(), the "this" scope is
// not fixed on a single object. Ported from MochiKit.
return function(){
return this[funcName].apply(this, arguments);
}; // Function
}
dojo.lang.curry = function(thisObj, func /* args ... */){
// summary:
// similar to the curry() method found in many functional programming
// environments, this function returns an "argument accumulator"
// function, bound to a particular scope, and "primed" with a variable
// number of arguments. The curry method is unique in that it returns
// a function that may return other "partial" function which can be
// called repeatedly. New functions are returned until the arity of
// the original function is reached, at which point the underlying
// function (func) is called in the scope thisObj with all of the
// accumulated arguments (plus any extras) in positional order.
// examples:
// assuming a function defined like this:
// var foo = {
// bar: function(arg1, arg2, arg3){
// dojo.debug.apply(dojo, arguments);
// }
// };
//
// dojo.lang.curry() can be used most simply in this way:
//
// tmp = dojo.lang.curry(foo, foo.bar, "arg one", "thinger");
// tmp("blah", "this is superfluous");
// // debugs: "arg one thinger blah this is superfluous"
// tmp("blah");
// // debugs: "arg one thinger blah"
// tmp();
// // returns a function exactly like tmp that expects one argument
//
// other intermittent functions could be created until the 3
// positional arguments are filled:
//
// tmp = dojo.lang.curry(foo, foo.bar, "arg one");
// tmp2 = tmp("arg two");
// tmp2("blah blah");
// // debugs: "arg one arg two blah blah"
// tmp2("oy");
// // debugs: "arg one arg two oy"
//
// curry() can also be used to call the function if enough arguments
// are passed in the initial invocation:
//
// dojo.lang.curry(foo, foo.bar, "one", "two", "three", "four");
// // debugs: "one two three four"
// dojo.lang.curry(foo, foo.bar, "one", "two", "three");
// // debugs: "one two three"
// FIXME: the order of func and thisObj should be changed!!!
var outerArgs = [];
thisObj = thisObj||dj_global;
if(dojo.lang.isString(func)){
func = thisObj[func];
}
for(var x=2; x 0){ this.duration = duration; }
if(repeatCount){ this.repeatCount = repeatCount; }
if(rate){ this.rate = rate; }
if(handlers){
dojo.lang.forEach([
"handler", "beforeBegin", "onBegin",
"onEnd", "onPlay", "onStop", "onAnimate"
], function(item){
if(handlers[item]){
this.connect(item, handlers[item]);
}
}, this);
}
if(easing && dojo.lang.isFunction(easing)){
this.easing=easing;
}
}
dojo.inherits(dojo.lfx.Animation, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Animation, {
// "private" properties
_startTime: null,
_endTime: null,
_timer: null,
_percent: 0,
_startRepeatCount: 0,
// public methods
play: function(/*int?*/ delay, /*bool?*/ gotoStart){
// summary: Start the animation.
// delay: How many milliseconds to delay before starting.
// gotoStart: If true, starts the animation from the beginning; otherwise,
// starts it from its current position.
if(gotoStart){
clearTimeout(this._timer);
this._active = false;
this._paused = false;
this._percent = 0;
}else if(this._active && !this._paused){
return this; // dojo.lfx.Animation
}
this.fire("handler", ["beforeBegin"]);
this.fire("beforeBegin");
if(delay > 0){
setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
return this; // dojo.lfx.Animation
}
this._startTime = new Date().valueOf();
if(this._paused){
this._startTime -= (this.duration * this._percent / 100);
}
this._endTime = this._startTime + this.duration;
this._active = true;
this._paused = false;
var step = this._percent / 100;
var value = this.curve.getValue(step);
if(this._percent == 0 ){
if(!this._startRepeatCount){
this._startRepeatCount = this.repeatCount;
}
this.fire("handler", ["begin", value]);
this.fire("onBegin", [value]);
}
this.fire("handler", ["play", value]);
this.fire("onPlay", [value]);
this._cycle();
return this; // dojo.lfx.Animation
},
pause: function(){
// summary: Pauses a running animation.
clearTimeout(this._timer);
if(!this._active){ return this; /*dojo.lfx.Animation*/}
this._paused = true;
var value = this.curve.getValue(this._percent / 100);
this.fire("handler", ["pause", value]);
this.fire("onPause", [value]);
return this; // dojo.lfx.Animation
},
gotoPercent: function(/*Decimal*/ pct, /*bool?*/ andPlay){
// summary: Sets the progress of the animation.
// pct: A percentage in decimal notation (between and including 0.0 and 1.0).
// andPlay: If true, play the animation after setting the progress.
clearTimeout(this._timer);
this._active = true;
this._paused = true;
this._percent = pct;
if(andPlay){ this.play(); }
return this; // dojo.lfx.Animation
},
stop: function(/*bool?*/ gotoEnd){
// summary: Stops a running animation.
// gotoEnd: If true, the animation will end.
clearTimeout(this._timer);
var step = this._percent / 100;
if(gotoEnd){
step = 1;
}
var value = this.curve.getValue(step);
this.fire("handler", ["stop", value]);
this.fire("onStop", [value]);
this._active = false;
this._paused = false;
return this; // dojo.lfx.Animation
},
status: function(){
// summary: Returns a string representation of the status of
// the animation.
if(this._active){
return this._paused ? "paused" : "playing"; // String
}else{
return "stopped"; // String
}
return this;
},
// "private" methods
_cycle: function(){
clearTimeout(this._timer);
if(this._active){
var curr = new Date().valueOf();
var step = (curr - this._startTime) / (this._endTime - this._startTime);
if(step >= 1){
step = 1;
this._percent = 100;
}else{
this._percent = step * 100;
}
// Perform easing
if((this.easing)&&(dojo.lang.isFunction(this.easing))){
step = this.easing(step);
}
var value = this.curve.getValue(step);
this.fire("handler", ["animate", value]);
this.fire("onAnimate", [value]);
if( step < 1 ){
this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
}else{
this._active = false;
this.fire("handler", ["end"]);
this.fire("onEnd");
if(this.repeatCount > 0){
this.repeatCount--;
this.play(null, true);
}else if(this.repeatCount == -1){
this.play(null, true);
}else{
if(this._startRepeatCount){
this.repeatCount = this._startRepeatCount;
this._startRepeatCount = 0;
}
}
}
}
return this; // dojo.lfx.Animation
}
});
dojo.lfx.Combine = function(/*dojo.lfx.IAnimation...*/ animations){
// summary: An animation object to play animations passed to it at the same time.
dojo.lfx.IAnimation.call(this);
this._anims = [];
this._animsEnded = 0;
var anims = arguments;
if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
/* animations: dojo.lfx.IAnimation[]
pId: a */
anims = anims[0];
}
dojo.lang.forEach(anims, function(anim){
this._anims.push(anim);
anim.connect("onEnd", dojo.lang.hitch(this, "_onAnimsEnded"));
}, this);
}
dojo.inherits(dojo.lfx.Combine, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Combine, {
// private members
_animsEnded: 0,
// public methods
play: function(/*int?*/ delay, /*bool?*/ gotoStart){
// summary: Start the animations.
// delay: How many milliseconds to delay before starting.
// gotoStart: If true, starts the animations from the beginning; otherwise,
// starts them from their current position.
if( !this._anims.length ){ return this; /*dojo.lfx.Combine*/}
this.fire("beforeBegin");
if(delay > 0){
setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
return this; // dojo.lfx.Combine
}
if(gotoStart || this._anims[0].percent == 0){
this.fire("onBegin");
}
this.fire("onPlay");
this._animsCall("play", null, gotoStart);
return this; // dojo.lfx.Combine
},
pause: function(){
// summary: Pauses the running animations.
this.fire("onPause");
this._animsCall("pause");
return this; // dojo.lfx.Combine
},
stop: function(/*bool?*/ gotoEnd){
// summary: Stops the running animations.
// gotoEnd: If true, the animations will end.
this.fire("onStop");
this._animsCall("stop", gotoEnd);
return this; // dojo.lfx.Combine
},
// private methods
_onAnimsEnded: function(){
this._animsEnded++;
if(this._animsEnded >= this._anims.length){
this.fire("onEnd");
}
return this; // dojo.lfx.Combine
},
_animsCall: function(/*String*/ funcName){
var args = [];
if(arguments.length > 1){
for(var i = 1 ; i < arguments.length ; i++){
args.push(arguments[i]);
}
}
var _this = this;
dojo.lang.forEach(this._anims, function(anim){
anim[funcName](args);
}, _this);
return this; // dojo.lfx.Combine
}
});
dojo.lfx.Chain = function(/*dojo.lfx.IAnimation...*/ animations) {
// summary: An animation object to play animations passed to it
// one after another.
dojo.lfx.IAnimation.call(this);
this._anims = [];
this._currAnim = -1;
var anims = arguments;
if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
/* animations: dojo.lfx.IAnimation[]
pId: a */
anims = anims[0];
}
var _this = this;
dojo.lang.forEach(anims, function(anim, i, anims_arr){
this._anims.push(anim);
if(i < anims_arr.length - 1){
anim.connect("onEnd", dojo.lang.hitch(this, "_playNext") );
}else{
anim.connect("onEnd", dojo.lang.hitch(this, function(){ this.fire("onEnd"); }) );
}
}, this);
}
dojo.inherits(dojo.lfx.Chain, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Chain, {
// private members
_currAnim: -1,
// public methods
play: function(/*int?*/ delay, /*bool?*/ gotoStart){
// summary: Start the animation sequence.
// delay: How many milliseconds to delay before starting.
// gotoStart: If true, starts the sequence from the beginning; otherwise,
// starts it from its current position.
if( !this._anims.length ) { return this; /*dojo.lfx.Chain*/}
if( gotoStart || !this._anims[this._currAnim] ) {
this._currAnim = 0;
}
var currentAnimation = this._anims[this._currAnim];
this.fire("beforeBegin");
if(delay > 0){
setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
return this; // dojo.lfx.Chain
}
if(currentAnimation){
if(this._currAnim == 0){
this.fire("handler", ["begin", this._currAnim]);
this.fire("onBegin", [this._currAnim]);
}
this.fire("onPlay", [this._currAnim]);
currentAnimation.play(null, gotoStart);
}
return this; // dojo.lfx.Chain
},
pause: function(){
// summary: Pauses the running animation sequence.
if( this._anims[this._currAnim] ) {
this._anims[this._currAnim].pause();
this.fire("onPause", [this._currAnim]);
}
return this; // dojo.lfx.Chain
},
playPause: function(){
// summary: If the animation sequence is playing, pause it; otherwise,
// play it.
if(this._anims.length == 0){ return this; }
if(this._currAnim == -1){ this._currAnim = 0; }
var currAnim = this._anims[this._currAnim];
if( currAnim ) {
if( !currAnim._active || currAnim._paused ) {
this.play();
} else {
this.pause();
}
}
return this; // dojo.lfx.Chain
},
stop: function(){
// summary: Stops the running animations.
var currAnim = this._anims[this._currAnim];
if(currAnim){
currAnim.stop();
this.fire("onStop", [this._currAnim]);
}
return currAnim; // dojo.lfx.IAnimation
},
// private methods
_playNext: function(){
if( this._currAnim == -1 || this._anims.length == 0 ) { return this; }
this._currAnim++;
if( this._anims[this._currAnim] ){
this._anims[this._currAnim].play(null, true);
}
return this; // dojo.lfx.Chain
}
});
dojo.lfx.combine = function(/*dojo.lfx.IAnimation...*/ animations){
// summary: Convenience function. Returns a dojo.lfx.Combine created
// using the animations passed in.
var anims = arguments;
if(dojo.lang.isArray(arguments[0])){
/* animations: dojo.lfx.IAnimation[]
pId: a */
anims = arguments[0];
}
if(anims.length == 1){ return anims[0]; }
return new dojo.lfx.Combine(anims); // dojo.lfx.Combine
}
dojo.lfx.chain = function(/*dojo.lfx.IAnimation...*/ animations){
// summary: Convenience function. Returns a dojo.lfx.Chain created
// using the animations passed in.
var anims = arguments;
if(dojo.lang.isArray(arguments[0])){
/* animations: dojo.lfx.IAnimation[]
pId: a */
anims = arguments[0];
}
if(anims.length == 1){ return anims[0]; }
return new dojo.lfx.Chain(anims); // dojo.lfx.Combine
}
dojo.provide("dojo.html.color");
dojo.html.getBackgroundColor = function(/* HTMLElement */node){
// summary
// returns the background color of the passed node as a 32-bit color (RGBA)
node = dojo.byId(node);
var color;
do{
color = dojo.html.getStyle(node, "background-color");
// Safari doesn't say "transparent"
if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; }
if(node == document.getElementsByTagName("body")[0]) { node = null; break; }
node = node.parentNode;
}while(node && dojo.lang.inArray(["transparent", ""], color));
if(color == "transparent"){
color = [255, 255, 255, 0];
}else{
color = dojo.gfx.color.extractRGB(color);
}
return color; // array
}
dojo.provide("dojo.lfx.html");
dojo.lfx.html._byId = function(nodes){
if(!nodes){ return []; }
if(dojo.lang.isArrayLike(nodes)){
if(!nodes.alreadyChecked){
var n = [];
dojo.lang.forEach(nodes, function(node){
n.push(dojo.byId(node));
});
n.alreadyChecked = true;
return n;
}else{
return nodes;
}
}else{
var n = [];
n.push(dojo.byId(nodes));
n.alreadyChecked = true;
return n;
}
}
dojo.lfx.html.propertyAnimation = function( /*DOMNode[]*/ nodes,
/*Object[]*/ propertyMap,
/*int*/ duration,
/*function*/ easing,
/*Object*/ handlers){
// summary: Returns an animation that will transition the properties of "nodes"
// depending how they are defined in "propertyMap".
// nodes: An array of DOMNodes or one DOMNode.
// propertyMap: { property: String, start: Decimal?, end: Decimal?, units: String? }
// An array of objects defining properties to change.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// handlers: { handler: Function?, onstart: Function?, onstop: Function?, onanimate: Function? }
nodes = dojo.lfx.html._byId(nodes);
var targs = {
"propertyMap": propertyMap,
"nodes": nodes,
"duration": duration,
"easing": easing||dojo.lfx.easeDefault
};
var setEmUp = function(args){
if(args.nodes.length==1){
// FIXME: we're only supporting start-value filling when one node is
// passed
var pm = args.propertyMap;
if(!dojo.lang.isArray(args.propertyMap)){
// it's stupid to have to pack an array with a set of objects
// when you can just pass in an object list
var parr = [];
for(var pname in pm){
pm[pname].property = pname;
parr.push(pm[pname]);
}
pm = args.propertyMap = parr;
}
dojo.lang.forEach(pm, function(prop){
if(dj_undef("start", prop)){
if(prop.property != "opacity"){
prop.start = parseInt(dojo.html.getComputedStyle(args.nodes[0], prop.property));
}else{
prop.start = dojo.html.getOpacity(args.nodes[0]);
}
}
});
}
}
var coordsAsInts = function(coords){
var cints = [];
dojo.lang.forEach(coords, function(c){
cints.push(Math.round(c));
});
return cints;
}
var setStyle = function(n, style){
n = dojo.byId(n);
if(!n || !n.style){ return; }
for(var s in style){
try{
if(s == "opacity"){
dojo.html.setOpacity(n, style[s]);
}else{
n.style[s] = style[s];
}
}catch(e){ dojo.debug(e); }
}
}
var propLine = function(properties){
this._properties = properties;
this.diffs = new Array(properties.length);
dojo.lang.forEach(properties, function(prop, i){
// calculate the end - start to optimize a bit
if(dojo.lang.isFunction(prop.start)){
prop.start = prop.start(prop, i);
}
if(dojo.lang.isFunction(prop.end)){
prop.end = prop.end(prop, i);
}
if(dojo.lang.isArray(prop.start)){
// don't loop through the arrays
this.diffs[i] = null;
}else if(prop.start instanceof dojo.gfx.color.Color){
// save these so we don't have to call toRgb() every getValue() call
prop.startRgb = prop.start.toRgb();
prop.endRgb = prop.end.toRgb();
}else{
this.diffs[i] = prop.end - prop.start;
}
}, this);
this.getValue = function(n){
var ret = {};
dojo.lang.forEach(this._properties, function(prop, i){
var value = null;
if(dojo.lang.isArray(prop.start)){
// FIXME: what to do here?
}else if(prop.start instanceof dojo.gfx.color.Color){
value = (prop.units||"rgb") + "(";
for(var j = 0 ; j < prop.startRgb.length ; j++){
value += Math.round(((prop.endRgb[j] - prop.startRgb[j]) * n) + prop.startRgb[j]) + (j < prop.startRgb.length - 1 ? "," : "");
}
value += ")";
}else{
value = ((this.diffs[i]) * n) + prop.start + (prop.property != "opacity" ? prop.units||"px" : "");
}
ret[dojo.html.toCamelCase(prop.property)] = value;
}, this);
return ret;
}
}
var anim = new dojo.lfx.Animation({
beforeBegin: function(){
setEmUp(targs);
anim.curve = new propLine(targs.propertyMap);
},
onAnimate: function(propValues){
dojo.lang.forEach(targs.nodes, function(node){
setStyle(node, propValues);
});
}
},
targs.duration,
null,
targs.easing
);
if(handlers){
for(var x in handlers){
if(dojo.lang.isFunction(handlers[x])){
anim.connect(x, anim, handlers[x]);
}
}
}
return anim; // dojo.lfx.Animation
}
dojo.lfx.html._makeFadeable = function(nodes){
var makeFade = function(node){
if(dojo.render.html.ie){
// only set the zoom if the "tickle" value would be the same as the
// default
if( (node.style.zoom.length == 0) &&
(dojo.html.getStyle(node, "zoom") == "normal") ){
// make sure the node "hasLayout"
// NOTE: this has been tested with larger and smaller user-set text
// sizes and works fine
node.style.zoom = "1";
// node.style.zoom = "normal";
}
// don't set the width to auto if it didn't already cascade that way.
// We don't want to f anyones designs
if( (node.style.width.length == 0) &&
(dojo.html.getStyle(node, "width") == "auto") ){
node.style.width = "auto";
}
}
}
if(dojo.lang.isArrayLike(nodes)){
dojo.lang.forEach(nodes, makeFade);
}else{
makeFade(nodes);
}
}
dojo.lfx.html.fade = function(/*DOMNode[]*/ nodes,
/*Object*/values,
/*int?*/ duration,
/*Function?*/ easing,
/*Function?*/ callback){
// summary:Returns an animation that will fade the "nodes" from the start to end values passed.
// nodes: An array of DOMNodes or one DOMNode.
// values: { start: Decimal?, end: Decimal? }
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes = dojo.lfx.html._byId(nodes);
var props = { property: "opacity" };
if(!dj_undef("start", values)){
props.start = values.start;
}else{
props.start = function(){ return dojo.html.getOpacity(nodes[0]); };
}
if(!dj_undef("end", values)){
props.end = values.end;
}else{
dojo.raise("dojo.lfx.html.fade needs an end value");
}
var anim = dojo.lfx.propertyAnimation(nodes, [ props ], duration, easing);
anim.connect("beforeBegin", function(){
dojo.lfx.html._makeFadeable(nodes);
});
if(callback){
anim.connect("onEnd", function(){ callback(nodes, anim); });
}
return anim; // dojo.lfx.Animation
}
dojo.lfx.html.fadeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
// summary: Returns an animation that will fade "nodes" from its current opacity to fully opaque.
// nodes: An array of DOMNodes or one DOMNode.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
return dojo.lfx.html.fade(nodes, { end: 1 }, duration, easing, callback); // dojo.lfx.Animation
}
dojo.lfx.html.fadeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
// summary: Returns an animation that will fade "nodes" from its current opacity to fully transparent.
// nodes: An array of DOMNodes or one DOMNode.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
return dojo.lfx.html.fade(nodes, { end: 0 }, duration, easing, callback); // dojo.lfx.Animation
}
dojo.lfx.html.fadeShow = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
// summary: Returns an animation that will fade "nodes" from transparent to opaque and shows
// "nodes" at the end if it is hidden.
// nodes: An array of DOMNodes or one DOMNode.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes=dojo.lfx.html._byId(nodes);
dojo.lang.forEach(nodes, function(node){
dojo.html.setOpacity(node, 0.0);
});
var anim = dojo.lfx.html.fadeIn(nodes, duration, easing, callback);
anim.connect("beforeBegin", function(){
if(dojo.lang.isArrayLike(nodes)){
dojo.lang.forEach(nodes, dojo.html.show);
}else{
dojo.html.show(nodes);
}
});
return anim; // dojo.lfx.Animation
}
dojo.lfx.html.fadeHide = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
// summary: Returns an animation that will fade "nodes" from its current opacity to opaque and hides
// "nodes" at the end.
// nodes: An array of DOMNodes or one DOMNode.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
var anim = dojo.lfx.html.fadeOut(nodes, duration, easing, function(){
if(dojo.lang.isArrayLike(nodes)){
dojo.lang.forEach(nodes, dojo.html.hide);
}else{
dojo.html.hide(nodes);
}
if(callback){ callback(nodes, anim); }
});
return anim; // dojo.lfx.Animation
}
dojo.lfx.html.wipeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
// summary: Returns an animation that will show and wipe in "nodes".
// nodes: An array of DOMNodes or one DOMNode.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes = dojo.lfx.html._byId(nodes);
var anims = [];
dojo.lang.forEach(nodes, function(node){
var oprop = { }; // old properties of node (before we mucked w/them)
// get node height, either it's natural height or it's height specified via style or class attributes
// (for FF, the node has to be (temporarily) rendered to measure height)
// TODO: should this offscreen code be part of dojo.html, so that getBorderBox() works on hidden nodes?
var origTop, origLeft, origPosition;
with(node.style){
origTop=top; origLeft=left; origPosition=position;
top="-9999px"; left="-9999px"; position="absolute";
display="";
}
var height = dojo.html.getBorderBox(node).height;
with(node.style){
top=origTop; left=origLeft; position=origPosition;
display="none";
}
var anim = dojo.lfx.propertyAnimation(node,
{ "height": {
start: 1, // 0 causes IE to display the whole panel
end: function(){ return height; }
}
},
duration,
easing);
anim.connect("beforeBegin", function(){
oprop.overflow = node.style.overflow;
oprop.height = node.style.height;
with(node.style){
overflow = "hidden";
height = "1px"; // 0 causes IE to display the whole panel
}
dojo.html.show(node);
});
anim.connect("onEnd", function(){
with(node.style){
overflow = oprop.overflow;
height = oprop.height;
}
if(callback){ callback(node, anim); }
});
anims.push(anim);
});
return dojo.lfx.combine(anims); // dojo.lfx.Combine
}
dojo.lfx.html.wipeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
// summary: Returns an animation that will wipe out and hide "nodes".
// nodes: An array of DOMNodes or one DOMNode.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes = dojo.lfx.html._byId(nodes);
var anims = [];
dojo.lang.forEach(nodes, function(node){
var oprop = { }; // old properties of node (before we mucked w/them)
var anim = dojo.lfx.propertyAnimation(node,
{ "height": {
start: function(){ return dojo.html.getContentBox(node).height; },
end: 1 // 0 causes IE to display the whole panel
}
},
duration,
easing,
{
"beforeBegin": function(){
oprop.overflow = node.style.overflow;
oprop.height = node.style.height;
with(node.style){
overflow = "hidden";
}
dojo.html.show(node);
},
"onEnd": function(){
dojo.html.hide(node);
with(node.style){
overflow = oprop.overflow;
height = oprop.height;
}
if(callback){ callback(node, anim); }
}
}
);
anims.push(anim);
});
return dojo.lfx.combine(anims); // dojo.lfx.Combine
}
dojo.lfx.html.slideTo = function(/*DOMNode*/ nodes,
/*Object*/ coords,
/*int?*/ duration,
/*Function?*/ easing,
/*Function?*/ callback){
// summary: Returns an animation that will slide "nodes" from its current position to
// the position defined in "coords".
// nodes: An array of DOMNodes or one DOMNode.
// coords: { top: Decimal?, left: Decimal? }
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes = dojo.lfx.html._byId(nodes);
var anims = [];
var compute = dojo.html.getComputedStyle;
if(dojo.lang.isArray(coords)){
/* coords: Array
pId: a */
dojo.deprecated('dojo.lfx.html.slideTo(node, array)', 'use dojo.lfx.html.slideTo(node, {top: value, left: value});', '0.5');
coords = { top: coords[0], left: coords[1] };
}
dojo.lang.forEach(nodes, function(node){
var top = null;
var left = null;
var init = (function(){
var innerNode = node;
return function(){
var pos = compute(innerNode, 'position');
top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0);
left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0);
if (!dojo.lang.inArray(['absolute', 'relative'], pos)) {
var ret = dojo.html.abs(innerNode, true);
dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
top = ret.y;
left = ret.x;
}
}
})();
init();
var anim = dojo.lfx.propertyAnimation(node,
{ "top": { start: top, end: (coords.top||0) },
"left": { start: left, end: (coords.left||0) }
},
duration,
easing,
{ "beforeBegin": init }
);
if(callback){
anim.connect("onEnd", function(){ callback(nodes, anim); });
}
anims.push(anim);
});
return dojo.lfx.combine(anims); // dojo.lfx.Combine
}
dojo.lfx.html.slideBy = function(/*DOMNode*/ nodes, /*Object*/ coords, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
// summary: Returns an animation that will slide "nodes" from its current position
// to its current position plus the numbers defined in "coords".
// nodes: An array of DOMNodes or one DOMNode.
// coords: { top: Decimal?, left: Decimal? }
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes = dojo.lfx.html._byId(nodes);
var anims = [];
var compute = dojo.html.getComputedStyle;
if(dojo.lang.isArray(coords)){
/* coords: Array
pId: a */
dojo.deprecated('dojo.lfx.html.slideBy(node, array)', 'use dojo.lfx.html.slideBy(node, {top: value, left: value});', '0.5');
coords = { top: coords[0], left: coords[1] };
}
dojo.lang.forEach(nodes, function(node){
var top = null;
var left = null;
var init = (function(){
var innerNode = node;
return function(){
var pos = compute(innerNode, 'position');
top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0);
left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0);
if (!dojo.lang.inArray(['absolute', 'relative'], pos)) {
var ret = dojo.html.abs(innerNode, true);
dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
top = ret.y;
left = ret.x;
}
}
})();
init();
var anim = dojo.lfx.propertyAnimation(node,
{
"top": { start: top, end: top+(coords.top||0) },
"left": { start: left, end: left+(coords.left||0) }
},
duration,
easing).connect("beforeBegin", init);
if(callback){
anim.connect("onEnd", function(){ callback(nodes, anim); });
}
anims.push(anim);
});
return dojo.lfx.combine(anims); // dojo.lfx.Combine
}
dojo.lfx.html.explode = function(/*DOMNode*/ start,
/*DOMNode*/ endNode,
/*int?*/ duration,
/*Function?*/ easing,
/*Function?*/ callback){
// summary: Returns an animation that will
// start:
// endNode:
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
var h = dojo.html;
start = dojo.byId(start);
endNode = dojo.byId(endNode);
var startCoords = h.toCoordinateObject(start, true);
var outline = document.createElement("div");
h.copyStyle(outline, endNode);
if(endNode.explodeClassName){ outline.className = endNode.explodeClassName; }
with(outline.style){
position = "absolute";
display = "none";
// border = "1px solid black";
var backgroundStyle = h.getStyle(start, "background-color");
backgroundColor = backgroundStyle ? backgroundStyle.toLowerCase() : "transparent";
backgroundColor = (backgroundColor == "transparent") ? "rgb(221, 221, 221)" : backgroundColor;
}
dojo.body().appendChild(outline);
with(endNode.style){
visibility = "hidden";
display = "block";
}
var endCoords = h.toCoordinateObject(endNode, true);
with(endNode.style){
display = "none";
visibility = "visible";
}
var props = { opacity: { start: 0.5, end: 1.0 } };
dojo.lang.forEach(["height", "width", "top", "left"], function(type){
props[type] = { start: startCoords[type], end: endCoords[type] }
});
var anim = new dojo.lfx.propertyAnimation(outline,
props,
duration,
easing,
{
"beforeBegin": function(){
h.setDisplay(outline, "block");
},
"onEnd": function(){
h.setDisplay(endNode, "block");
outline.parentNode.removeChild(outline);
}
}
);
if(callback){
anim.connect("onEnd", function(){ callback(endNode, anim); });
}
return anim; // dojo.lfx.Animation
}
dojo.lfx.html.implode = function(/*DOMNode*/ startNode,
/*DOMNode*/ end,
/*int?*/ duration,
/*Function?*/ easing,
/*Function?*/ callback){
// summary: Returns an animation that will
// startNode:
// end:
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
var h = dojo.html;
startNode = dojo.byId(startNode);
end = dojo.byId(end);
var startCoords = dojo.html.toCoordinateObject(startNode, true);
var endCoords = dojo.html.toCoordinateObject(end, true);
var outline = document.createElement("div");
dojo.html.copyStyle(outline, startNode);
if (startNode.explodeClassName) { outline.className = startNode.explodeClassName; }
dojo.html.setOpacity(outline, 0.3);
with(outline.style){
position = "absolute";
display = "none";
backgroundColor = h.getStyle(startNode, "background-color").toLowerCase();
}
dojo.body().appendChild(outline);
var props = { opacity: { start: 1.0, end: 0.5 } };
dojo.lang.forEach(["height", "width", "top", "left"], function(type){
props[type] = { start: startCoords[type], end: endCoords[type] }
});
var anim = new dojo.lfx.propertyAnimation(outline,
props,
duration,
easing,
{
"beforeBegin": function(){
dojo.html.hide(startNode);
dojo.html.show(outline);
},
"onEnd": function(){
outline.parentNode.removeChild(outline);
}
}
);
if(callback){
anim.connect("onEnd", function(){ callback(startNode, anim); });
}
return anim; // dojo.lfx.Animation
}
dojo.lfx.html.highlight = function(/*DOMNode[]*/ nodes,
/*dojo.gfx.color.Color*/ startColor,
/*int?*/ duration,
/*Function?*/ easing,
/*Function?*/ callback){
// summary: Returns an animation that will set the background color
// of "nodes" to startColor and transition it to "nodes"
// original color.
// startColor: Color to transition from.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes = dojo.lfx.html._byId(nodes);
var anims = [];
dojo.lang.forEach(nodes, function(node){
var color = dojo.html.getBackgroundColor(node);
var bg = dojo.html.getStyle(node, "background-color").toLowerCase();
var bgImage = dojo.html.getStyle(node, "background-image");
var wasTransparent = (bg == "transparent" || bg == "rgba(0, 0, 0, 0)");
while(color.length > 3) { color.pop(); }
var rgb = new dojo.gfx.color.Color(startColor);
var endRgb = new dojo.gfx.color.Color(color);
var anim = dojo.lfx.propertyAnimation(node,
{ "background-color": { start: rgb, end: endRgb } },
duration,
easing,
{
"beforeBegin": function(){
if(bgImage){
node.style.backgroundImage = "none";
}
node.style.backgroundColor = "rgb(" + rgb.toRgb().join(",") + ")";
},
"onEnd": function(){
if(bgImage){
node.style.backgroundImage = bgImage;
}
if(wasTransparent){
node.style.backgroundColor = "transparent";
}
if(callback){
callback(node, anim);
}
}
}
);
anims.push(anim);
});
return dojo.lfx.combine(anims); // dojo.lfx.Combine
}
dojo.lfx.html.unhighlight = function(/*DOMNode[]*/ nodes,
/*dojo.gfx.color.Color*/ endColor,
/*int?*/ duration,
/*Function?*/ easing,
/*Function?*/ callback){
// summary: Returns an animation that will transition "nodes" background color
// from its current color to "endColor".
// endColor: Color to transition to.
// duration: Duration of the animation in milliseconds.
// easing: An easing function.
// callback: Function to run at the end of the animation.
nodes = dojo.lfx.html._byId(nodes);
var anims = [];
dojo.lang.forEach(nodes, function(node){
var color = new dojo.gfx.color.Color(dojo.html.getBackgroundColor(node));
var rgb = new dojo.gfx.color.Color(endColor);
var bgImage = dojo.html.getStyle(node, "background-image");
var anim = dojo.lfx.propertyAnimation(node,
{ "background-color": { start: color, end: rgb } },
duration,
easing,
{
"beforeBegin": function(){
if(bgImage){
node.style.backgroundImage = "none";
}
node.style.backgroundColor = "rgb(" + color.toRgb().join(",") + ")";
},
"onEnd": function(){
if(callback){
callback(node, anim);
}
}
}
);
anims.push(anim);
});
return dojo.lfx.combine(anims); // dojo.lfx.Combine
}
dojo.lang.mixin(dojo.lfx, dojo.lfx.html);
dojo.provide("dojo.lfx.*");
dojo.provide("dojo.lang.extras");
dojo.lang.setTimeout = function(/*Function*/func, /*int*/delay /*, ...*/){
// summary:
// Sets a timeout in milliseconds to execute a function in a given
// context with optional arguments.
// usage:
// dojo.lang.setTimeout(Object context, function func, number delay[, arg1[, ...]]);
// dojo.lang.setTimeout(function func, number delay[, arg1[, ...]]);
var context = window, argsStart = 2;
if(!dojo.lang.isFunction(func)){
context = func;
func = delay;
delay = arguments[2];
argsStart++;
}
if(dojo.lang.isString(func)){
func = context[func];
}
var args = [];
for (var i = argsStart; i < arguments.length; i++){
args.push(arguments[i]);
}
return dojo.global().setTimeout(function(){ func.apply(context, args); }, delay); // int
}
dojo.lang.clearTimeout = function(/*int*/timer){
// summary: clears timer by number from the execution queue
// FIXME:
// why do we have this function? It's not portable outside of browser
// environments and it's a stupid wrapper on something that browsers
// provide anyway.
dojo.global().clearTimeout(timer);
}
dojo.lang.getNameInObj = function(/*Object*/ns, /*unknown*/item){
// summary:
// looks for a value in the object ns with a value matching item and
// returns the property name
// ns: if null, dj_global is used
// item: value to return a name for
if(!ns){ ns = dj_global; }
for(var x in ns){
if(ns[x] === item){
return new String(x); // String
}
}
return null; // null
}
dojo.lang.shallowCopy = function(/*Object*/obj, /*Boolean?*/deep){
// summary:
// copies object obj one level deep, or full depth if deep is true
var i, ret;
if(obj === null){ /*obj: null*/ return null; } // null
if(dojo.lang.isObject(obj)){
// obj: Object
ret = new obj.constructor();
for(i in obj){
if(dojo.lang.isUndefined(ret[i])){
ret[i] = deep ? dojo.lang.shallowCopy(obj[i], deep) : obj[i];
}
}
}else if(dojo.lang.isArray(obj)){
// obj: Array
ret = [];
for(i=0; i2) ? args[0] : "after",
precedence: "last",
once: false,
delay: null,
rate: 0,
adviceMsg: false
};
switch(args.length){
case 0: return;
case 1: return;
case 2:
ao.srcFunc = args[0];
ao.adviceFunc = args[1];
break;
case 3:
if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
ao.adviceType = "after";
ao.srcObj = args[0];
ao.srcFunc = args[1];
ao.adviceFunc = args[2];
}else if((dl.isString(args[1]))&&(dl.isString(args[2]))){
ao.srcFunc = args[1];
ao.adviceFunc = args[2];
}else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
ao.adviceType = "after";
ao.srcObj = args[0];
ao.srcFunc = args[1];
var tmpName = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames);
ao.adviceFunc = tmpName;
}else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
ao.adviceType = "after";
ao.srcObj = dj_global;
var tmpName = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames);
ao.srcFunc = tmpName;
ao.adviceObj = args[1];
ao.adviceFunc = args[2];
}
break;
case 4:
if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
// we can assume that we've got an old-style "connect" from
// the sigslot school of event attachment. We therefore
// assume after-advice.
ao.adviceType = "after";
ao.srcObj = args[0];
ao.srcFunc = args[1];
ao.adviceObj = args[2];
ao.adviceFunc = args[3];
}else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
ao.adviceType = args[0];
ao.srcObj = dj_global;
ao.srcFunc = args[1];
ao.adviceObj = args[2];
ao.adviceFunc = args[3];
}else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
ao.adviceType = args[0];
ao.srcObj = dj_global;
var tmpName = dl.nameAnonFunc(args[1], dj_global, searchForNames);
ao.srcFunc = tmpName;
ao.adviceObj = args[2];
ao.adviceFunc = args[3];
}else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
ao.srcObj = args[1];
ao.srcFunc = args[2];
var tmpName = dl.nameAnonFunc(args[3], dj_global, searchForNames);
ao.adviceObj = dj_global;
ao.adviceFunc = tmpName;
}else if(dl.isObject(args[1])){
ao.srcObj = args[1];
ao.srcFunc = args[2];
ao.adviceObj = dj_global;
ao.adviceFunc = args[3];
}else if(dl.isObject(args[2])){
ao.srcObj = dj_global;
ao.srcFunc = args[1];
ao.adviceObj = args[2];
ao.adviceFunc = args[3];
}else{
ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
ao.srcFunc = args[1];
ao.adviceFunc = args[2];
ao.aroundFunc = args[3];
}
break;
case 6:
ao.srcObj = args[1];
ao.srcFunc = args[2];
ao.adviceObj = args[3]
ao.adviceFunc = args[4];
ao.aroundFunc = args[5];
ao.aroundObj = dj_global;
break;
default:
ao.srcObj = args[1];
ao.srcFunc = args[2];
ao.adviceObj = args[3]
ao.adviceFunc = args[4];
ao.aroundObj = args[5];
ao.aroundFunc = args[6];
ao.once = args[7];
ao.delay = args[8];
ao.rate = args[9];
ao.adviceMsg = args[10];
break;
}
if(dl.isFunction(ao.aroundFunc)){
var tmpName = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames);
ao.aroundFunc = tmpName;
}
if(dl.isFunction(ao.srcFunc)){
ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc);
}
if(dl.isFunction(ao.adviceFunc)){
ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc);
}
if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc);
}
if(!ao.srcObj){
dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
}
if(!ao.adviceObj){
dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
}
if(!ao.adviceFunc){
dojo.debug("bad adviceFunc for srcFunc: "+ao.srcFunc);
dojo.debugShallow(ao);
}
return ao;
}
this.connect = function(/*...*/){
// summary:
// dojo.event.connect is the glue that holds most Dojo-based
// applications together. Most combinations of arguments are
// supported, with the connect() method attempting to disambiguate
// the implied types of positional parameters. The following will
// all work:
// dojo.event.connect("globalFunctionName1", "globalFunctionName2");
// dojo.event.connect(functionReference1, functionReference2);
// dojo.event.connect("globalFunctionName1", functionReference2);
// dojo.event.connect(functionReference1, "globalFunctionName2");
// dojo.event.connect(scope1, "functionName1", "globalFunctionName2");
// dojo.event.connect("globalFunctionName1", scope2, "functionName2");
// dojo.event.connect(scope1, "functionName1", scope2, "functionName2");
// dojo.event.connect("after", scope1, "functionName1", scope2, "functionName2");
// dojo.event.connect("before", scope1, "functionName1", scope2, "functionName2");
// dojo.event.connect("around", scope1, "functionName1",
// scope2, "functionName2",
// aroundFunctionReference);
// dojo.event.connect("around", scope1, "functionName1",
// scope2, "functionName2",
// scope3, "aroundFunctionName");
// dojo.event.connect("before-around", scope1, "functionName1",
// scope2, "functionName2",
// aroundFunctionReference);
// dojo.event.connect("after-around", scope1, "functionName1",
// scope2, "functionName2",
// aroundFunctionReference);
// dojo.event.connect("after-around", scope1, "functionName1",
// scope2, "functionName2",
// scope3, "aroundFunctionName");
// dojo.event.connect("around", scope1, "functionName1",
// scope2, "functionName2",
// scope3, "aroundFunctionName", true, 30);
// dojo.event.connect("around", scope1, "functionName1",
// scope2, "functionName2",
// scope3, "aroundFunctionName", null, null, 10);
// adviceType:
// Optional. String. One of "before", "after", "around",
// "before-around", or "after-around". FIXME
// srcObj:
// the scope in which to locate/execute the named srcFunc. Along
// with srcFunc, this creates a way to dereference the function to
// call. So if the function in question is "foo.bar", the
// srcObj/srcFunc pair would be foo and "bar", where "bar" is a
// string and foo is an object reference.
// srcFunc:
// the name of the function to connect to. When it is executed,
// the listener being registered with this call will be called.
// The adviceType defines the call order between the source and
// the target functions.
// adviceObj:
// the scope in which to locate/execute the named adviceFunc.
// adviceFunc:
// the name of the function being conected to srcObj.srcFunc
// aroundObj:
// the scope in which to locate/execute the named aroundFunc.
// aroundFunc:
// the name of, or a reference to, the function that will be used
// to mediate the advice call. Around advice requires a special
// unary function that will be passed a "MethodInvocation" object.
// These objects have several important properties, namely:
// - args
// a mutable array of arguments to be passed into the
// wrapped function
// - proceed
// a function that "continues" the invocation. The result
// of this function is the return of the wrapped function.
// You can then manipulate this return before passing it
// back out (or take further action based on it).
// once:
// boolean that determines whether or not this connect() will
// create a new connection if an identical connect() has already
// been made. Defaults to "false".
// delay:
// an optional delay (in ms), as an integer, for dispatch of a
// listener after the source has been fired.
// rate:
// an optional rate throttling parameter (integer, in ms). When
// specified, this particular connection will not fire more than
// once in the interval specified by the rate
// adviceMsg:
// boolean. Should the listener have all the parameters passed in
// as a single argument?
/*
ao.adviceType = args[0];
ao.srcObj = args[1];
ao.srcFunc = args[2];
ao.adviceObj = args[3]
ao.adviceFunc = args[4];
ao.aroundObj = args[5];
ao.aroundFunc = args[6];
ao.once = args[7];
ao.delay = args[8];
ao.rate = args[9];
ao.adviceMsg = args[10];
*/
if(arguments.length == 1){
var ao = arguments[0];
}else{
var ao = interpolateArgs(arguments, true);
}
if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){
if(dojo.render.html.ie){
ao.srcFunc = "onkeydown";
this.connect(ao);
}
ao.srcFunc = "onkeypress";
}
if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){
var tmpAO = {};
for(var x in ao){
tmpAO[x] = ao[x];
}
var mjps = [];
dojo.lang.forEach(ao.srcObj, function(src){
if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
src = dojo.byId(src);
// dojo.debug(src);
}
tmpAO.srcObj = src;
// dojo.debug(tmpAO.srcObj, tmpAO.srcFunc);
// dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc);
mjps.push(dojo.event.connect.call(dojo.event, tmpAO));
});
return mjps;
}
// FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
if(ao.adviceFunc){
var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
}
mjp.kwAddAdvice(ao);
// advanced users might want to fsck w/ the join point manually
return mjp; // a MethodJoinPoint object
}
this.log = function(/*object or funcName*/ a1, /*funcName*/ a2){
// summary:
// a function that will wrap and log all calls to the specified
// a1.a2() function. If only a1 is passed, it'll be used as a
// function or function name on the global context. Logging will
// be sent to dojo.debug
// a1:
// if a2 is passed, this should be an object. If not, it can be a
// function or function name.
// a2:
// a function name
var kwArgs;
if((arguments.length == 1)&&(typeof a1 == "object")){
kwArgs = a1;
}else{
kwArgs = {
srcObj: a1,
srcFunc: a2
};
}
kwArgs.adviceFunc = function(){
var argsStr = [];
for(var x=0; x= this.jp_.around.length){
return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
// return this.jp_.run_before_after(this.object, this.args);
}else{
var ti = this.jp_.around[this.around_index];
var mobj = ti[0]||dj_global;
var meth = ti[1];
return mobj[meth].call(mobj, this);
}
}
dojo.event.MethodJoinPoint = function(/*Object*/obj, /*String*/funcName){
this.object = obj||dj_global;
this.methodname = funcName;
this.methodfunc = this.object[funcName];
this.squelch = false;
// this.before = [];
// this.after = [];
// this.around = [];
}
dojo.event.MethodJoinPoint.getForMethod = function(/*Object*/obj, /*String*/funcName){
// summary:
// "static" class function for returning a MethodJoinPoint from a
// scoped function. If one doesn't exist, one is created.
// obj:
// the scope to search for the function in
// funcName:
// the name of the function to return a MethodJoinPoint for
if(!obj){ obj = dj_global; }
if(!obj[funcName]){
// supply a do-nothing method implementation
obj[funcName] = function(){};
if(!obj[funcName]){
// e.g. cannot add to inbuilt objects in IE6
dojo.raise("Cannot set do-nothing method on that object "+funcName);
}
}else if((!dojo.lang.isFunction(obj[funcName]))&&(!dojo.lang.isAlien(obj[funcName]))){
// FIXME: should we throw an exception here instead?
return null;
}
// we hide our joinpoint instance in obj[funcName + '$joinpoint']
var jpname = funcName + "$joinpoint";
var jpfuncname = funcName + "$joinpoint$method";
var joinpoint = obj[jpname];
if(!joinpoint){
var isNode = false;
if(dojo.event["browser"]){
if( (obj["attachEvent"])||
(obj["nodeType"])||
(obj["addEventListener"]) ){
isNode = true;
dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, funcName]);
}
}
var origArity = obj[funcName].length;
obj[jpfuncname] = obj[funcName];
// joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, funcName);
joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
obj[funcName] = function(){
var args = [];
if((isNode)&&(!arguments.length)){
var evt = null;
try{
if(obj.ownerDocument){
evt = obj.ownerDocument.parentWindow.event;
}else if(obj.documentElement){
evt = obj.documentElement.ownerDocument.parentWindow.event;
}else if(obj.event){ //obj is a window
evt = obj.event;
}else{
evt = window.event;
}
}catch(e){
evt = window.event;
}
if(evt){
args.push(dojo.event.browser.fixEvent(evt, this));
}
}else{
for(var x=0; x0)){
// pass a cloned array, if this event disconnects this event forEach on this.before wont work
dojo.lang.forEach(this.before.concat(new Array()), unRollSquelch);
}
var result;
try{
if((this["around"])&&(this.around.length>0)){
var mi = new dojo.event.MethodInvocation(this, obj, args);
result = mi.proceed();
}else if(this.methodfunc){
result = this.object[this.methodname].apply(this.object, args);
}
}catch(e){
if(!this.squelch){
dojo.debug(e,"when calling",this.methodname,"on",this.object,"with arguments",args);
dojo.raise(e);
}
}
if((this["after"])&&(this.after.length>0)){
// see comment on this.before above
dojo.lang.forEach(this.after.concat(new Array()), unRollSquelch);
}
return (this.methodfunc) ? result : null;
},
getArr: function(/*String*/kind){
// summary: return a list of listeners of the past "kind"
// kind:
// can be one of: "before", "after", "around", "before-around", or
// "after-around"
var type = "after";
// FIXME: we should be able to do this through props or Array.in()
if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
type = "before";
}else if(kind=="around"){
type = "around";
}
if(!this[type]){ this[type] = []; }
return this[type]; // Array
},
kwAddAdvice: function(/*Object*/args){
// summary:
// adds advice to the joinpoint with arguments in a map
// args:
// An object that can have the following properties:
// - adviceType
// - adviceObj
// - adviceFunc
// - aroundObj
// - aroundFunc
// - once
// - delay
// - rate
// - adviceMsg
this.addAdvice( args["adviceObj"], args["adviceFunc"],
args["aroundObj"], args["aroundFunc"],
args["adviceType"], args["precedence"],
args["once"], args["delay"], args["rate"],
args["adviceMsg"]);
},
addAdvice: function( thisAdviceObj, thisAdvice,
thisAroundObj, thisAround,
adviceType, precedence,
once, delay, rate, asMessage){
// summary:
// add advice to this joinpoint using positional parameters
// thisAdviceObj:
// the scope in which to locate/execute the named adviceFunc.
// thisAdviceFunc:
// the name of the function being conected
// thisAroundObj:
// the scope in which to locate/execute the named aroundFunc.
// thisAroundFunc:
// the name of the function that will be used to mediate the
// advice call.
// adviceType:
// Optional. String. One of "before", "after", "around",
// "before-around", or "after-around". FIXME
// once:
// boolean that determines whether or not this advice will create
// a new connection if an identical advice set has already been
// provided. Defaults to "false".
// delay:
// an optional delay (in ms), as an integer, for dispatch of a
// listener after the source has been fired.
// rate:
// an optional rate throttling parameter (integer, in ms). When
// specified, this particular connection will not fire more than
// once in the interval specified by the rate
// adviceMsg:
// boolean. Should the listener have all the parameters passed in
// as a single argument?
var arr = this.getArr(adviceType);
if(!arr){
dojo.raise("bad this: " + this);
}
var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage];
if(once){
if(this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr) >= 0){
return;
}
}
if(precedence == "first"){
arr.unshift(ao);
}else{
arr.push(ao);
}
},
hasAdvice: function(thisAdviceObj, thisAdvice, adviceType, arr){
// summary:
// returns the array index of the first existing connection
// betweened the passed advice and this joinpoint. Will be -1 if
// none exists.
// thisAdviceObj:
// the scope in which to locate/execute the named adviceFunc.
// thisAdviceFunc:
// the name of the function being conected
// adviceType:
// Optional. String. One of "before", "after", "around",
// "before-around", or "after-around". FIXME
// arr:
// Optional. The list of advices to search. Will be found via
// adviceType if not passed
if(!arr){ arr = this.getArr(adviceType); }
var ind = -1;
for(var x=0; x=0; i=i-1){
var el = na[i];
try{
if(el && el["__clobberAttrs__"]){
for(var j=0; j= 65 && unifiedCharCode <= 90 && evt.shiftKey == false){
unifiedCharCode += 32;
}
if(unifiedCharCode >= 1 && unifiedCharCode <= 26 && evt.ctrlKey){
unifiedCharCode += 96; // 001-032 = ctrl+[a-z]
}
evt.key = String.fromCharCode(unifiedCharCode);
}
}
} else if(evt["type"] == "keypress"){
if(dojo.render.html.opera){
if(evt.which == 0){
evt.key = evt.keyCode;
}else if(evt.which > 0){
switch(evt.which){
case evt.KEY_SHIFT:
case evt.KEY_CTRL:
case evt.KEY_ALT:
case evt.KEY_CAPS_LOCK:
case evt.KEY_NUM_LOCK:
case evt.KEY_SCROLL_LOCK:
break;
case evt.KEY_PAUSE:
case evt.KEY_TAB:
case evt.KEY_BACKSPACE:
case evt.KEY_ENTER:
case evt.KEY_ESCAPE:
evt.key = evt.which;
break;
default:
var unifiedCharCode = evt.which;
if((evt.ctrlKey || evt.altKey || evt.metaKey) && (evt.which >= 65 && evt.which <= 90 && evt.shiftKey == false)){
unifiedCharCode += 32;
}
evt.key = String.fromCharCode(unifiedCharCode);
}
}
}else if(dojo.render.html.ie){ // catch some IE keys that are hard to get in keyDown
// key combinations were handled in onKeyDown
if(!evt.ctrlKey && !evt.altKey && evt.keyCode >= evt.KEY_SPACE){
evt.key = String.fromCharCode(evt.keyCode);
}
}else if(dojo.render.html.safari){
switch(evt.keyCode){
case 25: evt.key = evt.KEY_TAB; evt.shift = true;break;
case 63232: evt.key = evt.KEY_UP_ARROW; break;
case 63233: evt.key = evt.KEY_DOWN_ARROW; break;
case 63234: evt.key = evt.KEY_LEFT_ARROW; break;
case 63235: evt.key = evt.KEY_RIGHT_ARROW; break;
case 63236: evt.key = evt.KEY_F1; break;
case 63237: evt.key = evt.KEY_F2; break;
case 63238: evt.key = evt.KEY_F3; break;
case 63239: evt.key = evt.KEY_F4; break;
case 63240: evt.key = evt.KEY_F5; break;
case 63241: evt.key = evt.KEY_F6; break;
case 63242: evt.key = evt.KEY_F7; break;
case 63243: evt.key = evt.KEY_F8; break;
case 63244: evt.key = evt.KEY_F9; break;
case 63245: evt.key = evt.KEY_F10; break;
case 63246: evt.key = evt.KEY_F11; break;
case 63247: evt.key = evt.KEY_F12; break;
case 63250: evt.key = evt.KEY_PAUSE; break;
case 63272: evt.key = evt.KEY_DELETE; break;
case 63273: evt.key = evt.KEY_HOME; break;
case 63275: evt.key = evt.KEY_END; break;
case 63276: evt.key = evt.KEY_PAGE_UP; break;
case 63277: evt.key = evt.KEY_PAGE_DOWN; break;
case 63302: evt.key = evt.KEY_INSERT; break;
case 63248://prtscr
case 63249://scrolllock
case 63289://numlock
break;
default:
evt.key = evt.charCode >= evt.KEY_SPACE ? String.fromCharCode(evt.charCode) : evt.keyCode;
}
}else{
evt.key = evt.charCode > 0 ? String.fromCharCode(evt.charCode) : evt.keyCode;
}
}
}
if(dojo.render.html.ie){
if(!evt.target){ evt.target = evt.srcElement; }
if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); }
if(!evt.layerX){ evt.layerX = evt.offsetX; }
if(!evt.layerY){ evt.layerY = evt.offsetY; }
// FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module
// DONOT replace the following to use dojo.body(), in IE, document.documentElement should be used
// here rather than document.body
var doc = (evt.srcElement && evt.srcElement.ownerDocument) ? evt.srcElement.ownerDocument : document;
var docBody = ((dojo.render.html.ie55)||(doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
if(!evt.pageX){ evt.pageX = evt.clientX + (docBody.scrollLeft || 0) }
if(!evt.pageY){ evt.pageY = evt.clientY + (docBody.scrollTop || 0) }
// mouseover
if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; }
// mouseout
if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; }
this.currentEvent = evt;
evt.callListener = this.callListener;
evt.stopPropagation = this._stopPropagation;
evt.preventDefault = this._preventDefault;
}
return evt; // Event
}
this.stopEvent = function(/*Event*/evt){
// summary:
// prevents propigation and clobbers the default action of the
// passed event
// evt: Optional for IE. The native event object.
if(window.event){
evt.cancelBubble = true;
evt.returnValue = false;
}else{
evt.preventDefault();
evt.stopPropagation();
}
}
}
dojo.provide("dojo.event.*");
dojo.provide("dojo.lang.declare");
dojo.lang.declare = function( /*String*/ className,
/*Function|Array*/ superclass,
/*Function?*/ init,
/*Object|Array*/ props){
/*
* summary: Create a feature-rich constructor with a compact notation
* className: the name of the constructor (loosely, a "class")
* superclass:
* may be a Function, or an Array of Functions. If "superclass" is an
* array, the first element is used as the prototypical ancestor and
* any following Functions become mixin ancestors.
* init: an initializer function
* props:
* an object (or array of objects) whose properties are copied to the
* created prototype
* description:
* Create a constructor using a compact notation for inheritance and
* prototype extension. "superclass" argument may be a Function, or an
* array of Functions.
*
* If "superclass" is an array, the first element is used as the
* prototypical ancestor and any following Functions become mixin
* ancestors.
*
* All "superclass(es)" must be Functions (not mere Objects).
*
* Using mixin ancestors provides a type of multiple inheritance.
* Mixin ancestors prototypical properties are copied to the subclass,
* and any inializater/constructor is invoked.
*
* Properties of object "props" are copied to the constructor
* prototype. If "props" is an array, properties of each object in the
* array are copied to the constructor prototype.
*
* name of the class ("className" argument) is stored in
* "declaredClass" property
*
* Initializer functions are called when an object is instantiated
* from this constructor.
*
* Aliased as "dojo.declare"
*
* Usage:
*
* dojo.declare("my.classes.bar", my.classes.foo,
* function(){
* // initialization function
* this.myComplicatedObject = new ReallyComplicatedObject();
* },
* { // properties to be added to the class prototype
* someValue: 2,
* someMethod: function(){
* doStuff();
* }
* }
* );
*
*/
if((dojo.lang.isFunction(props))||((!props)&&(!dojo.lang.isFunction(init)))){
// parameter juggling to support omitting init param (also allows
// reordering init and props arguments)
var temp = props;
props = init;
init = temp;
}
var mixins = [ ];
if(dojo.lang.isArray(superclass)){
mixins = superclass;
superclass = mixins.shift();
}
if(!init){
init = dojo.evalObjPath(className, false);
if((init)&&(!dojo.lang.isFunction(init))){ init = null };
}
var ctor = dojo.lang.declare._makeConstructor();
var scp = (superclass ? superclass.prototype : null);
if(scp){
scp.prototyping = true;
ctor.prototype = new superclass();
scp.prototyping = false;
}
ctor.superclass = scp;
ctor.mixins = mixins;
for(var i=0,l=mixins.length; i 0 && dojo.lang.isString(message[0])){
this.message=message.shift();
}
this.msgArgs = message;
}else{
this.message = message;
}
// FIXME: what other information can we receive/discover here?
}
dojo.logging.LogFilter = function(loggerChain){
// summary:
// An empty parent (abstract) class which concrete filters should
// inherit from. Filters should have only a single method, filter(),
// which processes a record and returns true or false to denote
// whether or not it should be handled by the next step in a filter
// chain.
this.passChain = loggerChain || "";
this.filter = function(record){
// FIXME: need to figure out a way to enforce the loggerChain
// restriction
return true; // pass all records
}
}
dojo.logging.Logger = function(){
this.cutOffLevel = 0;
this.propagate = true;
this.parent = null;
// storage for dojo.logging.Record objects seen and accepted by this logger
this.data = [];
this.filters = [];
this.handlers = [];
}
dojo.extend(dojo.logging.Logger,{
_argsToArr: function(args){
var ret = [];
for(var x=0; x= this.cutOffLevel; // boolean
},
getEffectiveLevel: function(){
// summary:
// gets the effective cutoff level, including that of any
// potential parent loggers in the chain.
if((this.cutOffLevel==0)&&(this.parent)){
return this.parent.getEffectiveLevel(); // Integer
}
return this.cutOffLevel; // Integer
},
addFilter: function(/*dojo.logging.LogFilter*/flt){
// summary:
// registers a new LogFilter object. All records will be passed
// through this filter from now on.
this.filters.push(flt);
return this.filters.length-1; // Integer
},
removeFilterByIndex: function(/*Integer*/fltIndex){
// summary:
// removes the filter at the specified index from the filter
// chain. Returns whether or not removal was successful.
if(this.filters[fltIndex]){
delete this.filters[fltIndex];
return true; // boolean
}
return false; // boolean
},
removeFilter: function(/*dojo.logging.LogFilter*/fltRef){
// summary:
// removes the passed LogFilter. Returns whether or not removal
// was successful.
for(var x=0; x=this.cutOffLevel)){
this.parent.log(lvl, msg);
return false;
}
// FIXME: need to call logging providers here!
this.handle(new dojo.logging.Record(lvl, msg));
return true;
},
// logger helpers
debug:function(/*string*/msg){
// summary:
// log the msg and any other arguments at the "debug" logging
// level.
return this.logType("DEBUG", this._argsToArr(arguments));
},
info: function(msg){
// summary:
// log the msg and any other arguments at the "info" logging
// level.
return this.logType("INFO", this._argsToArr(arguments));
},
warning: function(msg){
// summary:
// log the msg and any other arguments at the "warning" logging
// level.
return this.logType("WARNING", this._argsToArr(arguments));
},
error: function(msg){
// summary:
// log the msg and any other arguments at the "error" logging
// level.
return this.logType("ERROR", this._argsToArr(arguments));
},
critical: function(msg){
// summary:
// log the msg and any other arguments at the "critical" logging
// level.
return this.logType("CRITICAL", this._argsToArr(arguments));
},
exception: function(/*string*/msg, /*Error*/e, /*boolean*/squelch){
// summary:
// logs the error and the message at the "exception" logging
// level. If squelch is true, also prevent bubbling of the
// exception.
// FIXME: this needs to be modified to put the exception in the msg
// if we're on Moz, we can get the following from the exception object:
// lineNumber
// message
// fileName
// stack
// name
// on IE, we get:
// name
// message (from MDA?)
// number
// description (same as message!)
if(e){
var eparts = [e.name, (e.description||e.message)];
if(e.fileName){
eparts.push(e.fileName);
eparts.push("line "+e.lineNumber);
// eparts.push(e.stack);
}
msg += " "+eparts.join(" : ");
}
this.logType("ERROR", msg);
if(!squelch){
throw e;
}
},
logType: function(/*string*/type, /*array*/args){
// summary:
// a more "user friendly" version of the log() function. Takes the
// named log level instead of the corresponding integer.
return this.log.apply(this, [dojo.logging.log.getLevel(type),
args]);
},
warn:function(){
// summary: shorthand for warning()
this.warning.apply(this,arguments);
},
err:function(){
// summary: shorthand for error()
this.error.apply(this,arguments);
},
crit:function(){
// summary: shorthand for critical()
this.critical.apply(this,arguments);
}
});
// the Handler class
dojo.logging.LogHandler = function(level){
this.cutOffLevel = (level) ? level : 0;
this.formatter = null; // FIXME: default formatter?
this.data = [];
this.filters = [];
}
dojo.lang.extend(dojo.logging.LogHandler,{
setFormatter:function(formatter){
dojo.unimplemented("setFormatter");
},
flush:function(){
// summary:
// Unimplemented. Should be implemented by subclasses to handle
// finishing a transaction or otherwise comitting pending log
// messages to whatevery underlying transport or storage system is
// available.
},
close:function(){
// summary:
// Unimplemented. Should be implemented by subclasses to handle
// shutting down the logger, including a call to flush()
},
handleError:function(){
// summary:
// Unimplemented. Should be implemented by subclasses.
dojo.deprecated("dojo.logging.LogHandler.handleError", "use handle()", "0.6");
},
handle:function(/*dojo.logging.Record*/record){
// summary:
// Emits the record object passed in should the record meet the
// current logging level cuttof, as specified in cutOffLevel.
if((this.filter(record))&&(record.level>=this.cutOffLevel)){
this.emit(record);
}
},
emit:function(/*dojo.logging.Record*/record){
// summary:
// Unimplemented. Should be implemented by subclasses to handle
// an individual record. Subclasses may batch records and send
// them to their "substrate" only when flush() is called, but this
// is generally not a good idea as losing logging messages may
// make debugging significantly more difficult. Tuning the volume
// of logging messages written to storage should be accomplished
// with log levels instead.
dojo.unimplemented("emit");
}
});
// set aliases since we don't want to inherit from dojo.logging.Logger
void(function(){ // begin globals protection closure
var names = [
"setLevel", "addFilter", "removeFilterByIndex", "removeFilter",
"removeAllFilters", "filter"
];
var tgt = dojo.logging.LogHandler.prototype;
var src = dojo.logging.Logger.prototype;
for(var x=0; xinteger conversion for log levels
for(var x=0; xthis.numRecords){
this.data.shift();
}
}
}
}
);
dojo.logging.logQueueHandler = new dojo.logging.MemoryLogHandler(0,50,0,10000);
dojo.logging.log.addHandler(dojo.logging.logQueueHandler);
dojo.log = dojo.logging.log;
dojo.provide("dojo.logging.*");
dojo.provide("dojo.string.common");
dojo.string.trim = function(/* string */str, /* integer? */wh){
// summary
// Trim whitespace from str. If wh > 0, trim from start, if wh < 0, trim from end, else both
if(!str.replace){ return str; }
if(!str.length){ return str; }
var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
return str.replace(re, ""); // string
}
dojo.string.trimStart = function(/* string */str) {
// summary
// Trim whitespace at the beginning of 'str'
return dojo.string.trim(str, 1); // string
}
dojo.string.trimEnd = function(/* string */str) {
// summary
// Trim whitespace at the end of 'str'
return dojo.string.trim(str, -1);
}
dojo.string.repeat = function(/* string */str, /* integer */count, /* string? */separator) {
// summary
// Return 'str' repeated 'count' times, optionally placing 'separator' between each rep
var out = "";
for(var i = 0; i < count; i++) {
out += str;
if(separator && i < count - 1) {
out += separator;
}
}
return out; // string
}
dojo.string.pad = function(/* string */str, /* integer */len/*=2*/, /* string */ c/*='0'*/, /* integer */dir/*=1*/) {
// summary
// Pad 'str' to guarantee that it is at least 'len' length with the character 'c' at either the
// start (dir=1) or end (dir=-1) of the string
var out = String(str);
if(!c) {
c = '0';
}
if(!dir) {
dir = 1;
}
while(out.length < len) {
if(dir > 0) {
out = c + out;
} else {
out += c;
}
}
return out; // string
}
dojo.string.padLeft = function(/* string */str, /* integer */len, /* string */c) {
// summary
// same as dojo.string.pad(str, len, c, 1)
return dojo.string.pad(str, len, c, 1); // string
}
dojo.string.padRight = function(/* string */str, /* integer */len, /* string */c) {
// summary
// same as dojo.string.pad(str, len, c, -1)
return dojo.string.pad(str, len, c, -1); // string
}
dojo.provide("dojo.string");
dojo.provide("dojo.io.common");
/******************************************************************************
* Notes about dojo.io design:
*
* The dojo.io.* package has the unenviable task of making a lot of different
* types of I/O feel natural, despite a universal lack of good (or even
* reasonable!) I/O capability in the host environment. So lets pin this down
* a little bit further.
*
* Rhino:
* perhaps the best situation anywhere. Access to Java classes allows you
* to do anything one might want in terms of I/O, both synchronously and
* async. Can open TCP sockets and perform low-latency client/server
* interactions. HTTP transport is available through Java HTTP client and
* server classes. Wish it were always this easy.
*
* xpcshell:
* XPCOM for I/O.
*
* spidermonkey:
* S.O.L.
*
* Browsers:
* Browsers generally do not provide any useable filesystem access. We are
* therefore limited to HTTP for moving information to and from Dojo
* instances living in a browser.
*
* XMLHTTP:
* Sync or async, allows reading of arbitrary text files (including
* JS, which can then be eval()'d), writing requires server
* cooperation and is limited to HTTP mechanisms (POST and GET).
*
*