PageRenderTime 113ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/DotNetKicks/Incremental.Kick.Web.UI/Static/Scripts/2.0.2/Dojo/dojo.js.uncompressed.js

http://dotnetkicks.googlecode.com/
JavaScript | 7258 lines | 5302 code | 832 blank | 1124 comment | 1440 complexity | 47d5c6787181810e67b946a3968de939 MD5 | raw file
Possible License(s): BSD-3-Clause, MPL-2.0-no-copyleft-exception
  1. /*
  2. Copyright (c) 2004-2005, The Dojo Foundation
  3. All Rights Reserved.
  4. Licensed under the Academic Free License version 2.1 or above OR the
  5. modified BSD license. For more information on Dojo licensing, see:
  6. http://dojotoolkit.org/community/licensing.shtml
  7. */
  8. /**
  9. * @file bootstrap1.js
  10. *
  11. * bootstrap file that runs before hostenv_*.js file.
  12. *
  13. * @author Copyright 2004 Mark D. Anderson (mda@discerning.com)
  14. * @author Licensed under the Academic Free License 2.1 http://www.opensource.org/licenses/afl-2.1.php
  15. *
  16. * $Id: bootstrap1.js 2555 2005-12-20 00:26:24Z alex $
  17. */
  18. /**
  19. * The global djConfig can be set prior to loading the library, to override
  20. * certain settings. It does not exist under dojo.* so that it can be set
  21. * before the dojo variable exists. Setting any of these variables *after* the
  22. * library has loaded does nothing at all. The variables that can be set are
  23. * as follows:
  24. */
  25. /**
  26. * dj_global is an alias for the top-level global object in the host
  27. * environment (the "window" object in a browser).
  28. */
  29. var dj_global = this; //typeof window == 'undefined' ? this : window;
  30. function dj_undef(name, obj){
  31. if(!obj){ obj = dj_global; }
  32. return (typeof obj[name] == "undefined");
  33. }
  34. if(dj_undef("djConfig")){
  35. var djConfig = {};
  36. }
  37. /**
  38. * dojo is the root variable of (almost all) our public symbols.
  39. */
  40. var dojo;
  41. if(dj_undef("dojo")){ dojo = {}; }
  42. dojo.version = {
  43. major: 0, minor: 2, patch: 1, flag: "",
  44. revision: Number("$Rev: 2555 $".match(/[0-9]+/)[0]),
  45. toString: function() {
  46. with (dojo.version) {
  47. return major + "." + minor + "." + patch + flag + " (" + revision + ")";
  48. }
  49. }
  50. };
  51. /*
  52. * evaluate a string like "A.B" without using eval.
  53. */
  54. dojo.evalObjPath = function(objpath, create){
  55. // fast path for no periods
  56. if(typeof objpath != "string"){ return dj_global; }
  57. if(objpath.indexOf('.') == -1){
  58. if((dj_undef(objpath, dj_global))&&(create)){
  59. dj_global[objpath] = {};
  60. }
  61. return dj_global[objpath];
  62. }
  63. var syms = objpath.split(/\./);
  64. var obj = dj_global;
  65. for(var i=0;i<syms.length;++i){
  66. if(!create){
  67. obj = obj[syms[i]];
  68. if((typeof obj == 'undefined')||(!obj)){
  69. return obj;
  70. }
  71. }else{
  72. if(dj_undef(syms[i], obj)){
  73. obj[syms[i]] = {};
  74. }
  75. obj = obj[syms[i]];
  76. }
  77. }
  78. return obj;
  79. };
  80. // ****************************************************************
  81. // global public utils
  82. // ****************************************************************
  83. /*
  84. * utility to print an Error.
  85. * TODO: overriding Error.prototype.toString won't accomplish this?
  86. * ... since natively generated Error objects do not always reflect such things?
  87. */
  88. dojo.errorToString = function(excep){
  89. return ((!dj_undef("message", excep)) ? excep.message : (dj_undef("description", excep) ? excep : excep.description ));
  90. };
  91. /**
  92. * Throws an Error object given the string err. For now, will also do a println
  93. * to the user first.
  94. */
  95. dojo.raise = function(message, excep){
  96. if(excep){
  97. message = message + ": "+dojo.errorToString(excep);
  98. }
  99. var he = dojo.hostenv;
  100. if((!dj_undef("hostenv", dojo))&&(!dj_undef("println", dojo.hostenv))){
  101. dojo.hostenv.println("FATAL: " + message);
  102. }
  103. throw Error(message);
  104. };
  105. dj_throw = dj_rethrow = function(m, e){
  106. dojo.deprecated("dj_throw and dj_rethrow deprecated, use dojo.raise instead");
  107. dojo.raise(m, e);
  108. };
  109. /**
  110. * Produce a line of debug output.
  111. * Does nothing unless djConfig.isDebug is true.
  112. * varargs, joined with ''.
  113. * Caller should not supply a trailing "\n".
  114. */
  115. dojo.debug = function(){
  116. if (!djConfig.isDebug) { return; }
  117. var args = arguments;
  118. if(dj_undef("println", dojo.hostenv)){
  119. dojo.raise("dojo.debug not available (yet?)");
  120. }
  121. var isJUM = dj_global["jum"] && !dj_global["jum"].isBrowser;
  122. var s = [(isJUM ? "": "DEBUG: ")];
  123. for(var i=0;i<args.length;++i){
  124. if(!false && args[i] instanceof Error){
  125. var msg = "[" + args[i].name + ": " + dojo.errorToString(args[i]) +
  126. (args[i].fileName ? ", file: " + args[i].fileName : "") +
  127. (args[i].lineNumber ? ", line: " + args[i].lineNumber : "") + "]";
  128. } else {
  129. try {
  130. var msg = String(args[i]);
  131. } catch(e) {
  132. if(dojo.render.html.ie) {
  133. var msg = "[ActiveXObject]";
  134. } else {
  135. var msg = "[unknown]";
  136. }
  137. }
  138. }
  139. s.push(msg);
  140. }
  141. if(isJUM){ // this seems to be the only way to get JUM to "play nice"
  142. jum.debug(s.join(" "));
  143. }else{
  144. dojo.hostenv.println(s.join(" "));
  145. }
  146. }
  147. /**
  148. * this is really hacky for now - just
  149. * display the properties of the object
  150. **/
  151. dojo.debugShallow = function(obj){
  152. if (!djConfig.isDebug) { return; }
  153. dojo.debug('------------------------------------------------------------');
  154. dojo.debug('Object: '+obj);
  155. for(i in obj){
  156. dojo.debug(i + ': ' + obj[i]);
  157. }
  158. dojo.debug('------------------------------------------------------------');
  159. }
  160. var dj_debug = dojo.debug;
  161. /**
  162. * We put eval() in this separate function to keep down the size of the trapped
  163. * evaluation context.
  164. *
  165. * Note that:
  166. * - JSC eval() takes an optional second argument which can be 'unsafe'.
  167. * - Mozilla/SpiderMonkey eval() takes an optional second argument which is the
  168. * scope object for new symbols.
  169. */
  170. function dj_eval(s){ return dj_global.eval ? dj_global.eval(s) : eval(s); }
  171. /**
  172. * Convenience for throwing an exception because some function is not
  173. * implemented.
  174. */
  175. dj_unimplemented = dojo.unimplemented = function(funcname, extra){
  176. // FIXME: need to move this away from dj_*
  177. var mess = "'" + funcname + "' not implemented";
  178. if((!dj_undef(extra))&&(extra)){ mess += " " + extra; }
  179. dojo.raise(mess);
  180. }
  181. /**
  182. * Convenience for informing of deprecated behaviour.
  183. */
  184. dj_deprecated = dojo.deprecated = function(behaviour, extra, removal){
  185. var mess = "DEPRECATED: " + behaviour;
  186. if(extra){ mess += " " + extra; }
  187. if(removal){ mess += " -- will be removed in version: " + removal; }
  188. dojo.debug(mess);
  189. }
  190. /**
  191. * Does inheritance
  192. */
  193. dojo.inherits = function(subclass, superclass){
  194. if(typeof superclass != 'function'){
  195. dojo.raise("superclass: "+superclass+" borken");
  196. }
  197. subclass.prototype = new superclass();
  198. subclass.prototype.constructor = subclass;
  199. subclass.superclass = superclass.prototype;
  200. // DEPRICATED: super is a reserved word, use 'superclass'
  201. subclass['super'] = superclass.prototype;
  202. }
  203. dj_inherits = function(subclass, superclass){
  204. dojo.deprecated("dj_inherits deprecated, use dojo.inherits instead");
  205. dojo.inherits(subclass, superclass);
  206. }
  207. // an object that authors use determine what host we are running under
  208. dojo.render = (function(){
  209. function vscaffold(prefs, names){
  210. var tmp = {
  211. capable: false,
  212. support: {
  213. builtin: false,
  214. plugin: false
  215. },
  216. prefixes: prefs
  217. };
  218. for(var x in names){
  219. tmp[x] = false;
  220. }
  221. return tmp;
  222. }
  223. return {
  224. name: "",
  225. ver: dojo.version,
  226. os: { win: false, linux: false, osx: false },
  227. html: vscaffold(["html"], ["ie", "opera", "khtml", "safari", "moz"]),
  228. svg: vscaffold(["svg"], ["corel", "adobe", "batik"]),
  229. vml: vscaffold(["vml"], ["ie"]),
  230. swf: vscaffold(["Swf", "Flash", "Mm"], ["mm"]),
  231. swt: vscaffold(["Swt"], ["ibm"])
  232. };
  233. })();
  234. // ****************************************************************
  235. // dojo.hostenv methods that must be defined in hostenv_*.js
  236. // ****************************************************************
  237. /**
  238. * The interface definining the interaction with the EcmaScript host environment.
  239. */
  240. /*
  241. * None of these methods should ever be called directly by library users.
  242. * Instead public methods such as loadModule should be called instead.
  243. */
  244. dojo.hostenv = (function(){
  245. // default configuration options
  246. var config = {
  247. isDebug: false,
  248. allowQueryConfig: false,
  249. baseScriptUri: "",
  250. baseRelativePath: "",
  251. libraryScriptUri: "",
  252. iePreventClobber: false,
  253. ieClobberMinimal: true,
  254. preventBackButtonFix: true,
  255. searchIds: [],
  256. parseWidgets: true
  257. };
  258. if (typeof djConfig == "undefined") { djConfig = config; }
  259. else {
  260. for (var option in config) {
  261. if (typeof djConfig[option] == "undefined") {
  262. djConfig[option] = config[option];
  263. }
  264. }
  265. }
  266. var djc = djConfig;
  267. function _def(obj, name, def){
  268. return (dj_undef(name, obj) ? def : obj[name]);
  269. }
  270. return {
  271. name_: '(unset)',
  272. version_: '(unset)',
  273. pkgFileName: "__package__",
  274. // for recursion protection
  275. loading_modules_: {},
  276. loaded_modules_: {},
  277. addedToLoadingCount: [],
  278. removedFromLoadingCount: [],
  279. inFlightCount: 0,
  280. modulePrefixes_: {
  281. dojo: {name: "dojo", value: "src"}
  282. },
  283. setModulePrefix: function(module, prefix){
  284. this.modulePrefixes_[module] = {name: module, value: prefix};
  285. },
  286. getModulePrefix: function(module){
  287. var mp = this.modulePrefixes_;
  288. if((mp[module])&&(mp[module]["name"])){
  289. return mp[module].value;
  290. }
  291. return module;
  292. },
  293. getTextStack: [],
  294. loadUriStack: [],
  295. loadedUris: [],
  296. // lookup cache for modules.
  297. // NOTE: this is partially redundant a private variable in the jsdown
  298. // implementation, but we don't want to couple the two.
  299. // modules_ : {},
  300. post_load_: false,
  301. modulesLoadedListeners: [],
  302. /**
  303. * Return the name of the hostenv.
  304. */
  305. getName: function(){ return this.name_; },
  306. /**
  307. * Return the version of the hostenv.
  308. */
  309. getVersion: function(){ return this.version_; },
  310. /**
  311. * Read the plain/text contents at the specified uri. If getText() is
  312. * not implemented, then it is necessary to override loadUri() with an
  313. * implementation that doesn't rely on it.
  314. */
  315. getText: function(uri){
  316. dojo.unimplemented('getText', "uri=" + uri);
  317. },
  318. /**
  319. * return the uri of the script that defined this function
  320. * private method that must be implemented by the hostenv.
  321. */
  322. getLibraryScriptUri: function(){
  323. // FIXME: need to implement!!!
  324. dojo.unimplemented('getLibraryScriptUri','');
  325. }
  326. };
  327. })();
  328. /**
  329. * Display a line of text to the user.
  330. * The line argument should not contain a trailing "\n"; that is added by the
  331. * implementation.
  332. */
  333. //dojo.hostenv.println = function(line) {}
  334. // ****************************************************************
  335. // dojo.hostenv methods not defined in hostenv_*.js
  336. // ****************************************************************
  337. /**
  338. * Return the base script uri that other scripts are found relative to.
  339. * It is either the empty string, or a non-empty string ending in '/'.
  340. */
  341. dojo.hostenv.getBaseScriptUri = function(){
  342. if(djConfig.baseScriptUri.length){
  343. return djConfig.baseScriptUri;
  344. }
  345. var uri = new String(djConfig.libraryScriptUri||djConfig.baseRelativePath);
  346. if (!uri) { dojo.raise("Nothing returned by getLibraryScriptUri(): " + uri); }
  347. var lastslash = uri.lastIndexOf('/');
  348. djConfig.baseScriptUri = djConfig.baseRelativePath;
  349. return djConfig.baseScriptUri;
  350. }
  351. /**
  352. * Set the base script uri.
  353. */
  354. // In JScript .NET, see interface System._AppDomain implemented by
  355. // System.AppDomain.CurrentDomain. Members include AppendPrivatePath,
  356. // RelativeSearchPath, BaseDirectory.
  357. dojo.hostenv.setBaseScriptUri = function(uri){ djConfig.baseScriptUri = uri }
  358. /**
  359. * Loads and interprets the script located at relpath, which is relative to the
  360. * script root directory. If the script is found but its interpretation causes
  361. * a runtime exception, that exception is not caught by us, so the caller will
  362. * see it. We return a true value if and only if the script is found.
  363. *
  364. * For now, we do not have an implementation of a true search path. We
  365. * consider only the single base script uri, as returned by getBaseScriptUri().
  366. *
  367. * @param relpath A relative path to a script (no leading '/', and typically
  368. * ending in '.js').
  369. * @param module A module whose existance to check for after loading a path.
  370. * Can be used to determine success or failure of the load.
  371. */
  372. dojo.hostenv.loadPath = function(relpath, module /*optional*/, cb /*optional*/){
  373. if((relpath.charAt(0) == '/')||(relpath.match(/^\w+:/))){
  374. dojo.raise("relpath '" + relpath + "'; must be relative");
  375. }
  376. var uri = this.getBaseScriptUri() + relpath;
  377. if(djConfig.cacheBust && dojo.render.html.capable) { uri += "?" + djConfig.cacheBust.replace(/\W+/g,""); }
  378. try{
  379. return ((!module) ? this.loadUri(uri, cb) : this.loadUriAndCheck(uri, module, cb));
  380. }catch(e){
  381. dojo.debug(e);
  382. return false;
  383. }
  384. }
  385. /**
  386. * Reads the contents of the URI, and evaluates the contents.
  387. * Returns true if it succeeded. Returns false if the URI reading failed.
  388. * Throws if the evaluation throws.
  389. * The result of the eval is not available to the caller.
  390. */
  391. dojo.hostenv.loadUri = function(uri, cb){
  392. if(dojo.hostenv.loadedUris[uri]){
  393. return;
  394. }
  395. var contents = this.getText(uri, null, true);
  396. if(contents == null){ return 0; }
  397. var value = dj_eval(contents);
  398. return 1;
  399. }
  400. // FIXME: probably need to add logging to this method
  401. dojo.hostenv.loadUriAndCheck = function(uri, module, cb){
  402. var ok = true;
  403. try{
  404. ok = this.loadUri(uri, cb);
  405. }catch(e){
  406. dojo.debug("failed loading ", uri, " with error: ", e);
  407. }
  408. return ((ok)&&(this.findModule(module, false))) ? true : false;
  409. }
  410. dojo.loaded = function(){ }
  411. dojo.hostenv.loaded = function(){
  412. this.post_load_ = true;
  413. var mll = this.modulesLoadedListeners;
  414. for(var x=0; x<mll.length; x++){
  415. mll[x]();
  416. }
  417. dojo.loaded();
  418. }
  419. /*
  420. Call styles:
  421. dojo.addOnLoad(functionPointer)
  422. dojo.addOnLoad(object, "functionName")
  423. */
  424. dojo.addOnLoad = function(obj, fcnName) {
  425. if(arguments.length == 1) {
  426. dojo.hostenv.modulesLoadedListeners.push(obj);
  427. } else if(arguments.length > 1) {
  428. dojo.hostenv.modulesLoadedListeners.push(function() {
  429. obj[fcnName]();
  430. });
  431. }
  432. };
  433. dojo.hostenv.modulesLoaded = function(){
  434. if(this.post_load_){ return; }
  435. if((this.loadUriStack.length==0)&&(this.getTextStack.length==0)){
  436. if(this.inFlightCount > 0){
  437. dojo.debug("files still in flight!");
  438. return;
  439. }
  440. if(typeof setTimeout == "object"){
  441. setTimeout("dojo.hostenv.loaded();", 0);
  442. }else{
  443. dojo.hostenv.loaded();
  444. }
  445. }
  446. }
  447. dojo.hostenv.moduleLoaded = function(modulename){
  448. var modref = dojo.evalObjPath((modulename.split(".").slice(0, -1)).join('.'));
  449. this.loaded_modules_[(new String(modulename)).toLowerCase()] = modref;
  450. }
  451. /**
  452. * loadModule("A.B") first checks to see if symbol A.B is defined.
  453. * If it is, it is simply returned (nothing to do).
  454. *
  455. * If it is not defined, it will look for "A/B.js" in the script root directory,
  456. * followed by "A.js".
  457. *
  458. * It throws if it cannot find a file to load, or if the symbol A.B is not
  459. * defined after loading.
  460. *
  461. * It returns the object A.B.
  462. *
  463. * This does nothing about importing symbols into the current package.
  464. * It is presumed that the caller will take care of that. For example, to import
  465. * all symbols:
  466. *
  467. * with (dojo.hostenv.loadModule("A.B")) {
  468. * ...
  469. * }
  470. *
  471. * And to import just the leaf symbol:
  472. *
  473. * var B = dojo.hostenv.loadModule("A.B");
  474. * ...
  475. *
  476. * dj_load is an alias for dojo.hostenv.loadModule
  477. */
  478. dojo.hostenv._global_omit_module_check = false;
  479. dojo.hostenv.loadModule = function(modulename, exact_only, omit_module_check){
  480. omit_module_check = this._global_omit_module_check || omit_module_check;
  481. var module = this.findModule(modulename, false);
  482. if(module){
  483. return module;
  484. }
  485. // protect against infinite recursion from mutual dependencies
  486. if(dj_undef(modulename, this.loading_modules_)){
  487. this.addedToLoadingCount.push(modulename);
  488. }
  489. this.loading_modules_[modulename] = 1;
  490. // convert periods to slashes
  491. var relpath = modulename.replace(/\./g, '/') + '.js';
  492. var syms = modulename.split(".");
  493. var nsyms = modulename.split(".");
  494. for (var i = syms.length - 1; i > 0; i--) {
  495. var parentModule = syms.slice(0, i).join(".");
  496. var parentModulePath = this.getModulePrefix(parentModule);
  497. if (parentModulePath != parentModule) {
  498. syms.splice(0, i, parentModulePath);
  499. break;
  500. }
  501. }
  502. var last = syms[syms.length - 1];
  503. // figure out if we're looking for a full package, if so, we want to do
  504. // things slightly diffrently
  505. if(last=="*"){
  506. modulename = (nsyms.slice(0, -1)).join('.');
  507. while(syms.length){
  508. syms.pop();
  509. syms.push(this.pkgFileName);
  510. relpath = syms.join("/") + '.js';
  511. if(relpath.charAt(0)=="/"){
  512. relpath = relpath.slice(1);
  513. }
  514. ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
  515. if(ok){ break; }
  516. syms.pop();
  517. }
  518. }else{
  519. relpath = syms.join("/") + '.js';
  520. modulename = nsyms.join('.');
  521. var ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
  522. if((!ok)&&(!exact_only)){
  523. syms.pop();
  524. while(syms.length){
  525. relpath = syms.join('/') + '.js';
  526. ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
  527. if(ok){ break; }
  528. syms.pop();
  529. relpath = syms.join('/') + '/'+this.pkgFileName+'.js';
  530. if(relpath.charAt(0)=="/"){
  531. relpath = relpath.slice(1);
  532. }
  533. ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
  534. if(ok){ break; }
  535. }
  536. }
  537. if((!ok)&&(!omit_module_check)){
  538. dojo.raise("Could not load '" + modulename + "'; last tried '" + relpath + "'");
  539. }
  540. }
  541. // check that the symbol was defined
  542. if(!omit_module_check){
  543. // pass in false so we can give better error
  544. module = this.findModule(modulename, false);
  545. if(!module){
  546. dojo.raise("symbol '" + modulename + "' is not defined after loading '" + relpath + "'");
  547. }
  548. }
  549. return module;
  550. }
  551. /**
  552. * startPackage("A.B") follows the path, and at each level creates a new empty
  553. * object or uses what already exists. It returns the result.
  554. */
  555. dojo.hostenv.startPackage = function(packname){
  556. var syms = packname.split(/\./);
  557. if(syms[syms.length-1]=="*"){
  558. syms.pop();
  559. }
  560. return dojo.evalObjPath(syms.join("."), true);
  561. }
  562. /**
  563. * findModule("A.B") returns the object A.B if it exists, otherwise null.
  564. * @param modulename A string like 'A.B'.
  565. * @param must_exist Optional, defualt false. throw instead of returning null
  566. * if the module does not currently exist.
  567. */
  568. dojo.hostenv.findModule = function(modulename, must_exist) {
  569. // check cache
  570. /*
  571. if(!dj_undef(modulename, this.modules_)){
  572. return this.modules_[modulename];
  573. }
  574. */
  575. if(this.loaded_modules_[(new String(modulename)).toLowerCase()]){
  576. return this.loaded_modules_[modulename];
  577. }
  578. // see if symbol is defined anyway
  579. var module = dojo.evalObjPath(modulename);
  580. if((typeof module !== 'undefined')&&(module)){
  581. return module;
  582. // return this.modules_[modulename] = module;
  583. }
  584. if(must_exist){
  585. dojo.raise("no loaded module named '" + modulename + "'");
  586. }
  587. return null;
  588. }
  589. /**
  590. * @file hostenv_browser.js
  591. *
  592. * Implements the hostenv interface for a browser environment.
  593. *
  594. * Perhaps it could be called a "dom" or "useragent" environment.
  595. *
  596. * @author Copyright 2004 Mark D. Anderson (mda@discerning.com)
  597. * @author Licensed under the Academic Free License 2.1 http://www.opensource.org/licenses/afl-2.1.php
  598. */
  599. // make jsc shut up (so we can use jsc to sanity check the code even if it will never run it).
  600. /*@cc_on
  601. @if (@_jscript_version >= 7)
  602. var window; var XMLHttpRequest;
  603. @end
  604. @*/
  605. if(typeof window == 'undefined'){
  606. dojo.raise("no window object");
  607. }
  608. // attempt to figure out the path to dojo if it isn't set in the config
  609. (function() {
  610. // before we get any further with the config options, try to pick them out
  611. // of the URL. Most of this code is from NW
  612. if(djConfig.allowQueryConfig){
  613. var baseUrl = document.location.toString(); // FIXME: use location.query instead?
  614. var params = baseUrl.split("?", 2);
  615. if(params.length > 1){
  616. var paramStr = params[1];
  617. var pairs = paramStr.split("&");
  618. for(var x in pairs){
  619. var sp = pairs[x].split("=");
  620. // FIXME: is this eval dangerous?
  621. if((sp[0].length > 9)&&(sp[0].substr(0, 9) == "djConfig.")){
  622. var opt = sp[0].substr(9);
  623. try{
  624. djConfig[opt]=eval(sp[1]);
  625. }catch(e){
  626. djConfig[opt]=sp[1];
  627. }
  628. }
  629. }
  630. }
  631. }
  632. if(((djConfig["baseScriptUri"] == "")||(djConfig["baseRelativePath"] == "")) &&(document && document.getElementsByTagName)){
  633. var scripts = document.getElementsByTagName("script");
  634. var rePkg = /(__package__|dojo)\.js(\?|$)/i;
  635. for(var i = 0; i < scripts.length; i++) {
  636. var src = scripts[i].getAttribute("src");
  637. if(!src) { continue; }
  638. var m = src.match(rePkg);
  639. if(m) {
  640. root = src.substring(0, m.index);
  641. if(!this["djConfig"]) { djConfig = {}; }
  642. if(djConfig["baseScriptUri"] == "") { djConfig["baseScriptUri"] = root; }
  643. if(djConfig["baseRelativePath"] == "") { djConfig["baseRelativePath"] = root; }
  644. break;
  645. }
  646. }
  647. }
  648. var dr = dojo.render;
  649. var drh = dojo.render.html;
  650. var dua = drh.UA = navigator.userAgent;
  651. var dav = drh.AV = navigator.appVersion;
  652. var t = true;
  653. var f = false;
  654. drh.capable = t;
  655. drh.support.builtin = t;
  656. dr.ver = parseFloat(drh.AV);
  657. dr.os.mac = dav.indexOf("Macintosh") >= 0;
  658. dr.os.win = dav.indexOf("Windows") >= 0;
  659. // could also be Solaris or something, but it's the same browser
  660. dr.os.linux = dav.indexOf("X11") >= 0;
  661. drh.opera = dua.indexOf("Opera") >= 0;
  662. drh.khtml = (dav.indexOf("Konqueror") >= 0)||(dav.indexOf("Safari") >= 0);
  663. drh.safari = dav.indexOf("Safari") >= 0;
  664. var geckoPos = dua.indexOf("Gecko");
  665. drh.mozilla = drh.moz = (geckoPos >= 0)&&(!drh.khtml);
  666. if (drh.mozilla) {
  667. // gecko version is YYYYMMDD
  668. drh.geckoVersion = dua.substring(geckoPos + 6, geckoPos + 14);
  669. }
  670. drh.ie = (document.all)&&(!drh.opera);
  671. drh.ie50 = drh.ie && dav.indexOf("MSIE 5.0")>=0;
  672. drh.ie55 = drh.ie && dav.indexOf("MSIE 5.5")>=0;
  673. drh.ie60 = drh.ie && dav.indexOf("MSIE 6.0")>=0;
  674. dr.vml.capable=drh.ie;
  675. dr.svg.capable = f;
  676. dr.svg.support.plugin = f;
  677. dr.svg.support.builtin = f;
  678. dr.svg.adobe = f;
  679. if (document.implementation
  680. && document.implementation.hasFeature
  681. && document.implementation.hasFeature("org.w3c.dom.svg", "1.0")
  682. ){
  683. dr.svg.capable = t;
  684. dr.svg.support.builtin = t;
  685. dr.svg.support.plugin = f;
  686. dr.svg.adobe = f;
  687. }else{
  688. // check for ASVG
  689. if(navigator.mimeTypes && navigator.mimeTypes.length > 0){
  690. var result = navigator.mimeTypes["image/svg+xml"] ||
  691. navigator.mimeTypes["image/svg"] ||
  692. navigator.mimeTypes["image/svg-xml"];
  693. if (result){
  694. dr.svg.adobe = result && result.enabledPlugin &&
  695. result.enabledPlugin.description &&
  696. (result.enabledPlugin.description.indexOf("Adobe") > -1);
  697. if(dr.svg.adobe) {
  698. dr.svg.capable = t;
  699. dr.svg.support.plugin = t;
  700. }
  701. }
  702. }else if(drh.ie && dr.os.win){
  703. var result = f;
  704. try {
  705. var test = new ActiveXObject("Adobe.SVGCtl");
  706. result = t;
  707. } catch(e){}
  708. if (result){
  709. dr.svg.capable = t;
  710. dr.svg.support.plugin = t;
  711. dr.svg.adobe = t;
  712. }
  713. }else{
  714. dr.svg.capable = f;
  715. dr.svg.support.plugin = f;
  716. dr.svg.adobe = f;
  717. }
  718. }
  719. })();
  720. dojo.hostenv.startPackage("dojo.hostenv");
  721. dojo.hostenv.name_ = 'browser';
  722. dojo.hostenv.searchIds = [];
  723. // These are in order of decreasing likelihood; this will change in time.
  724. var DJ_XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
  725. dojo.hostenv.getXmlhttpObject = function(){
  726. var http = null;
  727. var last_e = null;
  728. try{ http = new XMLHttpRequest(); }catch(e){}
  729. if(!http){
  730. for(var i=0; i<3; ++i){
  731. var progid = DJ_XMLHTTP_PROGIDS[i];
  732. try{
  733. http = new ActiveXObject(progid);
  734. }catch(e){
  735. last_e = e;
  736. }
  737. if(http){
  738. DJ_XMLHTTP_PROGIDS = [progid]; // so faster next time
  739. break;
  740. }
  741. }
  742. /*if(http && !http.toString) {
  743. http.toString = function() { "[object XMLHttpRequest]"; }
  744. }*/
  745. }
  746. if(!http){
  747. return dojo.raise("XMLHTTP not available", last_e);
  748. }
  749. return http;
  750. }
  751. /**
  752. * Read the contents of the specified uri and return those contents.
  753. *
  754. * @param uri A relative or absolute uri. If absolute, it still must be in the
  755. * same "domain" as we are.
  756. *
  757. * @param async_cb If not specified, load synchronously. If specified, load
  758. * asynchronously, and use async_cb as the progress handler which takes the
  759. * xmlhttp object as its argument. If async_cb, this function returns null.
  760. *
  761. * @param fail_ok Default false. If fail_ok and !async_cb and loading fails,
  762. * return null instead of throwing.
  763. */
  764. dojo.hostenv.getText = function(uri, async_cb, fail_ok){
  765. var http = this.getXmlhttpObject();
  766. if(async_cb){
  767. http.onreadystatechange = function(){
  768. if((4==http.readyState)&&(http["status"])){
  769. if(http.status==200){
  770. dojo.debug("LOADED URI: "+uri);
  771. async_cb(http.responseText);
  772. }
  773. }
  774. }
  775. }
  776. http.open('GET', uri, async_cb ? true : false);
  777. http.send(null);
  778. if(async_cb){
  779. return null;
  780. }
  781. return http.responseText;
  782. }
  783. /*
  784. * It turns out that if we check *right now*, as this script file is being loaded,
  785. * then the last script element in the window DOM is ourselves.
  786. * That is because any subsequent script elements haven't shown up in the document
  787. * object yet.
  788. */
  789. /*
  790. function dj_last_script_src() {
  791. var scripts = window.document.getElementsByTagName('script');
  792. if(scripts.length < 1){
  793. dojo.raise("No script elements in window.document, so can't figure out my script src");
  794. }
  795. var script = scripts[scripts.length - 1];
  796. var src = script.src;
  797. if(!src){
  798. dojo.raise("Last script element (out of " + scripts.length + ") has no src");
  799. }
  800. return src;
  801. }
  802. if(!dojo.hostenv["library_script_uri_"]){
  803. dojo.hostenv.library_script_uri_ = dj_last_script_src();
  804. }
  805. */
  806. dojo.hostenv.defaultDebugContainerId = 'dojoDebug';
  807. dojo.hostenv._println_buffer = [];
  808. dojo.hostenv._println_safe = false;
  809. dojo.hostenv.println = function (line){
  810. if(!dojo.hostenv._println_safe){
  811. dojo.hostenv._println_buffer.push(line);
  812. }else{
  813. try {
  814. var console = document.getElementById(djConfig.debugContainerId ?
  815. djConfig.debugContainerId : dojo.hostenv.defaultDebugContainerId);
  816. if(!console) { console = document.getElementsByTagName("body")[0] || document.body; }
  817. var div = document.createElement("div");
  818. div.appendChild(document.createTextNode(line));
  819. console.appendChild(div);
  820. } catch (e) {
  821. try{
  822. // safari needs the output wrapped in an element for some reason
  823. document.write("<div>" + line + "</div>");
  824. }catch(e2){
  825. window.status = line;
  826. }
  827. }
  828. }
  829. }
  830. dojo.addOnLoad(function(){
  831. dojo.hostenv._println_safe = true;
  832. while(dojo.hostenv._println_buffer.length > 0){
  833. dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
  834. }
  835. });
  836. function dj_addNodeEvtHdlr (node, evtName, fp, capture){
  837. var oldHandler = node["on"+evtName] || function(){};
  838. node["on"+evtName] = function(){
  839. fp.apply(node, arguments);
  840. oldHandler.apply(node, arguments);
  841. }
  842. return true;
  843. }
  844. dj_addNodeEvtHdlr(window, "load", function(){
  845. if(dojo.render.html.ie){
  846. dojo.hostenv.makeWidgets();
  847. }
  848. dojo.hostenv.modulesLoaded();
  849. });
  850. dojo.hostenv.makeWidgets = function(){
  851. // you can put searchIds in djConfig and dojo.hostenv at the moment
  852. // we should probably eventually move to one or the other
  853. var sids = [];
  854. if(djConfig.searchIds && djConfig.searchIds.length > 0) {
  855. sids = sids.concat(djConfig.searchIds);
  856. }
  857. if(dojo.hostenv.searchIds && dojo.hostenv.searchIds.length > 0) {
  858. sids = sids.concat(dojo.hostenv.searchIds);
  859. }
  860. if((djConfig.parseWidgets)||(sids.length > 0)){
  861. if(dojo.evalObjPath("dojo.widget.Parse")){
  862. // we must do this on a delay to avoid:
  863. // http://www.shaftek.org/blog/archives/000212.html
  864. // IE is such a tremendous peice of shit.
  865. try{
  866. var parser = new dojo.xml.Parse();
  867. if(sids.length > 0){
  868. for(var x=0; x<sids.length; x++){
  869. var tmpNode = document.getElementById(sids[x]);
  870. if(!tmpNode){ continue; }
  871. var frag = parser.parseElement(tmpNode, null, true);
  872. dojo.widget.getParser().createComponents(frag);
  873. }
  874. }else if(djConfig.parseWidgets){
  875. var frag = parser.parseElement(document.getElementsByTagName("body")[0] || document.body, null, true);
  876. dojo.widget.getParser().createComponents(frag);
  877. }
  878. }catch(e){
  879. dojo.debug("auto-build-widgets error:", e);
  880. }
  881. }
  882. }
  883. }
  884. dojo.hostenv.modulesLoadedListeners.push(function(){
  885. if(!dojo.render.html.ie) {
  886. dojo.hostenv.makeWidgets();
  887. }
  888. });
  889. // we assume that we haven't hit onload yet. Lord help us.
  890. try {
  891. if (!window["djConfig"] || !window.djConfig["preventBackButtonFix"]){
  892. document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='"+(dojo.hostenv.getBaseScriptUri()+'iframe_history.html')+"'></iframe>");
  893. }
  894. if (dojo.render.html.ie) {
  895. document.write('<style>v\:*{ behavior:url(#default#VML); }</style>');
  896. document.write('<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>');
  897. }
  898. } catch (e) { }
  899. // stub, over-ridden by debugging code. This will at least keep us from
  900. // breaking when it's not included
  901. dojo.hostenv.writeIncludes = function(){}
  902. dojo.hostenv.byId = dojo.byId = function(id, doc){
  903. if(typeof id == "string" || id instanceof String){
  904. if(!doc){ doc = document; }
  905. return doc.getElementById(id);
  906. }
  907. return id; // assume it's a node
  908. }
  909. dojo.hostenv.byIdArray = dojo.byIdArray = function(){
  910. var ids = [];
  911. for(var i = 0; i < arguments.length; i++){
  912. if((arguments[i] instanceof Array)||(typeof arguments[i] == "array")){
  913. for(var j = 0; j < arguments[i].length; j++){
  914. ids = ids.concat(dojo.hostenv.byIdArray(arguments[i][j]));
  915. }
  916. }else{
  917. ids.push(dojo.hostenv.byId(arguments[i]));
  918. }
  919. }
  920. return ids;
  921. }
  922. /*
  923. * bootstrap2.js - runs after the hostenv_*.js file.
  924. */
  925. /*
  926. * This method taks a "map" of arrays which one can use to optionally load dojo
  927. * modules. The map is indexed by the possible dojo.hostenv.name_ values, with
  928. * two additional values: "default" and "common". The items in the "default"
  929. * array will be loaded if none of the other items have been choosen based on
  930. * the hostenv.name_ item. The items in the "common" array will _always_ be
  931. * loaded, regardless of which list is chosen. Here's how it's normally
  932. * called:
  933. *
  934. * dojo.hostenv.conditionalLoadModule({
  935. * browser: [
  936. * ["foo.bar.baz", true, true], // an example that passes multiple args to loadModule()
  937. * "foo.sample.*",
  938. * "foo.test,
  939. * ],
  940. * default: [ "foo.sample.*" ],
  941. * common: [ "really.important.module.*" ]
  942. * });
  943. */
  944. dojo.hostenv.conditionalLoadModule = function(modMap){
  945. var common = modMap["common"]||[];
  946. var result = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);
  947. for(var x=0; x<result.length; x++){
  948. var curr = result[x];
  949. if(curr.constructor == Array){
  950. dojo.hostenv.loadModule.apply(dojo.hostenv, curr);
  951. }else{
  952. dojo.hostenv.loadModule(curr);
  953. }
  954. }
  955. }
  956. dojo.hostenv.require = dojo.hostenv.loadModule;
  957. dojo.require = function(){
  958. dojo.hostenv.loadModule.apply(dojo.hostenv, arguments);
  959. }
  960. dojo.requireAfter = dojo.require;
  961. dojo.requireIf = function(){
  962. if((arguments[0] === true)||(arguments[0]=="common")||(dojo.render[arguments[0]].capable)){
  963. var args = [];
  964. for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
  965. dojo.require.apply(dojo, args);
  966. }
  967. }
  968. dojo.requireAfterIf = dojo.requireIf;
  969. dojo.conditionalRequire = dojo.requireIf;
  970. dojo.kwCompoundRequire = function(){
  971. dojo.hostenv.conditionalLoadModule.apply(dojo.hostenv, arguments);
  972. }
  973. dojo.hostenv.provide = dojo.hostenv.startPackage;
  974. dojo.provide = function(){
  975. return dojo.hostenv.startPackage.apply(dojo.hostenv, arguments);
  976. }
  977. dojo.setModulePrefix = function(module, prefix){
  978. return dojo.hostenv.setModulePrefix(module, prefix);
  979. }
  980. // stub
  981. dojo.profile = { start: function(){}, end: function(){}, dump: function(){} };
  982. // determine if an object supports a given method
  983. // useful for longer api chains where you have to test each object in the chain
  984. dojo.exists = function(obj, name){
  985. var p = name.split(".");
  986. for(var i = 0; i < p.length; i++){
  987. if(!(obj[p[i]])) return false;
  988. obj = obj[p[i]];
  989. }
  990. return true;
  991. }
  992. dojo.provide("dojo.lang");
  993. dojo.provide("dojo.AdapterRegistry");
  994. dojo.provide("dojo.lang.Lang");
  995. dojo.lang.mixin = function(obj, props, tobj){
  996. if(typeof tobj != "object") {
  997. tobj = {};
  998. }
  999. for(var x in props){
  1000. if(typeof tobj[x] == "undefined" || tobj[x] != props[x]) {
  1001. obj[x] = props[x];
  1002. }
  1003. }
  1004. return obj;
  1005. }
  1006. dojo.lang.extend = function(ctor, props){
  1007. this.mixin(ctor.prototype, props);
  1008. }
  1009. dojo.lang.extendPrototype = function(obj, props){
  1010. this.extend(obj.constructor, props);
  1011. }
  1012. dojo.lang.anonCtr = 0;
  1013. dojo.lang.anon = {};
  1014. dojo.lang.nameAnonFunc = function(anonFuncPtr, namespaceObj){
  1015. var nso = (namespaceObj || dojo.lang.anon);
  1016. if((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)){
  1017. for(var x in nso){
  1018. if(nso[x] === anonFuncPtr){
  1019. return x;
  1020. }
  1021. }
  1022. }
  1023. var ret = "__"+dojo.lang.anonCtr++;
  1024. while(typeof nso[ret] != "undefined"){
  1025. ret = "__"+dojo.lang.anonCtr++;
  1026. }
  1027. nso[ret] = anonFuncPtr;
  1028. return ret;
  1029. }
  1030. /**
  1031. * Runs a function in a given scope (thisObject), can
  1032. * also be used to preserve scope.
  1033. *
  1034. * hitch(foo, "bar"); // runs foo.bar() in the scope of foo
  1035. * hitch(foo, myFunction); // runs myFunction in the scope of foo
  1036. */
  1037. dojo.lang.hitch = function(thisObject, method) {
  1038. if(dojo.lang.isString(method)) {
  1039. var fcn = thisObject[method];
  1040. } else {
  1041. var fcn = method;
  1042. }
  1043. return function() {
  1044. return fcn.apply(thisObject, arguments);
  1045. }
  1046. }
  1047. /**
  1048. * Sets a timeout in milliseconds to execute a function in a given context
  1049. * with optional arguments.
  1050. *
  1051. * setTimeout (Object context, function func, number delay[, arg1[, ...]]);
  1052. * setTimeout (function func, number delay[, arg1[, ...]]);
  1053. */
  1054. dojo.lang.setTimeout = function(func, delay){
  1055. var context = window, argsStart = 2;
  1056. if(!dojo.lang.isFunction(func)){
  1057. context = func;
  1058. func = delay;
  1059. delay = arguments[2];
  1060. argsStart++;
  1061. }
  1062. if(dojo.lang.isString(func)){
  1063. func = context[func];
  1064. }
  1065. var args = [];
  1066. for (var i = argsStart; i < arguments.length; i++) {
  1067. args.push(arguments[i]);
  1068. }
  1069. return setTimeout(function () { func.apply(context, args); }, delay);
  1070. }
  1071. /**
  1072. * Partial implmentation of is* functions from
  1073. * http://www.crockford.com/javascript/recommend.html
  1074. * NOTE: some of these may not be the best thing to use in all situations
  1075. * as they aren't part of core JS and therefore can't work in every case.
  1076. * See WARNING messages inline for tips.
  1077. *
  1078. * The following is* functions are fairly "safe"
  1079. */
  1080. dojo.lang.isObject = function(wh) {
  1081. return typeof wh == "object" || dojo.lang.isArray(wh) || dojo.lang.isFunction(wh);
  1082. }
  1083. dojo.lang.isArray = function(wh) {
  1084. return (wh instanceof Array || typeof wh == "array");
  1085. }
  1086. dojo.lang.isArrayLike = function(wh) {
  1087. if(dojo.lang.isString(wh)){ return false; }
  1088. if(dojo.lang.isArray(wh)){ return true; }
  1089. if(dojo.lang.isNumber(wh.length) && isFinite(wh)){ return true; }
  1090. return false;
  1091. }
  1092. dojo.lang.isFunction = function(wh) {
  1093. return (wh instanceof Function || typeof wh == "function");
  1094. }
  1095. dojo.lang.isString = function(wh) {
  1096. return (wh instanceof String || typeof wh == "string");
  1097. }
  1098. dojo.lang.isAlien = function(wh) {
  1099. return !dojo.lang.isFunction() && /\{\s*\[native code\]\s*\}/.test(String(wh));
  1100. }
  1101. dojo.lang.isBoolean = function(wh) {
  1102. return (wh instanceof Boolean || typeof wh == "boolean");
  1103. }
  1104. /**
  1105. * The following is***() functions are somewhat "unsafe". Fortunately,
  1106. * there are workarounds the the language provides and are mentioned
  1107. * in the WARNING messages.
  1108. *
  1109. * WARNING: In most cases, isNaN(wh) is sufficient to determine whether or not
  1110. * something is a number or can be used as such. For example, a number or string
  1111. * can be used interchangably when accessing array items (arr["1"] is the same as
  1112. * arr[1]) and isNaN will return false for both values ("1" and 1). Should you
  1113. * use isNumber("1"), that will return false, which is generally not too useful.
  1114. * Also, isNumber(NaN) returns true, again, this isn't generally useful, but there
  1115. * are corner cases (like when you want to make sure that two things are really
  1116. * the same type of thing). That is really where isNumber "shines".
  1117. *
  1118. * RECOMMENDATION: Use isNaN(wh) when possible
  1119. */
  1120. dojo.lang.isNumber = function(wh) {
  1121. return (wh instanceof Number || typeof wh == "number");
  1122. }
  1123. /**
  1124. * WARNING: In some cases, isUndefined will not behave as you
  1125. * might expect. If you do isUndefined(foo) and there is no earlier
  1126. * reference to foo, an error will be thrown before isUndefined is
  1127. * called. It behaves correctly if you scope yor object first, i.e.
  1128. * isUndefined(foo.bar) where foo is an object and bar isn't a
  1129. * property of the object.
  1130. *
  1131. * RECOMMENDATION: Use `typeof foo == "undefined"` when possible
  1132. *
  1133. * FIXME: Should isUndefined go away since it is error prone?
  1134. */
  1135. dojo.lang.isUndefined = function(wh) {
  1136. return ((wh == undefined)&&(typeof wh == "undefined"));
  1137. }
  1138. // end Crockford functions
  1139. dojo.lang.whatAmI = function(wh) {
  1140. try {
  1141. if(dojo.lang.isArray(wh)) { return "array"; }
  1142. if(dojo.lang.isFunction(wh)) { return "function"; }
  1143. if(dojo.lang.isString(wh)) { return "string"; }
  1144. if(dojo.lang.isNumber(wh)) { return "number"; }
  1145. if(dojo.lang.isBoolean(wh)) { return "boolean"; }
  1146. if(dojo.lang.isAlien(wh)) { return "alien"; }
  1147. if(dojo.lang.isUndefined(wh)) { return "undefined"; }
  1148. // FIXME: should this go first?
  1149. for(var name in dojo.lang.whatAmI.custom) {
  1150. if(dojo.lang.whatAmI.custom[name](wh)) {
  1151. return name;
  1152. }
  1153. }
  1154. if(dojo.lang.isObject(wh)) { return "object"; }
  1155. } catch(E) {}
  1156. return "unknown";
  1157. }
  1158. /*
  1159. * dojo.lang.whatAmI.custom[typeName] = someFunction
  1160. * will return typeName is someFunction(wh) returns true
  1161. */
  1162. dojo.lang.whatAmI.custom = {};
  1163. dojo.lang.find = function(arr, val, identity){
  1164. // support both (arr, val) and (val, arr)
  1165. if(!dojo.lang.isArray(arr) && dojo.lang.isArray(val)) {
  1166. var a = arr;
  1167. arr = val;
  1168. val = a;
  1169. }
  1170. var isString = dojo.lang.isString(arr);
  1171. if(isString) { arr = arr.split(""); }
  1172. if(identity){
  1173. for(var i=0;i<arr.length;++i){
  1174. if(arr[i] === val){ return i; }
  1175. }
  1176. }else{
  1177. for(var i=0;i<arr.length;++i){
  1178. if(arr[i] == val){ return i; }
  1179. }
  1180. }
  1181. return -1;
  1182. }
  1183. dojo.lang.indexOf = dojo.lang.find;
  1184. dojo.lang.findLast = function(arr, val, identity) {
  1185. // support both (arr, val) and (val, arr)
  1186. if(!dojo.lang.isArray(arr) && dojo.lang.isArray(val)) {
  1187. var a = arr;
  1188. arr = val;
  1189. val = a;
  1190. }
  1191. var isString = dojo.lang.isString(arr);
  1192. if(isString) { arr = arr.split(""); }
  1193. if(identity){
  1194. for(var i = arr.length-1; i >= 0; i--) {
  1195. if(arr[i] === val){ return i; }
  1196. }
  1197. }else{
  1198. for(var i = arr.length-1; i >= 0; i--) {
  1199. if(arr[i] == val){ return i; }
  1200. }
  1201. }
  1202. return -1;
  1203. }
  1204. dojo.lang.lastIndexOf = dojo.lang.findLast;
  1205. dojo.lang.inArray = function(arr, val){
  1206. return dojo.lang.find(arr, val) > -1;
  1207. }
  1208. dojo.lang.getNameInObj = function(ns, item){
  1209. if(!ns){ ns = dj_global; }
  1210. for(var x in ns){
  1211. if(ns[x] === item){
  1212. return new String(x);
  1213. }
  1214. }
  1215. return null;
  1216. }
  1217. // FIXME: Is this worthless since you can do: if(name in obj)
  1218. // is this the right place for this?
  1219. dojo.lang.has = function(obj, name){
  1220. return (typeof obj[name] !== 'undefined');
  1221. }
  1222. dojo.lang.isEmpty = function(obj) {
  1223. if(dojo.lang.isObject(obj)) {
  1224. var tmp = {};
  1225. var count = 0;
  1226. for(var x in obj){
  1227. if(obj[x] && (!tmp[x])){
  1228. count++;
  1229. break;
  1230. }
  1231. }
  1232. return (count == 0);
  1233. } else if(dojo.lang.isArray(obj) || dojo.lang.isString(obj)) {
  1234. return obj.length == 0;
  1235. }
  1236. }
  1237. dojo.lang.forEach = function(arr, unary_func, fix_length){
  1238. var isString = dojo.lang.isString(arr);
  1239. if(isString) { arr = arr.split(""); }
  1240. var il = arr.length;
  1241. for(var i=0; i< ((fix_length) ? il : arr.length); i++){
  1242. if(unary_func(arr[i], i, arr) == "break"){
  1243. break;
  1244. }
  1245. }
  1246. }
  1247. dojo.lang.map = function(arr, obj, unary_func){
  1248. var isString = dojo.lang.isString(arr);
  1249. if(isString){
  1250. arr = arr.split("");
  1251. }
  1252. if(dojo.lang.isFunction(obj)&&(!unary_func)){
  1253. unary_func = obj;
  1254. obj = dj_global;
  1255. }else if(dojo.lang.isFunction(obj) && unary_func){
  1256. // ff 1.5 compat
  1257. var tmpObj = obj;
  1258. obj = unary_func;
  1259. unary_func = tmpObj;
  1260. }
  1261. if(Array.map){
  1262. var outArr = Array.map(arr, unary_func, obj);
  1263. }else{
  1264. var outArr = [];
  1265. for(var i=0;i<arr.length;++i){
  1266. outArr.push(unary_func.call(obj, arr[i]));
  1267. }
  1268. }
  1269. if(isString) {
  1270. return outArr.join("");
  1271. } else {
  1272. return outArr;
  1273. }
  1274. }
  1275. dojo.lang.tryThese = function(){
  1276. for(var x=0; x<arguments.length; x++){
  1277. try{
  1278. if(typeof arguments[x] == "function"){
  1279. var ret = (arguments[x]());
  1280. if(ret){
  1281. return ret;
  1282. }
  1283. }
  1284. }catch(e){
  1285. dojo.debug(e);
  1286. }
  1287. }
  1288. }
  1289. dojo.lang.delayThese = function(farr, cb, delay, onend){
  1290. /**
  1291. * alternate: (array funcArray, function callback, function onend)
  1292. * alternate: (array funcArray, function callback)
  1293. * alternate: (array funcArray)
  1294. */
  1295. if(!farr.length){
  1296. if(typeof onend == "function"){
  1297. onend();
  1298. }
  1299. return;
  1300. }
  1301. if((typeof delay == "undefined")&&(typeof cb == "number")){
  1302. delay = cb;
  1303. cb = function(){};
  1304. }else if(!cb){
  1305. cb = function(){};
  1306. if(!delay){ delay = 0; }
  1307. }
  1308. setTimeout(function(){
  1309. (farr.shift())();
  1310. cb();
  1311. dojo.lang.delayThese(farr, cb, delay, onend);
  1312. }, delay);
  1313. }
  1314. dojo.lang.shallowCopy = function(obj) {
  1315. var ret = {}, key;
  1316. for(key in obj) {
  1317. if(dojo.lang.isUndefined(ret[key])) {
  1318. ret[key] = obj[key];
  1319. }
  1320. }
  1321. return ret;
  1322. }
  1323. dojo.lang.every = function(arr, callback, thisObject) {
  1324. var isString = dojo.lang.isString(arr);
  1325. if(isString) { arr = arr.split(""); }
  1326. if(Array.every) {
  1327. return Array.every(arr, callback, thisObject);
  1328. } else {
  1329. if(!thisObject) {
  1330. if(arguments.length >= 3) { dojo.raise("thisObject doesn't exist!"); }
  1331. thisObject = dj_global;
  1332. }
  1333. for(var i = 0; i < arr.length; i++) {
  1334. if(!callback.call(thisObject, arr[i], i, arr)) {
  1335. return false;
  1336. }
  1337. }
  1338. return true;
  1339. }
  1340. }
  1341. dojo.lang.some = function(arr, callback, thisObject) {
  1342. var isString = dojo.lang.isString(arr);
  1343. if(isString) { arr = arr.split(""); }
  1344. if(Array.some) {
  1345. return Array.some(arr, callback, thisObject);
  1346. } else {
  1347. if(!thisObject) {
  1348. if(arguments.length >= 3) { dojo.raise("thisObject doesn't exist!"); }
  1349. thisObject = dj_global;
  1350. }
  1351. for(var i = 0; i < arr.length; i++) {
  1352. if(callback.call(thisObject, arr[i], i, arr)) {
  1353. return true;
  1354. }
  1355. }
  1356. return false;
  1357. }
  1358. }
  1359. dojo.lang.filter = function(arr, callback, thisObject) {
  1360. var isString = dojo.lang.isString(arr);
  1361. if(isString) { arr = arr.split(""); }
  1362. if(Array.filter) {
  1363. var outArr = Array.filter(arr, callback, thisObject);
  1364. } else {
  1365. if(!thisObject) {
  1366. if(arguments.length >= 3) { dojo.raise("thisObject doesn't exist!"); }
  1367. thisObject = dj_global;
  1368. }
  1369. var outArr = [];
  1370. for(var i = 0; i < arr.length; i++) {
  1371. if(callback.call(thisObject, arr[i], i, arr)) {
  1372. outArr.push(arr[i]);
  1373. }
  1374. }
  1375. }
  1376. if(isString) {
  1377. return outArr.join("");
  1378. } else {
  1379. return outArr;
  1380. }
  1381. }
  1382. dojo.AdapterRegistry = function(){
  1383. /***
  1384. A registry to facilitate adaptation.
  1385. Pairs is an array of [name, check, wrap] triples
  1386. All check/wrap functions in this registry should be of the same arity.
  1387. ***/
  1388. this.pairs = [];
  1389. }
  1390. dojo.lang.extend(dojo.AdapterRegistry, {
  1391. register: function (name, check, wrap, /* optional */ override){
  1392. /***
  1393. The check function should return true if the given arguments are
  1394. appropriate for the wrap function.
  1395. If override is given and true, the check function will be given
  1396. highest priority. Otherwise, it will be the lowest priority
  1397. adapter.
  1398. ***/
  1399. if (override) {
  1400. this.pairs.unshift([name, check, wrap]);
  1401. } else {
  1402. this.pairs.push([name, check, wrap]);
  1403. }
  1404. },
  1405. match: function (/* ... */) {
  1406. /***
  1407. Find an adapter for the given arguments.
  1408. If no suitable adapter is found, throws NotFound.
  1409. ***/
  1410. for(var i = 0; i < this.pairs.length; i++){
  1411. var pair = this.pairs[i];
  1412. if(pair[1].apply(this, arguments)){
  1413. return pair[2].apply(this, arguments);
  1414. }
  1415. }
  1416. dojo.raise("No match found");
  1417. },
  1418. unregister: function (name) {
  1419. /***
  1420. Remove a named adapter from the registry
  1421. ***/
  1422. for(var i = 0; i < this.pairs.length; i++){
  1423. var pair = this.pairs[i];
  1424. if(pair[0] == name){
  1425. this.pairs.splice(i, 1);
  1426. return true;
  1427. }
  1428. }
  1429. return false;
  1430. }
  1431. });
  1432. dojo.lang.reprRegistry = new dojo.AdapterRegistry();
  1433. dojo.lang.registerRepr = function(name, check, wrap, /*optional*/ override){
  1434. /***
  1435. Register a repr function. repr functions should take
  1436. one argument and return a string representation of it
  1437. suitable for developers, primarily used when debugging.
  1438. If override is given, it is used as the highest priority
  1439. repr, otherwise it will be used as the lowest.
  1440. ***/
  1441. dojo.lang.reprRegistry.register(name, check, wrap, override);
  1442. };
  1443. dojo.lang.repr = function(obj){
  1444. /***
  1445. Return a "programmer representation" for an object
  1446. ***/
  1447. if(typeof(obj) == "undefined"){
  1448. return "undefined";
  1449. }else if(obj === null){
  1450. return "null";
  1451. }
  1452. try{
  1453. if(typeof(obj["__repr__"]) == 'function'){
  1454. return obj["__repr__"]();
  1455. }else if((typeof(obj["repr"]) == 'function')&&(obj.repr != arguments.callee)){
  1456. return obj["repr"]();
  1457. }
  1458. return dojo.lang.reprRegistry.match(obj);
  1459. }catch(e){
  1460. if(typeof(obj.NAME) == 'string' && (
  1461. obj.toString == Function.prototype.toString ||
  1462. obj.toString == Object.prototype.toString
  1463. )){
  1464. return o.NAME;
  1465. }
  1466. }
  1467. if(typeof(obj) == "function"){
  1468. obj = (obj + "").replace(/^\s+/, "");
  1469. var idx = obj.indexOf("{");
  1470. if(idx != -1){
  1471. obj = obj.substr(0, idx) + "{...}";
  1472. }
  1473. }
  1474. return obj + "";
  1475. }
  1476. dojo.lang.reprArrayLike = function(arr){
  1477. try{
  1478. var na = dojo.lang.map(arr, dojo.lang.repr);
  1479. return "[" + na.join(", ") + "]";
  1480. }catch(e){ }
  1481. };
  1482. dojo.lang.reprString = function(str){
  1483. return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
  1484. ).replace(/[\f]/g, "\\f"
  1485. ).replace(/[\b]/g, "\\b"
  1486. ).replace(/[\n]/g, "\\n"
  1487. ).replace(/[\t]/g, "\\t"
  1488. ).replace(/[\r]/g, "\\r");
  1489. };
  1490. dojo.lang.reprNumber = function(num){
  1491. return num + "";
  1492. };
  1493. (function(){
  1494. var m = dojo.lang;
  1495. m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
  1496. m.registerRepr("string", m.isString, m.reprString);
  1497. m.registerRepr("numbers", m.isNumber, m.reprNumber);
  1498. m.registerRepr("boolean", m.isBoolean, m.reprNumber);
  1499. // m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
  1500. })();
  1501. /**
  1502. * Creates a 1-D array out of all the arguments passed,
  1503. * unravelling any array-like objects in the process
  1504. *
  1505. * Ex:
  1506. * unnest(1, 2, 3) ==> [1, 2, 3]
  1507. * unnest(1, [2, [3], [[[4]]]]) ==> [1, 2, 3, 4]
  1508. */
  1509. dojo.lang.unnest = function(/* ... */) {
  1510. var out = [];
  1511. for(var i = 0; i < arguments.length; i++) {
  1512. if(dojo.lang.isArrayLike(arguments[i])) {
  1513. var add = dojo.lang.unnest.apply(this, arguments[i]);
  1514. out = out.concat(add);
  1515. } else {
  1516. out.push(arguments[i]);
  1517. }
  1518. }
  1519. return out;
  1520. }
  1521. dojo.provide("dojo.string");
  1522. dojo.require("dojo.lang");
  1523. /**
  1524. * Trim whitespace from 'str'. If 'wh' > 0,
  1525. * only trim from start, if 'wh' < 0, only trim
  1526. * from end, otherwise trim both ends
  1527. */
  1528. dojo.string.trim = function(str, wh){
  1529. if(!dojo.lang.isString(str)){ return str; }
  1530. if(!str.length){ return str; }
  1531. if(wh > 0) {
  1532. return str.replace(/^\s+/, "");
  1533. } else if(wh < 0) {
  1534. return str.replace(/\s+$/, "");
  1535. } else {
  1536. return str.replace(/^\s+|\s+$/g, "");
  1537. }
  1538. }
  1539. /**
  1540. * Trim whitespace at the beginning of 'str'
  1541. */
  1542. dojo.string.trimStart = function(str) {
  1543. return dojo.string.trim(str, 1);
  1544. }
  1545. /**
  1546. * Trim whitespace at the end of 'str'
  1547. */
  1548. dojo.string.trimEnd = function(str) {
  1549. return dojo.string.trim(str, -1);
  1550. }
  1551. /**
  1552. * Parameterized string function
  1553. * str - formatted string with %{values} to be replaces
  1554. * pairs - object of name: "value" value pairs
  1555. * killExtra - remove all remaining %{values} after pairs are inserted
  1556. */
  1557. dojo.string.paramString = function(str, pairs, killExtra) {
  1558. for(var name in pairs) {
  1559. var re = new RegExp("\\%\\{" + name + "\\}", "g");
  1560. str = str.replace(re, pairs[name]);
  1561. }
  1562. if(killExtra) { str = str.replace(/%\{([^\}\s]+)\}/g, ""); }
  1563. return str;
  1564. }
  1565. /** Uppercases the first letter of each word */
  1566. dojo.string.capitalize = function (str) {
  1567. if (!dojo.lang.isString(str)) { return ""; }
  1568. if (arguments.length == 0) { str = this; }
  1569. var words = str.split(' ');
  1570. var retval = "";
  1571. var len = words.length;
  1572. for (var i=0; i<len; i++) {
  1573. var word = words[i];
  1574. word = word.charAt(0).toUpperCase() + word.substring(1, word.length);
  1575. retval += word;
  1576. if (i < len-1)
  1577. retval += " ";
  1578. }
  1579. return new String(retval);
  1580. }
  1581. /**
  1582. * Return true if the entire string is whitespace characters
  1583. */
  1584. dojo.string.isBlank = function (str) {
  1585. if(!dojo.lang.isString(str)) { return true; }
  1586. return (dojo.string.trim(str).length == 0);
  1587. }
  1588. dojo.string.encodeAscii = function(str) {
  1589. if(!dojo.lang.isString(str)) { return str; }
  1590. var ret = "";
  1591. var value = escape(str);
  1592. var match, re = /%u([0-9A-F]{4})/i;
  1593. while((match = value.match(re))) {
  1594. var num = Number("0x"+match[1]);
  1595. var newVal = escape("&#" + num + ";");
  1596. ret += value.substring(0, match.index) + newVal;
  1597. value = value.substring(match.index+match[0].length);
  1598. }
  1599. ret += value.replace(/\+/g, "%2B");
  1600. return ret;
  1601. }
  1602. // TODO: make an HTML version
  1603. dojo.string.summary = function(str, len) {
  1604. if(!len || str.length <= len) {
  1605. return str;
  1606. } else {
  1607. return str.substring(0, len).replace(/\.+$/, "") + "...";
  1608. }
  1609. }
  1610. dojo.string.escape = function(type, str) {
  1611. switch(type.toLowerCase()) {
  1612. case "xml":
  1613. case "html":
  1614. case "xhtml":
  1615. return dojo.string.escapeXml(str);
  1616. case "sql":
  1617. return dojo.string.escapeSql(str);
  1618. case "regexp":
  1619. case "regex":
  1620. return dojo.string.escapeRegExp(str);
  1621. case "javascript":
  1622. case "jscript":
  1623. case "js":
  1624. return dojo.string.escapeJavaScript(str);
  1625. case "ascii":
  1626. // so it's encode, but it seems useful
  1627. return dojo.string.encodeAscii(str);
  1628. default:
  1629. return str;
  1630. }
  1631. }
  1632. dojo.string.escapeXml = function(str) {
  1633. return str.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
  1634. .replace(/>/gm, "&gt;").replace(/"/gm, "&quot;").replace(/'/gm, "&#39;");
  1635. }
  1636. dojo.string.escapeSql = function(str) {
  1637. return str.replace(/'/gm, "''");
  1638. }
  1639. dojo.string.escapeRegExp = function(str) {
  1640. return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r])/gm, "\\$1");
  1641. }
  1642. dojo.string.escapeJavaScript = function(str) {
  1643. return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1");
  1644. }
  1645. /**
  1646. * Return 'str' repeated 'count' times, optionally
  1647. * placing 'separator' between each rep
  1648. */
  1649. dojo.string.repeat = function(str, count, separator) {
  1650. var out = "";
  1651. for(var i = 0; i < count; i++) {
  1652. out += str;
  1653. if(separator && i < count - 1) {
  1654. out += separator;
  1655. }
  1656. }
  1657. return out;
  1658. }
  1659. /**
  1660. * Returns true if 'str' ends with 'end'
  1661. */
  1662. dojo.string.endsWith = function(str, end, ignoreCase) {
  1663. if(ignoreCase) {
  1664. str = str.toLowerCase();
  1665. end = end.toLowerCase();
  1666. }
  1667. return str.lastIndexOf(end) == str.length - end.length;
  1668. }
  1669. /**
  1670. * Returns true if 'str' ends with any of the arguments[2 -> n]
  1671. */
  1672. dojo.string.endsWithAny = function(str /* , ... */) {
  1673. for(var i = 1; i < arguments.length; i++) {
  1674. if(dojo.string.endsWith(str, arguments[i])) {
  1675. return true;
  1676. }
  1677. }
  1678. return false;
  1679. }
  1680. /**
  1681. * Returns true if 'str' starts with 'start'
  1682. */
  1683. dojo.string.startsWith = function(str, start, ignoreCase) {
  1684. if(ignoreCase) {
  1685. str = str.toLowerCase();
  1686. start = start.toLowerCase();
  1687. }
  1688. return str.indexOf(start) == 0;
  1689. }
  1690. /**
  1691. * Returns true if 'str' starts with any of the arguments[2 -> n]
  1692. */
  1693. dojo.string.startsWithAny = function(str /* , ... */) {
  1694. for(var i = 1; i < arguments.length; i++) {
  1695. if(dojo.string.startsWith(str, arguments[i])) {
  1696. return true;
  1697. }
  1698. }
  1699. return false;
  1700. }
  1701. /**
  1702. * Returns true if 'str' starts with any of the arguments 2 -> n
  1703. */
  1704. dojo.string.has = function(str /* , ... */) {
  1705. for(var i = 1; i < arguments.length; i++) {
  1706. if(str.indexOf(arguments[i] > -1)) {
  1707. return true;
  1708. }
  1709. }
  1710. return false;
  1711. }
  1712. /**
  1713. * Pad 'str' to guarantee that it is at least 'len' length
  1714. * with the character 'c' at either the start (dir=1) or
  1715. * end (dir=-1) of the string
  1716. */
  1717. dojo.string.pad = function(str, len/*=2*/, c/*='0'*/, dir/*=1*/) {
  1718. var out = String(str);
  1719. if(!c) {
  1720. c = '0';
  1721. }
  1722. if(!dir) {
  1723. dir = 1;
  1724. }
  1725. while(out.length < len) {
  1726. if(dir > 0) {
  1727. out = c + out;
  1728. } else {
  1729. out += c;
  1730. }
  1731. }
  1732. return out;
  1733. }
  1734. /** same as dojo.string.pad(str, len, c, 1) */
  1735. dojo.string.padLeft = function(str, len, c) {
  1736. return dojo.string.pad(str, len, c, 1);
  1737. }
  1738. /** same as dojo.string.pad(str, len, c, -1) */
  1739. dojo.string.padRight = function(str, len, c) {
  1740. return dojo.string.pad(str, len, c, -1);
  1741. }
  1742. // do we even want to offer this? is it worth it?
  1743. dojo.string.addToPrototype = function() {
  1744. for(var method in dojo.string) {
  1745. if(dojo.lang.isFunction(dojo.string[method])) {
  1746. var func = (function() {
  1747. var meth = method;
  1748. switch(meth) {
  1749. case "addToPrototype":
  1750. return null;
  1751. break;
  1752. case "escape":
  1753. return function(type) {
  1754. return dojo.string.escape(type, this);
  1755. }
  1756. break;
  1757. default:
  1758. return function() {
  1759. var args = [this];
  1760. for(var i = 0; i < arguments.length; i++) {
  1761. args.push(arguments[i]);
  1762. }
  1763. dojo.debug(args);
  1764. return dojo.string[meth].apply(dojo.string, args);
  1765. }
  1766. }
  1767. })();
  1768. if(func) { String.prototype[method] = func; }
  1769. }
  1770. }
  1771. }
  1772. dojo.provide("dojo.io.IO");
  1773. dojo.require("dojo.string");
  1774. /******************************************************************************
  1775. * Notes about dojo.io design:
  1776. *
  1777. * The dojo.io.* package has the unenviable task of making a lot of different
  1778. * types of I/O feel natural, despite a universal lack of good (or even
  1779. * reasonable!) I/O capability in the host environment. So lets pin this down
  1780. * a little bit further.
  1781. *
  1782. * Rhino:
  1783. * perhaps the best situation anywhere. Access to Java classes allows you
  1784. * to do anything one might want in terms of I/O, both synchronously and
  1785. * async. Can open TCP sockets and perform low-latency client/server
  1786. * interactions. HTTP transport is available through Java HTTP client and
  1787. * server classes. Wish it were always this easy.
  1788. *
  1789. * xpcshell:
  1790. * XPCOM for I/O. A cluster-fuck to be sure.
  1791. *
  1792. * spidermonkey:
  1793. * S.O.L.
  1794. *
  1795. * Browsers:
  1796. * Browsers generally do not provide any useable filesystem access. We are
  1797. * therefore limited to HTTP for moving information to and from Dojo
  1798. * instances living in a browser.
  1799. *
  1800. * XMLHTTP:
  1801. * Sync or async, allows reading of arbitrary text files (including
  1802. * JS, which can then be eval()'d), writing requires server
  1803. * cooperation and is limited to HTTP mechanisms (POST and GET).
  1804. *
  1805. * <iframe> hacks:
  1806. * iframe document hacks allow browsers to communicate asynchronously
  1807. * with a server via HTTP POST and GET operations. With significant
  1808. * effort and server cooperation, low-latency data transit between
  1809. * client and server can be acheived via iframe mechanisms (repubsub).
  1810. *
  1811. * SVG:
  1812. * Adobe's SVG viewer implements helpful primitives for XML-based
  1813. * requests, but receipt of arbitrary text data seems unlikely w/o
  1814. * <![CDATA[]]> sections.
  1815. *
  1816. *
  1817. * A discussion between Dylan, Mark, Tom, and Alex helped to lay down a lot
  1818. * the IO API interface. A transcript of it can be found at:
  1819. * http://dojotoolkit.org/viewcvs/viewcvs.py/documents/irc/irc_io_api_log.txt?rev=307&view=auto
  1820. *
  1821. * Also referenced in the design of the API was the DOM 3 L&S spec:
  1822. * http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/load-save.html
  1823. ******************************************************************************/
  1824. // a map of the available transport options. Transports should add themselves
  1825. // by calling add(name)
  1826. dojo.io.transports = [];
  1827. dojo.io.hdlrFuncNames = [ "load", "error" ]; // we're omitting a progress() event for now
  1828. dojo.io.Request = function(url, mimetype, transport, changeUrl){
  1829. if((arguments.length == 1)&&(arguments[0].constructor == Object)){
  1830. this.fromKwArgs(arguments[0]);
  1831. }else{
  1832. this.url = url;
  1833. if(mimetype){ this.mimetype = mimetype; }
  1834. if(transport){ this.transport = transport; }
  1835. if(arguments.length >= 4){ this.changeUrl = changeUrl; }
  1836. }
  1837. }
  1838. dojo.lang.extend(dojo.io.Request, {
  1839. /** The URL to hit */
  1840. url: "",
  1841. /** The mime type used to interrpret the response body */
  1842. mimetype: "text/plain",
  1843. /** The HTTP method to use */
  1844. method: "GET",
  1845. /** An Object containing key-value pairs to be included with the request */
  1846. content: undefined, // Object
  1847. /** The transport medium to use */
  1848. transport: undefined, // String
  1849. /** If defined the URL of the page is physically changed */
  1850. changeUrl: undefined, // String
  1851. /** A form node to use in the request */
  1852. formNode: undefined, // HTMLFormElement
  1853. /** Whether the request should be made synchronously */
  1854. sync: false,
  1855. bindSuccess: false,
  1856. /** Cache/look for the request in the cache before attempting to request?
  1857. * NOTE: this isn't a browser cache, this is internal and would only cache in-page
  1858. */
  1859. useCache: false,
  1860. /** Prevent the browser from caching this by adding a query string argument to the URL */
  1861. preventCache: false,
  1862. // events stuff
  1863. load: function(type, data, evt){ },
  1864. error: function(type, error){ },
  1865. handle: function(){ },
  1866. // the abort method needs to be filled in by the transport that accepts the
  1867. // bind() request
  1868. abort: function(){ },
  1869. // backButton: function(){ },
  1870. // forwardButton: function(){ },
  1871. fromKwArgs: function(kwArgs){
  1872. // normalize args
  1873. if(kwArgs["url"]){ kwArgs.url = kwArgs.url.toString(); }
  1874. if(!kwArgs["method"] && kwArgs["formNode"] && kwArgs["formNode"].method) {
  1875. kwArgs.method = kwArgs["formNode"].method;
  1876. }
  1877. // backwards compatibility
  1878. if(!kwArgs["handle"] && kwArgs["handler"]){ kwArgs.handle = kwArgs.handler; }
  1879. if(!kwArgs["load"] && kwArgs["loaded"]){ kwArgs.load = kwArgs.loaded; }
  1880. if(!kwArgs["changeUrl"] && kwArgs["changeURL"]) { kwArgs.changeUrl = kwArgs.changeURL; }
  1881. // encoding fun!
  1882. if(!kwArgs["encoding"]) {
  1883. if(!dojo.lang.isUndefined(djConfig["bindEncoding"])) {
  1884. kwArgs.encoding = djConfig.bindEncoding;
  1885. } else {
  1886. kwArgs.encoding = "";
  1887. }
  1888. }
  1889. var isFunction = dojo.lang.isFunction;
  1890. for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
  1891. var fn = dojo.io.hdlrFuncNames[x];
  1892. if(isFunction(kwArgs[fn])){ continue; }
  1893. if(isFunction(kwArgs["handle"])){
  1894. kwArgs[fn] = kwArgs.handle;
  1895. }
  1896. // handler is aliased above, shouldn't need this check
  1897. /* else if(dojo.lang.isObject(kwArgs.handler)){
  1898. if(isFunction(kwArgs.handler[fn])){
  1899. kwArgs[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"]||function(){};
  1900. }
  1901. }*/
  1902. }
  1903. dojo.lang.mixin(this, kwArgs);
  1904. }
  1905. });
  1906. dojo.io.Error = function(msg, type, num){
  1907. this.message = msg;
  1908. this.type = type || "unknown"; // must be one of "io", "parse", "unknown"
  1909. this.number = num || 0; // per-substrate error number, not normalized
  1910. }
  1911. dojo.io.transports.addTransport = function(name){
  1912. this.push(name);
  1913. // FIXME: do we need to handle things that aren't direct children of the
  1914. // dojo.io namespace? (say, dojo.io.foo.fooTransport?)
  1915. this[name] = dojo.io[name];
  1916. }
  1917. // binding interface, the various implementations register their capabilities
  1918. // and the bind() method dispatches
  1919. dojo.io.bind = function(request){
  1920. // if the request asks for a particular implementation, use it
  1921. if(!(request instanceof dojo.io.Request)){
  1922. try{
  1923. request = new dojo.io.Request(request);
  1924. }catch(e){ dojo.debug(e); }
  1925. }
  1926. var tsName = "";
  1927. if(request["transport"]){
  1928. tsName = request["transport"];
  1929. // FIXME: it would be good to call the error handler, although we'd
  1930. // need to use setTimeout or similar to accomplish this and we can't
  1931. // garuntee that this facility is available.
  1932. if(!this[tsName]){ return request; }
  1933. }else{
  1934. // otherwise we do our best to auto-detect what available transports
  1935. // will handle
  1936. for(var x=0; x<dojo.io.transports.length; x++){
  1937. var tmp = dojo.io.transports[x];
  1938. if((this[tmp])&&(this[tmp].canHandle(request))){
  1939. tsName = tmp;
  1940. }
  1941. }
  1942. if(tsName == ""){ return request; }
  1943. }
  1944. this[tsName].bind(request);
  1945. request.bindSuccess = true;
  1946. return request;
  1947. }
  1948. dojo.io.queueBind = function(request){
  1949. if(!(request instanceof dojo.io.Request)){
  1950. try{
  1951. request = new dojo.io.Request(request);
  1952. }catch(e){ dojo.debug(e); }
  1953. }
  1954. // make sure we get called if/when we get a response
  1955. var oldLoad = request.load;
  1956. request.load = function(){
  1957. dojo.io._queueBindInFlight = false;
  1958. var ret = oldLoad.apply(this, arguments);
  1959. dojo.io._dispatchNextQueueBind();
  1960. return ret;
  1961. }
  1962. var oldErr = request.error;
  1963. request.error = function(){
  1964. dojo.io._queueBindInFlight = false;
  1965. var ret = oldErr.apply(this, arguments);
  1966. dojo.io._dispatchNextQueueBind();
  1967. return ret;
  1968. }
  1969. dojo.io._bindQueue.push(request);
  1970. dojo.io._dispatchNextQueueBind();
  1971. return request;
  1972. }
  1973. dojo.io._dispatchNextQueueBind = function(){
  1974. if(!dojo.io._queueBindInFlight){
  1975. dojo.io._queueBindInFlight = true;
  1976. dojo.io.bind(dojo.io._bindQueue.shift());
  1977. }
  1978. }
  1979. dojo.io._bindQueue = [];
  1980. dojo.io._queueBindInFlight = false;
  1981. dojo.io.argsFromMap = function(map, encoding){
  1982. var control = new Object();
  1983. var mapStr = "";
  1984. var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
  1985. for(var x in map){
  1986. if(!control[x]){
  1987. mapStr+= enc(x)+"="+enc(map[x])+"&";
  1988. }
  1989. }
  1990. return mapStr;
  1991. }
  1992. /*
  1993. dojo.io.sampleTranport = new function(){
  1994. this.canHandle = function(kwArgs){
  1995. // canHandle just tells dojo.io.bind() if this is a good transport to
  1996. // use for the particular type of request.
  1997. if(
  1998. (
  1999. (kwArgs["mimetype"] == "text/plain") ||
  2000. (kwArgs["mimetype"] == "text/html") ||
  2001. (kwArgs["mimetype"] == "text/javascript")
  2002. )&&(
  2003. (kwArgs["method"] == "get") ||
  2004. ( (kwArgs["method"] == "post") && (!kwArgs["formNode"]) )
  2005. )
  2006. ){
  2007. return true;
  2008. }
  2009. return false;
  2010. }
  2011. this.bind = function(kwArgs){
  2012. var hdlrObj = {};
  2013. // set up a handler object
  2014. for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
  2015. var fn = dojo.io.hdlrFuncNames[x];
  2016. if(typeof kwArgs.handler == "object"){
  2017. if(typeof kwArgs.handler[fn] == "function"){
  2018. hdlrObj[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"];
  2019. }
  2020. }else if(typeof kwArgs[fn] == "function"){
  2021. hdlrObj[fn] = kwArgs[fn];
  2022. }else{
  2023. hdlrObj[fn] = kwArgs["handle"]||function(){};
  2024. }
  2025. }
  2026. // build a handler function that calls back to the handler obj
  2027. var hdlrFunc = function(evt){
  2028. if(evt.type == "onload"){
  2029. hdlrObj.load("load", evt.data, evt);
  2030. }else if(evt.type == "onerr"){
  2031. var errObj = new dojo.io.Error("sampleTransport Error: "+evt.msg);
  2032. hdlrObj.error("error", errObj);
  2033. }
  2034. }
  2035. // the sample transport would attach the hdlrFunc() when sending the
  2036. // request down the pipe at this point
  2037. var tgtURL = kwArgs.url+"?"+dojo.io.argsFromMap(kwArgs.content);
  2038. // sampleTransport.sendRequest(tgtURL, hdlrFunc);
  2039. }
  2040. dojo.io.transports.addTransport("sampleTranport");
  2041. }
  2042. */
  2043. dojo.provide("dojo.dom");
  2044. dojo.require("dojo.lang");
  2045. dojo.dom.ELEMENT_NODE = 1;
  2046. dojo.dom.ATTRIBUTE_NODE = 2;
  2047. dojo.dom.TEXT_NODE = 3;
  2048. dojo.dom.CDATA_SECTION_NODE = 4;
  2049. dojo.dom.ENTITY_REFERENCE_NODE = 5;
  2050. dojo.dom.ENTITY_NODE = 6;
  2051. dojo.dom.PROCESSING_INSTRUCTION_NODE = 7;
  2052. dojo.dom.COMMENT_NODE = 8;
  2053. dojo.dom.DOCUMENT_NODE = 9;
  2054. dojo.dom.DOCUMENT_TYPE_NODE = 10;
  2055. dojo.dom.DOCUMENT_FRAGMENT_NODE = 11;
  2056. dojo.dom.NOTATION_NODE = 12;
  2057. dojo.dom.dojoml = "http://www.dojotoolkit.org/2004/dojoml";
  2058. /**
  2059. * comprehensive list of XML namespaces
  2060. **/
  2061. dojo.dom.xmlns = {
  2062. svg : "http://www.w3.org/2000/svg",
  2063. smil : "http://www.w3.org/2001/SMIL20/",
  2064. mml : "http://www.w3.org/1998/Math/MathML",
  2065. cml : "http://www.xml-cml.org",
  2066. xlink : "http://www.w3.org/1999/xlink",
  2067. xhtml : "http://www.w3.org/1999/xhtml",
  2068. xul : "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
  2069. xbl : "http://www.mozilla.org/xbl",
  2070. fo : "http://www.w3.org/1999/XSL/Format",
  2071. xsl : "http://www.w3.org/1999/XSL/Transform",
  2072. xslt : "http://www.w3.org/1999/XSL/Transform",
  2073. xi : "http://www.w3.org/2001/XInclude",
  2074. xforms : "http://www.w3.org/2002/01/xforms",
  2075. saxon : "http://icl.com/saxon",
  2076. xalan : "http://xml.apache.org/xslt",
  2077. xsd : "http://www.w3.org/2001/XMLSchema",
  2078. dt: "http://www.w3.org/2001/XMLSchema-datatypes",
  2079. xsi : "http://www.w3.org/2001/XMLSchema-instance",
  2080. rdf : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
  2081. rdfs : "http://www.w3.org/2000/01/rdf-schema#",
  2082. dc : "http://purl.org/dc/elements/1.1/",
  2083. dcq: "http://purl.org/dc/qualifiers/1.0",
  2084. "soap-env" : "http://schemas.xmlsoap.org/soap/envelope/",
  2085. wsdl : "http://schemas.xmlsoap.org/wsdl/",
  2086. AdobeExtensions : "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
  2087. };
  2088. dojo.dom.isNode = dojo.lang.isDomNode = function(wh){
  2089. if(typeof Element == "object") {
  2090. try {
  2091. return wh instanceof Element;
  2092. } catch(E) {}
  2093. } else {
  2094. // best-guess
  2095. return wh && !isNaN(wh.nodeType);
  2096. }
  2097. }
  2098. dojo.lang.whatAmI.custom["node"] = dojo.dom.isNode;
  2099. dojo.dom.getTagName = function(node){
  2100. var tagName = node.tagName;
  2101. if(tagName.substr(0,5).toLowerCase()!="dojo:"){
  2102. if(tagName.substr(0,4).toLowerCase()=="dojo"){
  2103. // FIXME: this assuumes tag names are always lower case
  2104. return "dojo:" + tagName.substring(4).toLowerCase();
  2105. }
  2106. // allow lower-casing
  2107. var djt = node.getAttribute("dojoType")||node.getAttribute("dojotype");
  2108. if(djt){
  2109. return "dojo:"+djt.toLowerCase();
  2110. }
  2111. if((node.getAttributeNS)&&(node.getAttributeNS(this.dojoml,"type"))){
  2112. return "dojo:" + node.getAttributeNS(this.dojoml,"type").toLowerCase();
  2113. }
  2114. try{
  2115. // FIXME: IE really really doesn't like this, so we squelch
  2116. // errors for it
  2117. djt = node.getAttribute("dojo:type");
  2118. }catch(e){ /* FIXME: log? */ }
  2119. if(djt){
  2120. return "dojo:"+djt.toLowerCase();
  2121. }
  2122. if((!dj_global["djConfig"])||(!djConfig["ignoreClassNames"])){
  2123. // FIXME: should we make this optionally enabled via djConfig?
  2124. var classes = node.className||node.getAttribute("class");
  2125. if((classes)&&(classes.indexOf("dojo-") != -1)){
  2126. var aclasses = classes.split(" ");
  2127. for(var x=0; x<aclasses.length; x++){
  2128. if((aclasses[x].length>5)&&(aclasses[x].indexOf("dojo-")>=0)){
  2129. return "dojo:"+aclasses[x].substr(5).toLowerCase();
  2130. }
  2131. }
  2132. }
  2133. }
  2134. }
  2135. return tagName.toLowerCase();
  2136. }
  2137. dojo.dom.getUniqueId = function(){
  2138. do {
  2139. var id = "dj_unique_" + (++arguments.callee._idIncrement);
  2140. }while(document.getElementById(id));
  2141. return id;
  2142. }
  2143. dojo.dom.getUniqueId._idIncrement = 0;
  2144. dojo.dom.firstElement = dojo.dom.getFirstChildElement = function(parentNode, tagName){
  2145. var node = parentNode.firstChild;
  2146. while(node && node.nodeType != dojo.dom.ELEMENT_NODE){
  2147. node = node.nextSibling;
  2148. }
  2149. if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
  2150. node = dojo.dom.nextElement(node, tagName);
  2151. }
  2152. return node;
  2153. }
  2154. dojo.dom.lastElement = dojo.dom.getLastChildElement = function(parentNode, tagName){
  2155. var node = parentNode.lastChild;
  2156. while(node && node.nodeType != dojo.dom.ELEMENT_NODE) {
  2157. node = node.previousSibling;
  2158. }
  2159. if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
  2160. node = dojo.dom.prevElement(node, tagName);
  2161. }
  2162. return node;
  2163. }
  2164. dojo.dom.nextElement = dojo.dom.getNextSiblingElement = function(node, tagName){
  2165. if(!node) { return null; }
  2166. do {
  2167. node = node.nextSibling;
  2168. } while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
  2169. if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
  2170. return dojo.dom.nextElement(node, tagName);
  2171. }
  2172. return node;
  2173. }
  2174. dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement = function(node, tagName){
  2175. if(!node) { return null; }
  2176. if(tagName) { tagName = tagName.toLowerCase(); }
  2177. do {
  2178. node = node.previousSibling;
  2179. } while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
  2180. if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
  2181. return dojo.dom.prevElement(node, tagName);
  2182. }
  2183. return node;
  2184. }
  2185. // TODO: hmph
  2186. /*this.forEachChildTag = function(node, unaryFunc) {
  2187. var child = this.getFirstChildTag(node);
  2188. while(child) {
  2189. if(unaryFunc(child) == "break") { break; }
  2190. child = this.getNextSiblingTag(child);
  2191. }
  2192. }*/
  2193. dojo.dom.moveChildren = function(srcNode, destNode, trim){
  2194. var count = 0;
  2195. if(trim) {
  2196. while(srcNode.hasChildNodes() &&
  2197. srcNode.firstChild.nodeType == dojo.dom.TEXT_NODE) {
  2198. srcNode.removeChild(srcNode.firstChild);
  2199. }
  2200. while(srcNode.hasChildNodes() &&
  2201. srcNode.lastChild.nodeType == dojo.dom.TEXT_NODE) {
  2202. srcNode.removeChild(srcNode.lastChild);
  2203. }
  2204. }
  2205. while(srcNode.hasChildNodes()){
  2206. destNode.appendChild(srcNode.firstChild);
  2207. count++;
  2208. }
  2209. return count;
  2210. }
  2211. dojo.dom.copyChildren = function(srcNode, destNode, trim){
  2212. var clonedNode = srcNode.cloneNode(true);
  2213. return this.moveChildren(clonedNode, destNode, trim);
  2214. }
  2215. dojo.dom.removeChildren = function(node){
  2216. var count = node.childNodes.length;
  2217. while(node.hasChildNodes()){ node.removeChild(node.firstChild); }
  2218. return count;
  2219. }
  2220. dojo.dom.replaceChildren = function(node, newChild){
  2221. // FIXME: what if newChild is an array-like object?
  2222. dojo.dom.removeChildren(node);
  2223. node.appendChild(newChild);
  2224. }
  2225. dojo.dom.removeNode = function(node){
  2226. if(node && node.parentNode){
  2227. // return a ref to the removed child
  2228. return node.parentNode.removeChild(node);
  2229. }
  2230. }
  2231. dojo.dom.getAncestors = function(node, filterFunction, returnFirstHit) {
  2232. var ancestors = [];
  2233. var isFunction = dojo.lang.isFunction(filterFunction);
  2234. while(node) {
  2235. if (!isFunction || filterFunction(node)) {
  2236. ancestors.push(node);
  2237. }
  2238. if (returnFirstHit && ancestors.length > 0) { return ancestors[0]; }
  2239. node = node.parentNode;
  2240. }
  2241. if (returnFirstHit) { return null; }
  2242. return ancestors;
  2243. }
  2244. dojo.dom.getAncestorsByTag = function(node, tag, returnFirstHit) {
  2245. tag = tag.toLowerCase();
  2246. return dojo.dom.getAncestors(node, function(el){
  2247. return ((el.tagName)&&(el.tagName.toLowerCase() == tag));
  2248. }, returnFirstHit);
  2249. }
  2250. dojo.dom.getFirstAncestorByTag = function(node, tag) {
  2251. return dojo.dom.getAncestorsByTag(node, tag, true);
  2252. }
  2253. dojo.dom.isDescendantOf = function(node, ancestor, guaranteeDescendant){
  2254. // guaranteeDescendant allows us to be a "true" isDescendantOf function
  2255. if(guaranteeDescendant && node) { node = node.parentNode; }
  2256. while(node) {
  2257. if(node == ancestor){ return true; }
  2258. node = node.parentNode;
  2259. }
  2260. return false;
  2261. }
  2262. dojo.dom.innerXML = function(node){
  2263. if(node.innerXML){
  2264. return node.innerXML;
  2265. }else if(typeof XMLSerializer != "undefined"){
  2266. return (new XMLSerializer()).serializeToString(node);
  2267. }
  2268. }
  2269. dojo.dom.createDocumentFromText = function(str, mimetype){
  2270. if(!mimetype) { mimetype = "text/xml"; }
  2271. if(typeof DOMParser != "undefined") {
  2272. var parser = new DOMParser();
  2273. return parser.parseFromString(str, mimetype);
  2274. }else if(typeof ActiveXObject != "undefined"){
  2275. var domDoc = new ActiveXObject("Microsoft.XMLDOM");
  2276. if(domDoc) {
  2277. domDoc.async = false;
  2278. domDoc.loadXML(str);
  2279. return domDoc;
  2280. }else{
  2281. dojo.debug("toXml didn't work?");
  2282. }
  2283. /*
  2284. }else if((dojo.render.html.capable)&&(dojo.render.html.safari)){
  2285. // FIXME: this doesn't appear to work!
  2286. // from: http://web-graphics.com/mtarchive/001606.php
  2287. // var xml = '<?xml version="1.0"?>'+str;
  2288. var mtype = "text/xml";
  2289. var xml = '<?xml version="1.0"?>'+str;
  2290. var url = "data:"+mtype+";charset=utf-8,"+encodeURIComponent(xml);
  2291. var req = new XMLHttpRequest();
  2292. req.open("GET", url, false);
  2293. req.overrideMimeType(mtype);
  2294. req.send(null);
  2295. return req.responseXML;
  2296. */
  2297. }else if(document.createElement){
  2298. // FIXME: this may change all tags to uppercase!
  2299. var tmp = document.createElement("xml");
  2300. tmp.innerHTML = str;
  2301. if(document.implementation && document.implementation.createDocument) {
  2302. var xmlDoc = document.implementation.createDocument("foo", "", null);
  2303. for(var i = 0; i < tmp.childNodes.length; i++) {
  2304. xmlDoc.importNode(tmp.childNodes.item(i), true);
  2305. }
  2306. return xmlDoc;
  2307. }
  2308. // FIXME: probably not a good idea to have to return an HTML fragment
  2309. // FIXME: the tmp.doc.firstChild is as tested from IE, so it may not
  2310. // work that way across the board
  2311. return tmp.document && tmp.document.firstChild ?
  2312. tmp.document.firstChild : tmp;
  2313. }
  2314. return null;
  2315. }
  2316. dojo.dom.insertBefore = function(node, ref, force){
  2317. if (force != true &&
  2318. (node === ref || node.nextSibling === ref)){ return false; }
  2319. var parent = ref.parentNode;
  2320. parent.insertBefore(node, ref);
  2321. return true;
  2322. }
  2323. dojo.dom.insertAfter = function(node, ref, force){
  2324. var pn = ref.parentNode;
  2325. if(ref == pn.lastChild){
  2326. if((force != true)&&(node === ref)){
  2327. return false;
  2328. }
  2329. pn.appendChild(node);
  2330. }else{
  2331. return this.insertBefore(node, ref.nextSibling, force);
  2332. }
  2333. return true;
  2334. }
  2335. dojo.dom.insertAtPosition = function(node, ref, position){
  2336. if((!node)||(!ref)||(!position)){ return false; }
  2337. switch(position.toLowerCase()){
  2338. case "before":
  2339. return dojo.dom.insertBefore(node, ref);
  2340. case "after":
  2341. return dojo.dom.insertAfter(node, ref);
  2342. case "first":
  2343. if(ref.firstChild){
  2344. return dojo.dom.insertBefore(node, ref.firstChild);
  2345. }else{
  2346. ref.appendChild(node);
  2347. return true;
  2348. }
  2349. break;
  2350. default: // aka: last
  2351. ref.appendChild(node);
  2352. return true;
  2353. }
  2354. }
  2355. dojo.dom.insertAtIndex = function(node, containingNode, insertionIndex){
  2356. var siblingNodes = containingNode.childNodes;
  2357. // if there aren't any kids yet, just add it to the beginning
  2358. if (!siblingNodes.length){
  2359. containingNode.appendChild(node);
  2360. return true;
  2361. }
  2362. // otherwise we need to walk the childNodes
  2363. // and find our spot
  2364. var after = null;
  2365. for(var i=0; i<siblingNodes.length; i++){
  2366. var sibling_index = siblingNodes.item(i)["getAttribute"] ? parseInt(siblingNodes.item(i).getAttribute("dojoinsertionindex")) : -1;
  2367. if (sibling_index < insertionIndex){
  2368. after = siblingNodes.item(i);
  2369. }
  2370. }
  2371. if (after){
  2372. // add it after the node in {after}
  2373. return dojo.dom.insertAfter(node, after);
  2374. }else{
  2375. // add it to the start
  2376. return dojo.dom.insertBefore(node, siblingNodes.item(0));
  2377. }
  2378. }
  2379. /**
  2380. * implementation of the DOM Level 3 attribute.
  2381. *
  2382. * @param node The node to scan for text
  2383. * @param text Optional, set the text to this value.
  2384. */
  2385. dojo.dom.textContent = function(node, text){
  2386. if (text) {
  2387. dojo.dom.replaceChildren(node, document.createTextNode(text));
  2388. return text;
  2389. } else {
  2390. var _result = "";
  2391. if (node == null) { return _result; }
  2392. for (var i = 0; i < node.childNodes.length; i++) {
  2393. switch (node.childNodes[i].nodeType) {
  2394. case 1: // ELEMENT_NODE
  2395. case 5: // ENTITY_REFERENCE_NODE
  2396. _result += dojo.dom.textContent(node.childNodes[i]);
  2397. break;
  2398. case 3: // TEXT_NODE
  2399. case 2: // ATTRIBUTE_NODE
  2400. case 4: // CDATA_SECTION_NODE
  2401. _result += node.childNodes[i].nodeValue;
  2402. break;
  2403. default:
  2404. break;
  2405. }
  2406. }
  2407. return _result;
  2408. }
  2409. }
  2410. dojo.dom.collectionToArray = function(collection){
  2411. var array = new Array(collection.length);
  2412. for (var i = 0; i < collection.length; i++) {
  2413. array[i] = collection[i];
  2414. }
  2415. return array;
  2416. }
  2417. dojo.provide("dojo.io.BrowserIO");
  2418. dojo.require("dojo.io");
  2419. dojo.require("dojo.lang");
  2420. dojo.require("dojo.dom");
  2421. try {
  2422. if((!djConfig.preventBackButtonFix)&&(!dojo.hostenv.post_load_)){
  2423. document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='"+(dojo.hostenv.getBaseScriptUri()+'iframe_history.html')+"'></iframe>");
  2424. }
  2425. }catch(e){/* squelch */}
  2426. dojo.io.checkChildrenForFile = function(node){
  2427. var hasFile = false;
  2428. var inputs = node.getElementsByTagName("input");
  2429. dojo.lang.forEach(inputs, function(input){
  2430. if(hasFile){ return; }
  2431. if(input.getAttribute("type")=="file"){
  2432. hasFile = true;
  2433. }
  2434. });
  2435. return hasFile;
  2436. }
  2437. dojo.io.formHasFile = function(formNode){
  2438. return dojo.io.checkChildrenForFile(formNode);
  2439. }
  2440. // TODO: Move to htmlUtils
  2441. dojo.io.encodeForm = function(formNode, encoding){
  2442. if((!formNode)||(!formNode.tagName)||(!formNode.tagName.toLowerCase() == "form")){
  2443. dojo.raise("Attempted to encode a non-form element.");
  2444. }
  2445. var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
  2446. var values = [];
  2447. for(var i = 0; i < formNode.elements.length; i++){
  2448. var elm = formNode.elements[i];
  2449. if(elm.disabled || elm.tagName.toLowerCase() == "fieldset" || !elm.name){
  2450. continue;
  2451. }
  2452. var name = enc(elm.name);
  2453. var type = elm.type.toLowerCase();
  2454. if(type == "select-multiple"){
  2455. for(var j = 0; j < elm.options.length; j++){
  2456. if(elm.options[j].selected) {
  2457. values.push(name + "=" + enc(elm.options[j].value));
  2458. }
  2459. }
  2460. }else if(dojo.lang.inArray(type, ["radio", "checkbox"])){
  2461. if(elm.checked){
  2462. values.push(name + "=" + enc(elm.value));
  2463. }
  2464. }else if(!dojo.lang.inArray(type, ["file", "submit", "reset", "button"])) {
  2465. values.push(name + "=" + enc(elm.value));
  2466. }
  2467. }
  2468. // now collect input type="image", which doesn't show up in the elements array
  2469. var inputs = formNode.getElementsByTagName("input");
  2470. for(var i = 0; i < inputs.length; i++) {
  2471. var input = inputs[i];
  2472. if(input.type.toLowerCase() == "image" && input.form == formNode) {
  2473. var name = enc(input.name);
  2474. values.push(name + "=" + enc(input.value));
  2475. values.push(name + ".x=0");
  2476. values.push(name + ".y=0");
  2477. }
  2478. }
  2479. return values.join("&") + "&";
  2480. }
  2481. dojo.io.setIFrameSrc = function(iframe, src, replace){
  2482. try{
  2483. var r = dojo.render.html;
  2484. // dojo.debug(iframe);
  2485. if(!replace){
  2486. if(r.safari){
  2487. iframe.location = src;
  2488. }else{
  2489. frames[iframe.name].location = src;
  2490. }
  2491. }else{
  2492. var idoc;
  2493. // dojo.debug(iframe.name);
  2494. if(r.ie){
  2495. idoc = iframe.contentWindow.document;
  2496. }else if(r.moz){
  2497. idoc = iframe.contentWindow;
  2498. }
  2499. idoc.location.replace(src);
  2500. }
  2501. }catch(e){
  2502. dojo.debug(e);
  2503. dojo.debug("setIFrameSrc: "+e);
  2504. }
  2505. }
  2506. dojo.io.XMLHTTPTransport = new function(){
  2507. var _this = this;
  2508. this.initialHref = window.location.href;
  2509. this.initialHash = window.location.hash;
  2510. this.moveForward = false;
  2511. var _cache = {}; // FIXME: make this public? do we even need to?
  2512. this.useCache = false; // if this is true, we'll cache unless kwArgs.useCache = false
  2513. this.preventCache = false; // if this is true, we'll always force GET requests to cache
  2514. this.historyStack = [];
  2515. this.forwardStack = [];
  2516. this.historyIframe = null;
  2517. this.bookmarkAnchor = null;
  2518. this.locationTimer = null;
  2519. /* NOTES:
  2520. * Safari 1.2:
  2521. * back button "works" fine, however it's not possible to actually
  2522. * DETECT that you've moved backwards by inspecting window.location.
  2523. * Unless there is some other means of locating.
  2524. * FIXME: perhaps we can poll on history.length?
  2525. * IE 5.5 SP2:
  2526. * back button behavior is macro. It does not move back to the
  2527. * previous hash value, but to the last full page load. This suggests
  2528. * that the iframe is the correct way to capture the back button in
  2529. * these cases.
  2530. * IE 6.0:
  2531. * same behavior as IE 5.5 SP2
  2532. * Firefox 1.0:
  2533. * the back button will return us to the previous hash on the same
  2534. * page, thereby not requiring an iframe hack, although we do then
  2535. * need to run a timer to detect inter-page movement.
  2536. */
  2537. // FIXME: Should this even be a function? or do we just hard code it in the next 2 functions?
  2538. function getCacheKey(url, query, method) {
  2539. return url + "|" + query + "|" + method.toLowerCase();
  2540. }
  2541. function addToCache(url, query, method, http) {
  2542. _cache[getCacheKey(url, query, method)] = http;
  2543. }
  2544. function getFromCache(url, query, method) {
  2545. return _cache[getCacheKey(url, query, method)];
  2546. }
  2547. this.clearCache = function() {
  2548. _cache = {};
  2549. }
  2550. // moved successful load stuff here
  2551. function doLoad(kwArgs, http, url, query, useCache) {
  2552. if((http.status==200)||(location.protocol=="file:" && http.status==0)) {
  2553. var ret;
  2554. if(kwArgs.method.toLowerCase() == "head"){
  2555. var headers = http.getAllResponseHeaders();
  2556. ret = {};
  2557. ret.toString = function(){ return headers; }
  2558. var values = headers.split(/[\r\n]+/g);
  2559. for(var i = 0; i < values.length; i++) {
  2560. var pair = values[i].match(/^([^:]+)\s*:\s*(.+)$/i);
  2561. if(pair) {
  2562. ret[pair[1]] = pair[2];
  2563. }
  2564. }
  2565. }else if(kwArgs.mimetype == "text/javascript"){
  2566. try{
  2567. ret = dj_eval(http.responseText);
  2568. }catch(e){
  2569. dojo.debug(e);
  2570. dojo.debug(http.responseText);
  2571. ret = null;
  2572. }
  2573. }else if(kwArgs.mimetype == "text/json"){
  2574. try{
  2575. ret = dj_eval("("+http.responseText+")");
  2576. }catch(e){
  2577. dojo.debug(e);
  2578. dojo.debug(http.responseText);
  2579. ret = false;
  2580. }
  2581. }else if((kwArgs.mimetype == "application/xml")||
  2582. (kwArgs.mimetype == "text/xml")){
  2583. ret = http.responseXML;
  2584. if(!ret || typeof ret == "string") {
  2585. ret = dojo.dom.createDocumentFromText(http.responseText);
  2586. }
  2587. }else{
  2588. ret = http.responseText;
  2589. }
  2590. if(useCache){ // only cache successful responses
  2591. addToCache(url, query, kwArgs.method, http);
  2592. }
  2593. kwArgs[(typeof kwArgs.load == "function") ? "load" : "handle"]("load", ret, http);
  2594. }else{
  2595. var errObj = new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
  2596. kwArgs[(typeof kwArgs.error == "function") ? "error" : "handle"]("error", errObj, http);
  2597. }
  2598. }
  2599. // set headers (note: Content-Type will get overriden if kwArgs.contentType is set)
  2600. function setHeaders(http, kwArgs){
  2601. if(kwArgs["headers"]) {
  2602. for(var header in kwArgs["headers"]) {
  2603. if(header.toLowerCase() == "content-type" && !kwArgs["contentType"]) {
  2604. kwArgs["contentType"] = kwArgs["headers"][header];
  2605. } else {
  2606. http.setRequestHeader(header, kwArgs["headers"][header]);
  2607. }
  2608. }
  2609. }
  2610. }
  2611. this.addToHistory = function(args){
  2612. var callback = args["back"]||args["backButton"]||args["handle"];
  2613. var hash = null;
  2614. if(!this.historyIframe){
  2615. this.historyIframe = window.frames["djhistory"];
  2616. }
  2617. if(!this.bookmarkAnchor){
  2618. this.bookmarkAnchor = document.createElement("a");
  2619. (document.body||document.getElementsByTagName("body")[0]).appendChild(this.bookmarkAnchor);
  2620. this.bookmarkAnchor.style.display = "none";
  2621. }
  2622. if((!args["changeUrl"])||(dojo.render.html.ie)){
  2623. var url = dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime();
  2624. this.moveForward = true;
  2625. dojo.io.setIFrameSrc(this.historyIframe, url, false);
  2626. }
  2627. if(args["changeUrl"]){
  2628. hash = "#"+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
  2629. setTimeout("window.location.href = '"+hash+"';", 1);
  2630. this.bookmarkAnchor.href = hash;
  2631. if(dojo.render.html.ie){
  2632. // IE requires manual setting of the hash since we are catching
  2633. // events from the iframe
  2634. var oldCB = callback;
  2635. var lh = null;
  2636. var hsl = this.historyStack.length-1;
  2637. if(hsl>=0){
  2638. while(!this.historyStack[hsl]["urlHash"]){
  2639. hsl--;
  2640. }
  2641. lh = this.historyStack[hsl]["urlHash"];
  2642. }
  2643. if(lh){
  2644. callback = function(){
  2645. if(window.location.hash != ""){
  2646. setTimeout("window.location.href = '"+lh+"';", 1);
  2647. }
  2648. oldCB();
  2649. }
  2650. }
  2651. // when we issue a new bind(), we clobber the forward
  2652. // FIXME: is this always a good idea?
  2653. this.forwardStack = [];
  2654. var oldFW = args["forward"]||args["forwardButton"];;
  2655. var tfw = function(){
  2656. if(window.location.hash != ""){
  2657. window.location.href = hash;
  2658. }
  2659. if(oldFW){ // we might not actually have one
  2660. oldFW();
  2661. }
  2662. }
  2663. if(args["forward"]){
  2664. args.forward = tfw;
  2665. }else if(args["forwardButton"]){
  2666. args.forwardButton = tfw;
  2667. }
  2668. }else if(dojo.render.html.moz){
  2669. // start the timer
  2670. if(!this.locationTimer){
  2671. this.locationTimer = setInterval("dojo.io.XMLHTTPTransport.checkLocation();", 200);
  2672. }
  2673. }
  2674. }
  2675. this.historyStack.push({"url": url, "callback": callback, "kwArgs": args, "urlHash": hash});
  2676. }
  2677. this.checkLocation = function(){
  2678. var hsl = this.historyStack.length;
  2679. if((window.location.hash == this.initialHash)||(window.location.href == this.initialHref)&&(hsl == 1)){
  2680. // FIXME: could this ever be a forward button?
  2681. // we can't clear it because we still need to check for forwards. Ugg.
  2682. // clearInterval(this.locationTimer);
  2683. this.handleBackButton();
  2684. return;
  2685. }
  2686. // first check to see if we could have gone forward. We always halt on
  2687. // a no-hash item.
  2688. if(this.forwardStack.length > 0){
  2689. if(this.forwardStack[this.forwardStack.length-1].urlHash == window.location.hash){
  2690. this.handleForwardButton();
  2691. return;
  2692. }
  2693. }
  2694. // ok, that didn't work, try someplace back in the history stack
  2695. if((hsl >= 2)&&(this.historyStack[hsl-2])){
  2696. if(this.historyStack[hsl-2].urlHash==window.location.hash){
  2697. this.handleBackButton();
  2698. return;
  2699. }
  2700. }
  2701. }
  2702. this.iframeLoaded = function(evt, ifrLoc){
  2703. var isp = ifrLoc.href.split("?");
  2704. if(isp.length < 2){
  2705. // alert("iframeLoaded");
  2706. // we hit the end of the history, so we should go back
  2707. if(this.historyStack.length == 1){
  2708. this.handleBackButton();
  2709. }
  2710. return;
  2711. }
  2712. var query = isp[1];
  2713. if(this.moveForward){
  2714. // we were expecting it, so it's not either a forward or backward
  2715. // movement
  2716. this.moveForward = false;
  2717. return;
  2718. }
  2719. var last = this.historyStack.pop();
  2720. // we don't have anything in history, so it could be a forward button
  2721. if(!last){
  2722. if(this.forwardStack.length > 0){
  2723. var next = this.forwardStack[this.forwardStack.length-1];
  2724. if(query == next.url.split("?")[1]){
  2725. this.handleForwardButton();
  2726. }
  2727. }
  2728. // regardless, we didnt' have any history, so it can't be a back button
  2729. return;
  2730. }
  2731. // put it back on the stack so we can do something useful with it when
  2732. // we call handleBackButton()
  2733. this.historyStack.push(last);
  2734. if(this.historyStack.length >= 2){
  2735. if(isp[1] == this.historyStack[this.historyStack.length-2].url.split("?")[1]){
  2736. // looks like it IS a back button press, so handle it
  2737. this.handleBackButton();
  2738. }
  2739. }else{
  2740. this.handleBackButton();
  2741. }
  2742. }
  2743. this.handleBackButton = function(){
  2744. var last = this.historyStack.pop();
  2745. if(!last){ return; }
  2746. if(last["callback"]){
  2747. last.callback();
  2748. }else if(last.kwArgs["backButton"]){
  2749. last.kwArgs["backButton"]();
  2750. }else if(last.kwArgs["back"]){
  2751. last.kwArgs["back"]();
  2752. }else if(last.kwArgs["handle"]){
  2753. last.kwArgs.handle("back");
  2754. }
  2755. this.forwardStack.push(last);
  2756. }
  2757. this.handleForwardButton = function(){
  2758. // FIXME: should we build in support for re-issuing the bind() call here?
  2759. // alert("alert we found a forward button call");
  2760. var last = this.forwardStack.pop();
  2761. if(!last){ return; }
  2762. if(last.kwArgs["forward"]){
  2763. last.kwArgs.forward();
  2764. }else if(last.kwArgs["forwardButton"]){
  2765. last.kwArgs.forwardButton();
  2766. }else if(last.kwArgs["handle"]){
  2767. last.kwArgs.handle("forward");
  2768. }
  2769. this.historyStack.push(last);
  2770. }
  2771. this.inFlight = [];
  2772. this.inFlightTimer = null;
  2773. this.startWatchingInFlight = function(){
  2774. if(!this.inFlightTimer){
  2775. this.inFlightTimer = setInterval("dojo.io.XMLHTTPTransport.watchInFlight();", 10);
  2776. }
  2777. }
  2778. this.watchInFlight = function(){
  2779. for(var x=this.inFlight.length-1; x>=0; x--){
  2780. var tif = this.inFlight[x];
  2781. if(!tif){ this.inFlight.splice(x, 1); continue; }
  2782. if(4==tif.http.readyState){
  2783. // remove it so we can clean refs
  2784. this.inFlight.splice(x, 1);
  2785. doLoad(tif.req, tif.http, tif.url, tif.query, tif.useCache);
  2786. if(this.inFlight.length == 0){
  2787. clearInterval(this.inFlightTimer);
  2788. this.inFlightTimer = null;
  2789. }
  2790. } // FIXME: need to implement a timeout param here!
  2791. }
  2792. }
  2793. var hasXmlHttp = dojo.hostenv.getXmlhttpObject() ? true : false;
  2794. this.canHandle = function(kwArgs){
  2795. // canHandle just tells dojo.io.bind() if this is a good transport to
  2796. // use for the particular type of request.
  2797. // FIXME: we need to determine when form values need to be
  2798. // multi-part mime encoded and avoid using this transport for those
  2799. // requests.
  2800. return hasXmlHttp
  2801. && dojo.lang.inArray((kwArgs["mimetype"]||"".toLowerCase()), ["text/plain", "text/html", "application/xml", "text/xml", "text/javascript", "text/json"])
  2802. && dojo.lang.inArray(kwArgs["method"].toLowerCase(), ["post", "get", "head"])
  2803. && !( kwArgs["formNode"] && dojo.io.formHasFile(kwArgs["formNode"]) );
  2804. }
  2805. this.multipartBoundary = "45309FFF-BD65-4d50-99C9-36986896A96F"; // unique guid as a boundary value for multipart posts
  2806. this.bind = function(kwArgs){
  2807. if(!kwArgs["url"]){
  2808. // are we performing a history action?
  2809. if( !kwArgs["formNode"]
  2810. && (kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"] || kwArgs["watchForURL"])
  2811. && (!djConfig.preventBackButtonFix)) {
  2812. this.addToHistory(kwArgs);
  2813. return true;
  2814. }
  2815. }
  2816. // build this first for cache purposes
  2817. var url = kwArgs.url;
  2818. var query = "";
  2819. if(kwArgs["formNode"]){
  2820. var ta = kwArgs.formNode.getAttribute("action");
  2821. if((ta)&&(!kwArgs["url"])){ url = ta; }
  2822. var tp = kwArgs.formNode.getAttribute("method");
  2823. if((tp)&&(!kwArgs["method"])){ kwArgs.method = tp; }
  2824. query += dojo.io.encodeForm(kwArgs.formNode, kwArgs.encoding);
  2825. }
  2826. if(url.indexOf("#") > -1) {
  2827. dojo.debug("Warning: dojo.io.bind: stripping hash values from url:", url);
  2828. url = url.split("#")[0];
  2829. }
  2830. if(kwArgs["file"]){
  2831. // force post for file transfer
  2832. kwArgs.method = "post";
  2833. }
  2834. if(!kwArgs["method"]){
  2835. kwArgs.method = "get";
  2836. }
  2837. // guess the multipart value
  2838. if(kwArgs.method.toLowerCase() == "get"){
  2839. // GET cannot use multipart
  2840. kwArgs.multipart = false;
  2841. }else{
  2842. if(kwArgs["file"]){
  2843. // enforce multipart when sending files
  2844. kwArgs.multipart = true;
  2845. }else if(!kwArgs["multipart"]){
  2846. // default
  2847. kwArgs.multipart = false;
  2848. }
  2849. }
  2850. if(kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"]){
  2851. this.addToHistory(kwArgs);
  2852. }
  2853. do { // break-block
  2854. if(kwArgs.postContent){
  2855. query = kwArgs.postContent;
  2856. break;
  2857. }
  2858. if(kwArgs["content"]) {
  2859. query += dojo.io.argsFromMap(kwArgs.content, kwArgs.encoding);
  2860. }
  2861. if(kwArgs.method.toLowerCase() == "get" || !kwArgs.multipart){
  2862. break;
  2863. }
  2864. var t = [];
  2865. if(query.length){
  2866. var q = query.split("&");
  2867. for(var i = 0; i < q.length; ++i){
  2868. if(q[i].length){
  2869. var p = q[i].split("=");
  2870. t.push( "--" + this.multipartBoundary,
  2871. "Content-Disposition: form-data; name=\"" + p[0] + "\"",
  2872. "",
  2873. p[1]);
  2874. }
  2875. }
  2876. }
  2877. if(kwArgs.file){
  2878. if(dojo.lang.isArray(kwArgs.file)){
  2879. for(var i = 0; i < kwArgs.file.length; ++i){
  2880. var o = kwArgs.file[i];
  2881. t.push( "--" + this.multipartBoundary,
  2882. "Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
  2883. "Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
  2884. "",
  2885. o.content);
  2886. }
  2887. }else{
  2888. var o = kwArgs.file;
  2889. t.push( "--" + this.multipartBoundary,
  2890. "Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
  2891. "Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
  2892. "",
  2893. o.content);
  2894. }
  2895. }
  2896. if(t.length){
  2897. t.push("--"+this.multipartBoundary+"--", "");
  2898. query = t.join("\r\n");
  2899. }
  2900. }while(false);
  2901. // kwArgs.Connection = "close";
  2902. var async = kwArgs["sync"] ? false : true;
  2903. var preventCache = kwArgs["preventCache"] ||
  2904. (this.preventCache == true && kwArgs["preventCache"] != false);
  2905. var useCache = kwArgs["useCache"] == true ||
  2906. (this.useCache == true && kwArgs["useCache"] != false );
  2907. // preventCache is browser-level (add query string junk), useCache
  2908. // is for the local cache. If we say preventCache, then don't attempt
  2909. // to look in the cache, but if useCache is true, we still want to cache
  2910. // the response
  2911. if(!preventCache && useCache){
  2912. var cachedHttp = getFromCache(url, query, kwArgs.method);
  2913. if(cachedHttp){
  2914. doLoad(kwArgs, cachedHttp, url, query, false);
  2915. return;
  2916. }
  2917. }
  2918. // much of this is from getText, but reproduced here because we need
  2919. // more flexibility
  2920. var http = dojo.hostenv.getXmlhttpObject();
  2921. var received = false;
  2922. // build a handler function that calls back to the handler obj
  2923. if(async){
  2924. // FIXME: setting up this callback handler leaks on IE!!!
  2925. this.inFlight.push({
  2926. "req": kwArgs,
  2927. "http": http,
  2928. "url": url,
  2929. "query": query,
  2930. "useCache": useCache
  2931. });
  2932. this.startWatchingInFlight();
  2933. }
  2934. if(kwArgs.method.toLowerCase() == "post"){
  2935. // FIXME: need to hack in more flexible Content-Type setting here!
  2936. http.open("POST", url, async);
  2937. setHeaders(http, kwArgs);
  2938. http.setRequestHeader("Content-Type", kwArgs.multipart ? ("multipart/form-data; boundary=" + this.multipartBoundary) :
  2939. (kwArgs.contentType || "application/x-www-form-urlencoded"));
  2940. http.send(query);
  2941. }else{
  2942. var tmpUrl = url;
  2943. if(query != "") {
  2944. tmpUrl += (tmpUrl.indexOf("?") > -1 ? "&" : "?") + query;
  2945. }
  2946. if(preventCache) {
  2947. tmpUrl += (dojo.string.endsWithAny(tmpUrl, "?", "&")
  2948. ? "" : (tmpUrl.indexOf("?") > -1 ? "&" : "?")) + "dojo.preventCache=" + new Date().valueOf();
  2949. }
  2950. http.open(kwArgs.method.toUpperCase(), tmpUrl, async);
  2951. setHeaders(http, kwArgs);
  2952. http.send(null);
  2953. }
  2954. if( !async ) {
  2955. doLoad(kwArgs, http, url, query, useCache);
  2956. }
  2957. kwArgs.abort = function(){
  2958. return http.abort();
  2959. }
  2960. return;
  2961. }
  2962. dojo.io.transports.addTransport("XMLHTTPTransport");
  2963. }
  2964. dojo.require("dojo.lang");
  2965. dojo.provide("dojo.event");
  2966. dojo.event = new function(){
  2967. this.canTimeout = dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
  2968. this.createFunctionPair = function(obj, cb) {
  2969. var ret = [];
  2970. if(typeof obj == "function"){
  2971. ret[1] = dojo.lang.nameAnonFunc(obj, dj_global);
  2972. ret[0] = dj_global;
  2973. return ret;
  2974. }else if((typeof obj == "object")&&(typeof cb == "string")){
  2975. return [obj, cb];
  2976. }else if((typeof obj == "object")&&(typeof cb == "function")){
  2977. ret[1] = dojo.lang.nameAnonFunc(cb, obj);
  2978. ret[0] = obj;
  2979. return ret;
  2980. }
  2981. return null;
  2982. }
  2983. // FIXME: where should we put this method (not here!)?
  2984. function interpolateArgs(args){
  2985. var ao = {
  2986. srcObj: dj_global,
  2987. srcFunc: null,
  2988. adviceObj: dj_global,
  2989. adviceFunc: null,
  2990. aroundObj: null,
  2991. aroundFunc: null,
  2992. adviceType: (args.length>2) ? args[0] : "after",
  2993. precedence: "last",
  2994. once: false,
  2995. delay: null,
  2996. rate: 0,
  2997. adviceMsg: false
  2998. };
  2999. switch(args.length){
  3000. case 0: return;
  3001. case 1: return;
  3002. case 2:
  3003. ao.srcFunc = args[0];
  3004. ao.adviceFunc = args[1];
  3005. break;
  3006. case 3:
  3007. if((typeof args[0] == "object")&&(typeof args[1] == "string")&&(typeof args[2] == "string")){
  3008. ao.adviceType = "after";
  3009. ao.srcObj = args[0];
  3010. ao.srcFunc = args[1];
  3011. ao.adviceFunc = args[2];
  3012. }else if((typeof args[1] == "string")&&(typeof args[2] == "string")){
  3013. ao.srcFunc = args[1];
  3014. ao.adviceFunc = args[2];
  3015. }else if((typeof args[0] == "object")&&(typeof args[1] == "string")&&(typeof args[2] == "function")){
  3016. ao.adviceType = "after";
  3017. ao.srcObj = args[0];
  3018. ao.srcFunc = args[1];
  3019. var tmpName = dojo.lang.nameAnonFunc(args[2], ao.adviceObj);
  3020. ao.adviceObj[tmpName] = args[2];
  3021. ao.adviceFunc = tmpName;
  3022. }else if((typeof args[0] == "function")&&(typeof args[1] == "object")&&(typeof args[2] == "string")){
  3023. ao.adviceType = "after";
  3024. ao.srcObj = dj_global;
  3025. var tmpName = dojo.lang.nameAnonFunc(args[0], ao.srcObj);
  3026. ao.srcObj[tmpName] = args[0];
  3027. ao.srcFunc = tmpName;
  3028. ao.adviceObj = args[1];
  3029. ao.adviceFunc = args[2];
  3030. }
  3031. break;
  3032. case 4:
  3033. if((typeof args[0] == "object")&&(typeof args[2] == "object")){
  3034. // we can assume that we've got an old-style "connect" from
  3035. // the sigslot school of event attachment. We therefore
  3036. // assume after-advice.
  3037. ao.adviceType = "after";
  3038. ao.srcObj = args[0];
  3039. ao.srcFunc = args[1];
  3040. ao.adviceObj = args[2];
  3041. ao.adviceFunc = args[3];
  3042. }else if((typeof args[1]).toLowerCase() == "object"){
  3043. ao.srcObj = args[1];
  3044. ao.srcFunc = args[2];
  3045. ao.adviceObj = dj_global;
  3046. ao.adviceFunc = args[3];
  3047. }else if((typeof args[2]).toLowerCase() == "object"){
  3048. ao.srcObj = dj_global;
  3049. ao.srcFunc = args[1];
  3050. ao.adviceObj = args[2];
  3051. ao.adviceFunc = args[3];
  3052. }else{
  3053. ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
  3054. ao.srcFunc = args[1];
  3055. ao.adviceFunc = args[2];
  3056. ao.aroundFunc = args[3];
  3057. }
  3058. break;
  3059. case 6:
  3060. ao.srcObj = args[1];
  3061. ao.srcFunc = args[2];
  3062. ao.adviceObj = args[3]
  3063. ao.adviceFunc = args[4];
  3064. ao.aroundFunc = args[5];
  3065. ao.aroundObj = dj_global;
  3066. break;
  3067. default:
  3068. ao.srcObj = args[1];
  3069. ao.srcFunc = args[2];
  3070. ao.adviceObj = args[3]
  3071. ao.adviceFunc = args[4];
  3072. ao.aroundObj = args[5];
  3073. ao.aroundFunc = args[6];
  3074. ao.once = args[7];
  3075. ao.delay = args[8];
  3076. ao.rate = args[9];
  3077. ao.adviceMsg = args[10];
  3078. break;
  3079. }
  3080. if((typeof ao.srcFunc).toLowerCase() != "string"){
  3081. ao.srcFunc = dojo.lang.getNameInObj(ao.srcObj, ao.srcFunc);
  3082. }
  3083. if((typeof ao.adviceFunc).toLowerCase() != "string"){
  3084. ao.adviceFunc = dojo.lang.getNameInObj(ao.adviceObj, ao.adviceFunc);
  3085. }
  3086. if((ao.aroundObj)&&((typeof ao.aroundFunc).toLowerCase() != "string")){
  3087. ao.aroundFunc = dojo.lang.getNameInObj(ao.aroundObj, ao.aroundFunc);
  3088. }
  3089. if(!ao.srcObj){
  3090. dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
  3091. }
  3092. if(!ao.adviceObj){
  3093. dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
  3094. }
  3095. return ao;
  3096. }
  3097. this.connect = function(){
  3098. var ao = interpolateArgs(arguments);
  3099. // FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
  3100. var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
  3101. if(ao.adviceFunc){
  3102. var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
  3103. }
  3104. mjp.kwAddAdvice(ao);
  3105. return mjp; // advanced users might want to fsck w/ the join point
  3106. // manually
  3107. }
  3108. this.connectBefore = function() {
  3109. var args = ["before"];
  3110. for(var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }
  3111. return this.connect.apply(this, args);
  3112. }
  3113. this.connectAround = function() {
  3114. var args = ["around"];
  3115. for(var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }
  3116. return this.connect.apply(this, args);
  3117. }
  3118. this._kwConnectImpl = function(kwArgs, disconnect){
  3119. var fn = (disconnect) ? "disconnect" : "connect";
  3120. if(typeof kwArgs["srcFunc"] == "function"){
  3121. kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
  3122. var tmpName = dojo.lang.nameAnonFunc(kwArgs.srcFunc, kwArgs.srcObj);
  3123. kwArgs.srcFunc = tmpName;
  3124. }
  3125. if(typeof kwArgs["adviceFunc"] == "function"){
  3126. kwArgs.adviceObj = kwArgs["adviceObj"]||dj_global;
  3127. var tmpName = dojo.lang.nameAnonFunc(kwArgs.adviceFunc, kwArgs.adviceObj);
  3128. kwArgs.adviceFunc = tmpName;
  3129. }
  3130. return dojo.event[fn]( (kwArgs["type"]||kwArgs["adviceType"]||"after"),
  3131. kwArgs["srcObj"]||dj_global,
  3132. kwArgs["srcFunc"],
  3133. kwArgs["adviceObj"]||kwArgs["targetObj"]||dj_global,
  3134. kwArgs["adviceFunc"]||kwArgs["targetFunc"],
  3135. kwArgs["aroundObj"],
  3136. kwArgs["aroundFunc"],
  3137. kwArgs["once"],
  3138. kwArgs["delay"],
  3139. kwArgs["rate"],
  3140. kwArgs["adviceMsg"]||false );
  3141. }
  3142. this.kwConnect = function(kwArgs){
  3143. return this._kwConnectImpl(kwArgs, false);
  3144. }
  3145. this.disconnect = function(){
  3146. var ao = interpolateArgs(arguments);
  3147. if(!ao.adviceFunc){ return; } // nothing to disconnect
  3148. var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
  3149. return mjp.removeAdvice(ao.adviceObj, ao.adviceFunc, ao.adviceType, ao.once);
  3150. }
  3151. this.kwDisconnect = function(kwArgs){
  3152. return this._kwConnectImpl(kwArgs, true);
  3153. }
  3154. }
  3155. // exactly one of these is created whenever a method with a joint point is run,
  3156. // if there is at least one 'around' advice.
  3157. dojo.event.MethodInvocation = function(join_point, obj, args) {
  3158. this.jp_ = join_point;
  3159. this.object = obj;
  3160. this.args = [];
  3161. for(var x=0; x<args.length; x++){
  3162. this.args[x] = args[x];
  3163. }
  3164. // the index of the 'around' that is currently being executed.
  3165. this.around_index = -1;
  3166. }
  3167. dojo.event.MethodInvocation.prototype.proceed = function() {
  3168. this.around_index++;
  3169. if(this.around_index >= this.jp_.around.length){
  3170. return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
  3171. // return this.jp_.run_before_after(this.object, this.args);
  3172. }else{
  3173. var ti = this.jp_.around[this.around_index];
  3174. var mobj = ti[0]||dj_global;
  3175. var meth = ti[1];
  3176. return mobj[meth].call(mobj, this);
  3177. }
  3178. }
  3179. dojo.event.MethodJoinPoint = function(obj, methname){
  3180. this.object = obj||dj_global;
  3181. this.methodname = methname;
  3182. this.methodfunc = this.object[methname];
  3183. this.before = [];
  3184. this.after = [];
  3185. this.around = [];
  3186. }
  3187. dojo.event.MethodJoinPoint.getForMethod = function(obj, methname) {
  3188. // if(!(methname in obj)){
  3189. if(!obj){ obj = dj_global; }
  3190. if(!obj[methname]){
  3191. // supply a do-nothing method implementation
  3192. obj[methname] = function(){};
  3193. }else if((!dojo.lang.isFunction(obj[methname]))&&(!dojo.lang.isAlien(obj[methname]))){
  3194. return null; // FIXME: should we throw an exception here instead?
  3195. }
  3196. // we hide our joinpoint instance in obj[methname + '$joinpoint']
  3197. var jpname = methname + "$joinpoint";
  3198. var jpfuncname = methname + "$joinpoint$method";
  3199. var joinpoint = obj[jpname];
  3200. if(!joinpoint){
  3201. var isNode = false;
  3202. if(dojo.event["browser"]){
  3203. if( (obj["attachEvent"])||
  3204. (obj["nodeType"])||
  3205. (obj["addEventListener"]) ){
  3206. isNode = true;
  3207. dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, methname]);
  3208. }
  3209. }
  3210. obj[jpfuncname] = obj[methname];
  3211. // joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, methname);
  3212. joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
  3213. obj[methname] = function(){
  3214. var args = [];
  3215. if((isNode)&&(!arguments.length)&&(window.event)){
  3216. args.push(dojo.event.browser.fixEvent(window.event));
  3217. }else{
  3218. for(var x=0; x<arguments.length; x++){
  3219. if((x==0)&&(isNode)&&(dojo.event.browser.isEvent(arguments[x]))){
  3220. args.push(dojo.event.browser.fixEvent(arguments[x]));
  3221. }else{
  3222. args.push(arguments[x]);
  3223. }
  3224. }
  3225. }
  3226. // return joinpoint.run.apply(joinpoint, arguments);
  3227. return joinpoint.run.apply(joinpoint, args);
  3228. }
  3229. }
  3230. return joinpoint;
  3231. }
  3232. dojo.lang.extend(dojo.event.MethodJoinPoint, {
  3233. unintercept: function() {
  3234. this.object[this.methodname] = this.methodfunc;
  3235. },
  3236. run: function() {
  3237. var obj = this.object||dj_global;
  3238. var args = arguments;
  3239. // optimization. We only compute once the array version of the arguments
  3240. // pseudo-arr in order to prevent building it each time advice is unrolled.
  3241. var aargs = [];
  3242. for(var x=0; x<args.length; x++){
  3243. aargs[x] = args[x];
  3244. }
  3245. var unrollAdvice = function(marr){
  3246. if(!marr){
  3247. dojo.debug("Null argument to unrollAdvice()");
  3248. return;
  3249. }
  3250. var callObj = marr[0]||dj_global;
  3251. var callFunc = marr[1];
  3252. if(!callObj[callFunc]){
  3253. dojo.raise("function \"" + callFunc + "\" does not exist on \"" + callObj + "\"");
  3254. }
  3255. var aroundObj = marr[2]||dj_global;
  3256. var aroundFunc = marr[3];
  3257. var msg = marr[6];
  3258. var undef;
  3259. var to = {
  3260. args: [],
  3261. jp_: this,
  3262. object: obj,
  3263. proceed: function(){
  3264. return callObj[callFunc].apply(callObj, to.args);
  3265. }
  3266. };
  3267. to.args = aargs;
  3268. var delay = parseInt(marr[4]);
  3269. var hasDelay = ((!isNaN(delay))&&(marr[4]!==null)&&(typeof marr[4] != "undefined"));
  3270. if(marr[5]){
  3271. var rate = parseInt(marr[5]);
  3272. var cur = new Date();
  3273. var timerSet = false;
  3274. if((marr["last"])&&((cur-marr.last)<=rate)){
  3275. if(dojo.event.canTimeout){
  3276. if(marr["delayTimer"]){
  3277. clearTimeout(marr.delayTimer);
  3278. }
  3279. var tod = parseInt(rate*2); // is rate*2 naive?
  3280. var mcpy = dojo.lang.shallowCopy(marr);
  3281. marr.delayTimer = setTimeout(function(){
  3282. // FIXME: on IE at least, event objects from the
  3283. // browser can go out of scope. How (or should?) we
  3284. // deal with it?
  3285. mcpy[5] = 0;
  3286. unrollAdvice(mcpy);
  3287. }, tod);
  3288. }
  3289. return;
  3290. }else{
  3291. marr.last = cur;
  3292. }
  3293. }
  3294. // FIXME: need to enforce rates for a connection here!
  3295. if(aroundFunc){
  3296. // NOTE: around advice can't delay since we might otherwise depend
  3297. // on execution order!
  3298. aroundObj[aroundFunc].call(aroundObj, to);
  3299. }else{
  3300. // var tmjp = dojo.event.MethodJoinPoint.getForMethod(obj, methname);
  3301. if((hasDelay)&&((dojo.render.html)||(dojo.render.svg))){ // FIXME: the render checks are grotty!
  3302. dj_global["setTimeout"](function(){
  3303. if(msg){
  3304. callObj[callFunc].call(callObj, to);
  3305. }else{
  3306. callObj[callFunc].apply(callObj, args);
  3307. }
  3308. }, delay);
  3309. }else{ // many environments can't support delay!
  3310. if(msg){
  3311. callObj[callFunc].call(callObj, to);
  3312. }else{
  3313. callObj[callFunc].apply(callObj, args);
  3314. }
  3315. }
  3316. }
  3317. }
  3318. if(this.before.length>0){
  3319. dojo.lang.forEach(this.before, unrollAdvice, true);
  3320. }
  3321. var result;
  3322. if(this.around.length>0){
  3323. var mi = new dojo.event.MethodInvocation(this, obj, args);
  3324. result = mi.proceed();
  3325. }else if(this.methodfunc){
  3326. result = this.object[this.methodname].apply(this.object, args);
  3327. }
  3328. if(this.after.length>0){
  3329. dojo.lang.forEach(this.after, unrollAdvice, true);
  3330. }
  3331. return (this.methodfunc) ? result : null;
  3332. },
  3333. getArr: function(kind){
  3334. var arr = this.after;
  3335. // FIXME: we should be able to do this through props or Array.in()
  3336. if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
  3337. arr = this.before;
  3338. }else if(kind=="around"){
  3339. arr = this.around;
  3340. }
  3341. return arr;
  3342. },
  3343. kwAddAdvice: function(args){
  3344. this.addAdvice( args["adviceObj"], args["adviceFunc"],
  3345. args["aroundObj"], args["aroundFunc"],
  3346. args["adviceType"], args["precedence"],
  3347. args["once"], args["delay"], args["rate"],
  3348. args["adviceMsg"]);
  3349. },
  3350. addAdvice: function( thisAdviceObj, thisAdvice,
  3351. thisAroundObj, thisAround,
  3352. advice_kind, precedence,
  3353. once, delay, rate, asMessage){
  3354. var arr = this.getArr(advice_kind);
  3355. if(!arr){
  3356. dojo.raise("bad this: " + this);
  3357. }
  3358. var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage];
  3359. if(once){
  3360. if(this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr) >= 0){
  3361. return;
  3362. }
  3363. }
  3364. if(precedence == "first"){
  3365. arr.unshift(ao);
  3366. }else{
  3367. arr.push(ao);
  3368. }
  3369. },
  3370. hasAdvice: function(thisAdviceObj, thisAdvice, advice_kind, arr){
  3371. if(!arr){ arr = this.getArr(advice_kind); }
  3372. var ind = -1;
  3373. for(var x=0; x<arr.length; x++){
  3374. if((arr[x][0] == thisAdviceObj)&&(arr[x][1] == thisAdvice)){
  3375. ind = x;
  3376. }
  3377. }
  3378. return ind;
  3379. },
  3380. removeAdvice: function(thisAdviceObj, thisAdvice, advice_kind, once){
  3381. var arr = this.getArr(advice_kind);
  3382. var ind = this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr);
  3383. if(ind == -1){
  3384. return false;
  3385. }
  3386. while(ind != -1){
  3387. arr.splice(ind, 1);
  3388. if(once){ break; }
  3389. ind = this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr);
  3390. }
  3391. return true;
  3392. }
  3393. });
  3394. dojo.require("dojo.event");
  3395. dojo.provide("dojo.event.topic");
  3396. dojo.event.topic = new function(){
  3397. this.topics = {};
  3398. this.getTopic = function(topicName){
  3399. if(!this.topics[topicName]){
  3400. this.topics[topicName] = new this.TopicImpl(topicName);
  3401. }
  3402. return this.topics[topicName];
  3403. }
  3404. this.registerPublisher = function(topic, obj, funcName){
  3405. var topic = this.getTopic(topic);
  3406. topic.registerPublisher(obj, funcName);
  3407. }
  3408. this.subscribe = function(topic, obj, funcName){
  3409. var topic = this.getTopic(topic);
  3410. topic.subscribe(obj, funcName);
  3411. }
  3412. this.unsubscribe = function(topic, obj, funcName){
  3413. var topic = this.getTopic(topic);
  3414. topic.unsubscribe(obj, funcName);
  3415. }
  3416. this.publish = function(topic, message){
  3417. var topic = this.getTopic(topic);
  3418. // if message is an array, we treat it as a set of arguments,
  3419. // otherwise, we just pass on the arguments passed in as-is
  3420. var args = [];
  3421. if((arguments.length == 2)&&(message.length)&&(typeof message != "string")){
  3422. args = message;
  3423. }else{
  3424. var args = [];
  3425. for(var x=1; x<arguments.length; x++){
  3426. args.push(arguments[x]);
  3427. }
  3428. }
  3429. topic.sendMessage.apply(topic, args);
  3430. }
  3431. }
  3432. dojo.event.topic.TopicImpl = function(topicName){
  3433. this.topicName = topicName;
  3434. var self = this;
  3435. self.subscribe = function(listenerObject, listenerMethod){
  3436. dojo.event.connect("before", self, "sendMessage", listenerObject, listenerMethod);
  3437. }
  3438. self.unsubscribe = function(listenerObject, listenerMethod){
  3439. dojo.event.disconnect("before", self, "sendMessage", listenerObject, listenerMethod);
  3440. }
  3441. self.registerPublisher = function(publisherObject, publisherMethod){
  3442. dojo.event.connect(publisherObject, publisherMethod, self, "sendMessage");
  3443. }
  3444. self.sendMessage = function(message){
  3445. // The message has been propagated
  3446. }
  3447. }
  3448. dojo.provide("dojo.event.browser");
  3449. dojo.require("dojo.event");
  3450. dojo_ie_clobber = new function(){
  3451. this.clobberNodes = [];
  3452. function nukeProp(node, prop){
  3453. // try{ node.removeAttribute(prop); }catch(e){ /* squelch */ }
  3454. try{ node[prop] = null; }catch(e){ /* squelch */ }
  3455. try{ delete node[prop]; }catch(e){ /* squelch */ }
  3456. // FIXME: JotLive needs this, but I'm not sure if it's too slow or not
  3457. try{ node.removeAttribute(prop); }catch(e){ /* squelch */ }
  3458. }
  3459. this.clobber = function(nodeRef){
  3460. var na;
  3461. var tna;
  3462. if(nodeRef){
  3463. tna = nodeRef.getElementsByTagName("*");
  3464. na = [nodeRef];
  3465. for(var x=0; x<tna.length; x++){
  3466. // if we're gonna be clobbering the thing, at least make sure
  3467. // we aren't trying to do it twice
  3468. if(tna[x]["__doClobber__"]){
  3469. na.push(tna[x]);
  3470. }
  3471. }
  3472. }else{
  3473. try{ window.onload = null; }catch(e){}
  3474. na = (this.clobberNodes.length) ? this.clobberNodes : document.all;
  3475. }
  3476. tna = null;
  3477. var basis = {};
  3478. for(var i = na.length-1; i>=0; i=i-1){
  3479. var el = na[i];
  3480. if(el["__clobberAttrs__"]){
  3481. for(var j=0; j<el.__clobberAttrs__.length; j++){
  3482. nukeProp(el, el.__clobberAttrs__[j]);
  3483. }
  3484. nukeProp(el, "__clobberAttrs__");
  3485. nukeProp(el, "__doClobber__");
  3486. }
  3487. }
  3488. na = null;
  3489. }
  3490. }
  3491. if(dojo.render.html.ie){
  3492. window.onunload = function(){
  3493. dojo_ie_clobber.clobber();
  3494. try{
  3495. if((dojo["widget"])&&(dojo.widget["manager"])){
  3496. dojo.widget.manager.destroyAll();
  3497. }
  3498. }catch(e){}
  3499. try{ window.onload = null; }catch(e){}
  3500. try{ window.onunload = null; }catch(e){}
  3501. dojo_ie_clobber.clobberNodes = [];
  3502. // CollectGarbage();
  3503. }
  3504. }
  3505. dojo.event.browser = new function(){
  3506. var clobberIdx = 0;
  3507. this.clean = function(node){
  3508. if(dojo.render.html.ie){
  3509. dojo_ie_clobber.clobber(node);
  3510. }
  3511. }
  3512. this.addClobberNode = function(node){
  3513. if(!node["__doClobber__"]){
  3514. node.__doClobber__ = true;
  3515. dojo_ie_clobber.clobberNodes.push(node);
  3516. // this might not be the most efficient thing to do, but it's
  3517. // much less error prone than other approaches which were
  3518. // previously tried and failed
  3519. node.__clobberAttrs__ = [];
  3520. }
  3521. }
  3522. this.addClobberNodeAttrs = function(node, props){
  3523. this.addClobberNode(node);
  3524. for(var x=0; x<props.length; x++){
  3525. node.__clobberAttrs__.push(props[x]);
  3526. }
  3527. }
  3528. this.removeListener = function(node, evtName, fp, capture){
  3529. if(!capture){ var capture = false; }
  3530. evtName = evtName.toLowerCase();
  3531. if(evtName.substr(0,2)=="on"){ evtName = evtName.substr(2); }
  3532. // FIXME: this is mostly a punt, we aren't actually doing anything on IE
  3533. if(node.removeEventListener){
  3534. node.removeEventListener(evtName, fp, capture);
  3535. }
  3536. }
  3537. this.addListener = function(node, evtName, fp, capture, dontFix){
  3538. if(!node){ return; } // FIXME: log and/or bail?
  3539. if(!capture){ var capture = false; }
  3540. evtName = evtName.toLowerCase();
  3541. if(evtName.substr(0,2)!="on"){ evtName = "on"+evtName; }
  3542. if(!dontFix){
  3543. // build yet another closure around fp in order to inject fixEvent
  3544. // around the resulting event
  3545. var newfp = function(evt){
  3546. if(!evt){ evt = window.event; }
  3547. var ret = fp(dojo.event.browser.fixEvent(evt));
  3548. if(capture){
  3549. dojo.event.browser.stopEvent(evt);
  3550. }
  3551. return ret;
  3552. }
  3553. }else{
  3554. newfp = fp;
  3555. }
  3556. if(node.addEventListener){
  3557. node.addEventListener(evtName.substr(2), newfp, capture);
  3558. return newfp;
  3559. }else{
  3560. if(typeof node[evtName] == "function" ){
  3561. var oldEvt = node[evtName];
  3562. node[evtName] = function(e){
  3563. oldEvt(e);
  3564. return newfp(e);
  3565. }
  3566. }else{
  3567. node[evtName]=newfp;
  3568. }
  3569. if(dojo.render.html.ie){
  3570. this.addClobberNodeAttrs(node, [evtName]);
  3571. }
  3572. return newfp;
  3573. }
  3574. }
  3575. this.isEvent = function(obj){
  3576. // FIXME: event detection hack ... could test for additional attributes
  3577. // if necessary
  3578. return (typeof Event != "undefined")&&(obj.eventPhase);
  3579. // Event does not support instanceof in Opera, otherwise:
  3580. //return (typeof Event != "undefined")&&(obj instanceof Event);
  3581. }
  3582. this.currentEvent = null;
  3583. this.callListener = function(listener, curTarget){
  3584. if(typeof listener != 'function'){
  3585. dojo.raise("listener not a function: " + listener);
  3586. }
  3587. dojo.event.browser.currentEvent.currentTarget = curTarget;
  3588. return listener.call(curTarget, dojo.event.browser.currentEvent);
  3589. }
  3590. this.stopPropagation = function(){
  3591. dojo.event.browser.currentEvent.cancelBubble = true;
  3592. }
  3593. this.preventDefault = function(){
  3594. dojo.event.browser.currentEvent.returnValue = false;
  3595. }
  3596. this.keys = {
  3597. KEY_BACKSPACE: 8,
  3598. KEY_TAB: 9,
  3599. KEY_ENTER: 13,
  3600. KEY_SHIFT: 16,
  3601. KEY_CTRL: 17,
  3602. KEY_ALT: 18,
  3603. KEY_PAUSE: 19,
  3604. KEY_CAPS_LOCK: 20,
  3605. KEY_ESCAPE: 27,
  3606. KEY_SPACE: 32,
  3607. KEY_PAGE_UP: 33,
  3608. KEY_PAGE_DOWN: 34,
  3609. KEY_END: 35,
  3610. KEY_HOME: 36,
  3611. KEY_LEFT_ARROW: 37,
  3612. KEY_UP_ARROW: 38,
  3613. KEY_RIGHT_ARROW: 39,
  3614. KEY_DOWN_ARROW: 40,
  3615. KEY_INSERT: 45,
  3616. KEY_DELETE: 46,
  3617. KEY_LEFT_WINDOW: 91,
  3618. KEY_RIGHT_WINDOW: 92,
  3619. KEY_SELECT: 93,
  3620. KEY_F1: 112,
  3621. KEY_F2: 113,
  3622. KEY_F3: 114,
  3623. KEY_F4: 115,
  3624. KEY_F5: 116,
  3625. KEY_F6: 117,
  3626. KEY_F7: 118,
  3627. KEY_F8: 119,
  3628. KEY_F9: 120,
  3629. KEY_F10: 121,
  3630. KEY_F11: 122,
  3631. KEY_F12: 123,
  3632. KEY_NUM_LOCK: 144,
  3633. KEY_SCROLL_LOCK: 145
  3634. };
  3635. // reverse lookup
  3636. this.revKeys = [];
  3637. for(var key in this.keys){
  3638. this.revKeys[this.keys[key]] = key;
  3639. }
  3640. this.fixEvent = function(evt){
  3641. if((!evt)&&(window["event"])){
  3642. var evt = window.event;
  3643. }
  3644. if((evt["type"])&&(evt["type"].indexOf("key") == 0)){ // key events
  3645. evt.keys = this.revKeys;
  3646. // FIXME: how can we eliminate this iteration?
  3647. for(var key in this.keys) {
  3648. evt[key] = this.keys[key];
  3649. }
  3650. if((dojo.render.html.ie)&&(evt["type"] == "keypress")){
  3651. evt.charCode = evt.keyCode;
  3652. }
  3653. }
  3654. if(dojo.render.html.ie){
  3655. if(!evt.target){ evt.target = evt.srcElement; }
  3656. if(!evt.currentTarget){ evt.currentTarget = evt.srcElement; }
  3657. if(!evt.layerX){ evt.layerX = evt.offsetX; }
  3658. if(!evt.layerY){ evt.layerY = evt.offsetY; }
  3659. // mouseover
  3660. if(evt.fromElement){ evt.relatedTarget = evt.fromElement; }
  3661. // mouseout
  3662. if(evt.toElement){ evt.relatedTarget = evt.toElement; }
  3663. this.currentEvent = evt;
  3664. evt.callListener = this.callListener;
  3665. evt.stopPropagation = this.stopPropagation;
  3666. evt.preventDefault = this.preventDefault;
  3667. }
  3668. return evt;
  3669. }
  3670. this.stopEvent = function(ev) {
  3671. if(window.event){
  3672. ev.returnValue = false;
  3673. ev.cancelBubble = true;
  3674. }else{
  3675. ev.preventDefault();
  3676. ev.stopPropagation();
  3677. }
  3678. }
  3679. }
  3680. dojo.hostenv.conditionalLoadModule({
  3681. common: ["dojo.event", "dojo.event.topic"],
  3682. browser: ["dojo.event.browser"]
  3683. });
  3684. dojo.hostenv.moduleLoaded("dojo.event.*");
  3685. dojo.provide("dojo.alg.Alg");
  3686. dojo.require("dojo.lang");
  3687. dj_deprecated("dojo.alg.Alg is deprecated, use dojo.lang instead");
  3688. dojo.alg.find = function(arr, val){ return dojo.lang.find(arr, val); }
  3689. dojo.alg.inArray = function(arr, val){
  3690. return dojo.lang.inArray(arr, val);
  3691. }
  3692. dojo.alg.inArr = dojo.alg.inArray; // for backwards compatibility
  3693. dojo.alg.getNameInObj = function(ns, item){
  3694. return dojo.lang.getNameInObj(ns, item);
  3695. }
  3696. // is this the right place for this?
  3697. dojo.alg.has = function(obj, name){
  3698. return dojo.lang.has(obj, name);
  3699. }
  3700. dojo.alg.forEach = function(arr, unary_func, fix_length){
  3701. return dojo.lang.forEach(arr, unary_func, fix_length);
  3702. }
  3703. dojo.alg.for_each = dojo.alg.forEach; // burst compat
  3704. dojo.alg.map = function(arr, obj, unary_func){
  3705. return dojo.lang.map(arr, obj, unary_func);
  3706. }
  3707. dojo.alg.tryThese = function(){
  3708. return dojo.lang.tryThese.apply(dojo.lang, arguments);
  3709. }
  3710. dojo.alg.delayThese = function(farr, cb, delay, onend){
  3711. return dojo.lang.delayThese.apply(dojo.lang, arguments);
  3712. }
  3713. dojo.alg.for_each_call = dojo.alg.map; // burst compat
  3714. dojo.require("dojo.alg.Alg", false, true);
  3715. dojo.hostenv.moduleLoaded("dojo.alg.*");
  3716. dojo.provide("dojo.uri.Uri");
  3717. dojo.uri = new function() {
  3718. this.joinPath = function() {
  3719. // DEPRECATED: use the dojo.uri.Uri object instead
  3720. var arr = [];
  3721. for(var i = 0; i < arguments.length; i++) { arr.push(arguments[i]); }
  3722. return arr.join("/").replace(/\/{2,}/g, "/").replace(/((https*|ftps*):)/i, "$1/");
  3723. }
  3724. this.dojoUri = function (uri) {
  3725. // returns a Uri object resolved relative to the dojo root
  3726. return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
  3727. }
  3728. this.Uri = function (/*uri1, uri2, [...]*/) {
  3729. // An object representing a Uri.
  3730. // Each argument is evaluated in order relative to the next until
  3731. // a conanical uri is producued. To get an absolute Uri relative
  3732. // to the current document use
  3733. // new dojo.uri.Uri(document.baseURI, uri)
  3734. // TODO: support for IPv6, see RFC 2732
  3735. // resolve uri components relative to each other
  3736. var uri = arguments[0];
  3737. for (var i = 1; i < arguments.length; i++) {
  3738. if(!arguments[i]) { continue; }
  3739. // Safari doesn't support this.constructor so we have to be explicit
  3740. var relobj = new dojo.uri.Uri(arguments[i].toString());
  3741. var uriobj = new dojo.uri.Uri(uri.toString());
  3742. if (relobj.path == "" && relobj.scheme == null &&
  3743. relobj.authority == null && relobj.query == null) {
  3744. if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; }
  3745. relobj = uriobj;
  3746. } else if (relobj.scheme == null) {
  3747. relobj.scheme = uriobj.scheme;
  3748. if (relobj.authority == null) {
  3749. relobj.authority = uriobj.authority;
  3750. if (relobj.path.charAt(0) != "/") {
  3751. var path = uriobj.path.substring(0,
  3752. uriobj.path.lastIndexOf("/") + 1) + relobj.path;
  3753. var segs = path.split("/");
  3754. for (var j = 0; j < segs.length; j++) {
  3755. if (segs[j] == ".") {
  3756. if (j == segs.length - 1) { segs[j] = ""; }
  3757. else { segs.splice(j, 1); j--; }
  3758. } else if (j > 0 && !(j == 1 && segs[0] == "") &&
  3759. segs[j] == ".." && segs[j-1] != "..") {
  3760. if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; }
  3761. else { segs.splice(j - 1, 2); j -= 2; }
  3762. }
  3763. }
  3764. relobj.path = segs.join("/");
  3765. }
  3766. }
  3767. }
  3768. uri = "";
  3769. if (relobj.scheme != null) { uri += relobj.scheme + ":"; }
  3770. if (relobj.authority != null) { uri += "//" + relobj.authority; }
  3771. uri += relobj.path;
  3772. if (relobj.query != null) { uri += "?" + relobj.query; }
  3773. if (relobj.fragment != null) { uri += "#" + relobj.fragment; }
  3774. }
  3775. this.uri = uri.toString();
  3776. // break the uri into its main components
  3777. var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
  3778. var r = this.uri.match(new RegExp(regexp));
  3779. this.scheme = r[2] || (r[1] ? "" : null);
  3780. this.authority = r[4] || (r[3] ? "" : null);
  3781. this.path = r[5]; // can never be undefined
  3782. this.query = r[7] || (r[6] ? "" : null);
  3783. this.fragment = r[9] || (r[8] ? "" : null);
  3784. if (this.authority != null) {
  3785. // server based naming authority
  3786. regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
  3787. r = this.authority.match(new RegExp(regexp));
  3788. this.user = r[3] || null;
  3789. this.password = r[4] || null;
  3790. this.host = r[5];
  3791. this.port = r[7] || null;
  3792. }
  3793. this.toString = function(){ return this.uri; }
  3794. }
  3795. };
  3796. dojo.provide("dojo.math");
  3797. dojo.math.degToRad = function (x) { return (x*Math.PI) / 180; }
  3798. dojo.math.radToDeg = function (x) { return (x*180) / Math.PI; }
  3799. dojo.math.factorial = function (n) {
  3800. if(n<1){ return 0; }
  3801. var retVal = 1;
  3802. for(var i=1;i<=n;i++){ retVal *= i; }
  3803. return retVal;
  3804. }
  3805. //The number of ways of obtaining an ordered subset of k elements from a set of n elements
  3806. dojo.math.permutations = function (n,k) {
  3807. if(n==0 || k==0) return 1;
  3808. return (dojo.math.factorial(n) / dojo.math.factorial(n-k));
  3809. }
  3810. //The number of ways of picking n unordered outcomes from r possibilities
  3811. dojo.math.combinations = function (n,r) {
  3812. if(n==0 || r==0) return 1;
  3813. return (dojo.math.factorial(n) / (dojo.math.factorial(n-r) * dojo.math.factorial(r)));
  3814. }
  3815. dojo.math.bernstein = function (t,n,i) {
  3816. return (dojo.math.combinations(n,i) * Math.pow(t,i) * Math.pow(1-t,n-i));
  3817. }
  3818. /**
  3819. * Returns random numbers with a Gaussian distribution, with the mean set at
  3820. * 0 and the variance set at 1.
  3821. *
  3822. * @return A random number from a Gaussian distribution
  3823. */
  3824. dojo.math.gaussianRandom = function () {
  3825. var k = 2;
  3826. do {
  3827. var i = 2 * Math.random() - 1;
  3828. var j = 2 * Math.random() - 1;
  3829. k = i * i + j * j;
  3830. } while (k >= 1);
  3831. k = Math.sqrt((-2 * Math.log(k)) / k);
  3832. return i * k;
  3833. }
  3834. /**
  3835. * Calculates the mean of an Array of numbers.
  3836. *
  3837. * @return The mean of the numbers in the Array
  3838. */
  3839. dojo.math.mean = function () {
  3840. var array = dojo.lang.isArray(arguments[0]) ? arguments[0] : arguments;
  3841. var mean = 0;
  3842. for (var i = 0; i < array.length; i++) { mean += array[i]; }
  3843. return mean / array.length;
  3844. }
  3845. /**
  3846. * Extends Math.round by adding a second argument specifying the number of
  3847. * decimal places to round to.
  3848. *
  3849. * @param number The number to round
  3850. * @param places The number of decimal places to round to
  3851. * @return The rounded number
  3852. */
  3853. // TODO: add support for significant figures
  3854. dojo.math.round = function (number, places) {
  3855. if (!places) { var shift = 1; }
  3856. else { var shift = Math.pow(10, places); }
  3857. return Math.round(number * shift) / shift;
  3858. }
  3859. /**
  3860. * Calculates the standard deviation of an Array of numbers
  3861. *
  3862. * @return The standard deviation of the numbers
  3863. */
  3864. dojo.math.sd = function () {
  3865. var array = dojo.lang.isArray(arguments[0]) ? arguments[0] : arguments;
  3866. return Math.sqrt(dojo.math.variance(array));
  3867. }
  3868. /**
  3869. * Calculates the variance of an Array of numbers
  3870. *
  3871. * @return The variance of the numbers
  3872. */
  3873. dojo.math.variance = function () {
  3874. var array = dojo.lang.isArray(arguments[0]) ? arguments[0] : arguments;
  3875. var mean = 0, squares = 0;
  3876. for (var i = 0; i < array.length; i++) {
  3877. mean += array[i];
  3878. squares += Math.pow(array[i], 2);
  3879. }
  3880. return (squares / array.length)
  3881. - Math.pow(mean / array.length, 2);
  3882. }
  3883. dojo.provide("dojo.graphics.color");
  3884. dojo.require("dojo.lang");
  3885. dojo.require("dojo.string");
  3886. dojo.require("dojo.math");
  3887. // TODO: rewrite the "x2y" methods to take advantage of the parsing
  3888. // abilities of the Color object. Also, beef up the Color
  3889. // object (as possible) to parse most common formats
  3890. // takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa)
  3891. dojo.graphics.color.Color = function(r, g, b, a) {
  3892. // dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]);
  3893. if(dojo.lang.isArray(r)) {
  3894. this.r = r[0];
  3895. this.g = r[1];
  3896. this.b = r[2];
  3897. this.a = r[3]||1.0;
  3898. } else if(dojo.lang.isString(r)) {
  3899. var rgb = dojo.graphics.color.extractRGB(r);
  3900. this.r = rgb[0];
  3901. this.g = rgb[1];
  3902. this.b = rgb[2];
  3903. this.a = g||1.0;
  3904. } else if(r instanceof dojo.graphics.color.Color) {
  3905. this.r = r.r;
  3906. this.b = r.b;
  3907. this.g = r.g;
  3908. this.a = r.a;
  3909. } else {
  3910. this.r = r;
  3911. this.g = g;
  3912. this.b = b;
  3913. this.a = a;
  3914. }
  3915. }
  3916. dojo.lang.extend(dojo.graphics.color.Color, {
  3917. toRgb: function(includeAlpha) {
  3918. if(includeAlpha) {
  3919. return this.toRgba();
  3920. } else {
  3921. return [this.r, this.g, this.b];
  3922. }
  3923. },
  3924. toRgba: function() {
  3925. return [this.r, this.g, this.b, this.a];
  3926. },
  3927. toHex: function() {
  3928. return dojo.graphics.color.rgb2hex(this.toRgb());
  3929. },
  3930. toCss: function() {
  3931. return "rgb(" + this.toRgb().join() + ")";
  3932. },
  3933. toString: function() {
  3934. return this.toHex(); // decent default?
  3935. },
  3936. toHsv: function() {
  3937. return dojo.graphics.color.rgb2hsv(this.toRgb());
  3938. },
  3939. toHsl: function() {
  3940. return dojo.graphics.color.rgb2hsl(this.toRgb());
  3941. },
  3942. blend: function(color, weight) {
  3943. return dojo.graphics.color.blend(this.toRgb(), new Color(color).toRgb(), weight);
  3944. }
  3945. });
  3946. dojo.graphics.color.named = {
  3947. white: [255,255,255],
  3948. black: [0,0,0],
  3949. red: [255,0,0],
  3950. green: [0,255,0],
  3951. blue: [0,0,255],
  3952. navy: [0,0,128],
  3953. gray: [128,128,128],
  3954. silver: [192,192,192]
  3955. };
  3956. // blend colors a and b (both as RGB array or hex strings) with weight from -1 to +1, 0 being a 50/50 blend
  3957. dojo.graphics.color.blend = function(a, b, weight) {
  3958. if(typeof a == "string") { return dojo.graphics.color.blendHex(a, b, weight); }
  3959. if(!weight) { weight = 0; }
  3960. else if(weight > 1) { weight = 1; }
  3961. else if(weight < -1) { weight = -1; }
  3962. var c = new Array(3);
  3963. for(var i = 0; i < 3; i++) {
  3964. var half = Math.abs(a[i] - b[i])/2;
  3965. c[i] = Math.floor(Math.min(a[i], b[i]) + half + (half * weight));
  3966. }
  3967. return c;
  3968. }
  3969. // very convenient blend that takes and returns hex values
  3970. // (will get called automatically by blend when blend gets strings)
  3971. dojo.graphics.color.blendHex = function(a, b, weight) {
  3972. return dojo.graphics.color.rgb2hex(dojo.graphics.color.blend(dojo.graphics.color.hex2rgb(a), dojo.graphics.color.hex2rgb(b), weight));
  3973. }
  3974. // get RGB array from css-style color declarations
  3975. dojo.graphics.color.extractRGB = function(color) {
  3976. var hex = "0123456789abcdef";
  3977. color = color.toLowerCase();
  3978. if( color.indexOf("rgb") == 0 ) {
  3979. var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
  3980. var ret = matches.splice(1, 3);
  3981. return ret;
  3982. } else {
  3983. var colors = dojo.graphics.color.hex2rgb(color);
  3984. if(colors) {
  3985. return colors;
  3986. } else {
  3987. // named color (how many do we support?)
  3988. return dojo.graphics.color.named[color] || [255, 255, 255];
  3989. }
  3990. }
  3991. }
  3992. dojo.graphics.color.hex2rgb = function(hex) {
  3993. var hexNum = "0123456789ABCDEF";
  3994. var rgb = new Array(3);
  3995. if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); }
  3996. hex = hex.toUpperCase();
  3997. if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") {
  3998. return null;
  3999. }
  4000. if( hex.length == 3 ) {
  4001. rgb[0] = hex.charAt(0) + hex.charAt(0)
  4002. rgb[1] = hex.charAt(1) + hex.charAt(1)
  4003. rgb[2] = hex.charAt(2) + hex.charAt(2);
  4004. } else {
  4005. rgb[0] = hex.substring(0, 2);
  4006. rgb[1] = hex.substring(2, 4);
  4007. rgb[2] = hex.substring(4);
  4008. }
  4009. for(var i = 0; i < rgb.length; i++) {
  4010. rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1));
  4011. }
  4012. return rgb;
  4013. }
  4014. dojo.graphics.color.rgb2hex = function(r, g, b) {
  4015. if(dojo.lang.isArray(r)) {
  4016. g = r[1] || 0;
  4017. b = r[2] || 0;
  4018. r = r[0] || 0;
  4019. }
  4020. return ["#",
  4021. dojo.string.pad(r.toString(16), 2),
  4022. dojo.string.pad(g.toString(16), 2),
  4023. dojo.string.pad(b.toString(16), 2)].join("");
  4024. }
  4025. dojo.graphics.color.rgb2hsv = function(r, g, b){
  4026. if (dojo.lang.isArray(r)) {
  4027. b = r[2] || 0;
  4028. g = r[1] || 0;
  4029. r = r[0] || 0;
  4030. }
  4031. // r,g,b, each 0 to 255, to HSV.
  4032. // h = 0.0 to 360.0 (corresponding to 0..360.0 degrees around hexcone)
  4033. // s = 0.0 (shade of gray) to 1.0 (pure color)
  4034. // v = 0.0 (black) to 1.0 {white)
  4035. //
  4036. // Based on C Code in "Computer Graphics -- Principles and Practice,"
  4037. // Foley et al, 1996, p. 592.
  4038. //
  4039. // our calculatuions are based on 'regular' values (0-360, 0-1, 0-1)
  4040. // but we return bytes values (0-255, 0-255, 0-255)
  4041. var h = null;
  4042. var s = null;
  4043. var v = null;
  4044. var min = Math.min(r, g, b);
  4045. v = Math.max(r, g, b);
  4046. var delta = v - min;
  4047. // calculate saturation (0 if r, g and b are all 0)
  4048. s = (v == 0) ? 0 : delta/v;
  4049. if (s == 0){
  4050. // achromatic: when saturation is, hue is undefined
  4051. h = 0;
  4052. }else{
  4053. // chromatic
  4054. if (r == v){
  4055. // between yellow and magenta
  4056. h = 60 * (g - b) / delta;
  4057. }else{
  4058. if (g == v){
  4059. // between cyan and yellow
  4060. h = 120 + 60 * (b - r) / delta;
  4061. }else{
  4062. if (b == v){
  4063. // between magenta and cyan
  4064. h = 240 + 60 * (r - g) / delta;
  4065. }
  4066. }
  4067. }
  4068. if (h < 0){
  4069. h += 360;
  4070. }
  4071. }
  4072. h = (h == 0) ? 360 : Math.ceil((h / 360) * 255);
  4073. s = Math.ceil(s * 255);
  4074. return [h, s, v];
  4075. }
  4076. dojo.graphics.color.hsv2rgb = function(h, s, v){
  4077. if (dojo.lang.isArray(h)) {
  4078. v = h[2] || 0;
  4079. s = h[1] || 0;
  4080. h = h[0] || 0;
  4081. }
  4082. h = (h / 255) * 360;
  4083. if (h == 360){ h = 0;}
  4084. s = s / 255;
  4085. v = v / 255;
  4086. // Based on C Code in "Computer Graphics -- Principles and Practice,"
  4087. // Foley et al, 1996, p. 593.
  4088. //
  4089. // H = 0.0 to 360.0 (corresponding to 0..360 degrees around hexcone) 0 for S = 0
  4090. // S = 0.0 (shade of gray) to 1.0 (pure color)
  4091. // V = 0.0 (black) to 1.0 (white)
  4092. var r = null;
  4093. var g = null;
  4094. var b = null;
  4095. if (s == 0){
  4096. // color is on black-and-white center line
  4097. // achromatic: shades of gray
  4098. r = v;
  4099. g = v;
  4100. b = v;
  4101. }else{
  4102. // chromatic color
  4103. var hTemp = h / 60; // h is now IN [0,6]
  4104. var i = Math.floor(hTemp); // largest integer <= h
  4105. var f = hTemp - i; // fractional part of h
  4106. var p = v * (1 - s);
  4107. var q = v * (1 - (s * f));
  4108. var t = v * (1 - (s * (1 - f)));
  4109. switch(i){
  4110. case 0: r = v; g = t; b = p; break;
  4111. case 1: r = q; g = v; b = p; break;
  4112. case 2: r = p; g = v; b = t; break;
  4113. case 3: r = p; g = q; b = v; break;
  4114. case 4: r = t; g = p; b = v; break;
  4115. case 5: r = v; g = p; b = q; break;
  4116. }
  4117. }
  4118. r = Math.ceil(r * 255);
  4119. g = Math.ceil(g * 255);
  4120. b = Math.ceil(b * 255);
  4121. return [r, g, b];
  4122. }
  4123. dojo.graphics.color.rgb2hsl = function(r, g, b){
  4124. if (dojo.lang.isArray(r)) {
  4125. b = r[2] || 0;
  4126. g = r[1] || 0;
  4127. r = r[0] || 0;
  4128. }
  4129. r /= 255;
  4130. g /= 255;
  4131. b /= 255;
  4132. //
  4133. // based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/
  4134. //
  4135. var h = null;
  4136. var s = null;
  4137. var l = null;
  4138. var min = Math.min(r, g, b);
  4139. var max = Math.max(r, g, b);
  4140. var delta = max - min;
  4141. l = (min + max) / 2;
  4142. s = 0;
  4143. if ((l > 0) && (l < 1)){
  4144. s = delta / ((l < 0.5) ? (2 * l) : (2 - 2 * l));
  4145. }
  4146. h = 0;
  4147. if (delta > 0) {
  4148. if ((max == r) && (max != g)){
  4149. h += (g - b) / delta;
  4150. }
  4151. if ((max == g) && (max != b)){
  4152. h += (2 + (b - r) / delta);
  4153. }
  4154. if ((max == b) && (max != r)){
  4155. h += (4 + (r - g) / delta);
  4156. }
  4157. h *= 60;
  4158. }
  4159. h = (h == 0) ? 360 : Math.ceil((h / 360) * 255);
  4160. s = Math.ceil(s * 255);
  4161. l = Math.ceil(l * 255);
  4162. return [h, s, l];
  4163. }
  4164. dojo.graphics.color.hsl2rgb = function(h, s, l){
  4165. if (dojo.lang.isArray(h)) {
  4166. l = h[2] || 0;
  4167. s = h[1] || 0;
  4168. h = h[0] || 0;
  4169. }
  4170. h = (h / 255) * 360;
  4171. if (h == 360){ h = 0;}
  4172. s = s / 255;
  4173. l = l / 255;
  4174. //
  4175. // based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/
  4176. //
  4177. while (h < 0){ h += 360; }
  4178. while (h > 360){ h -= 360; }
  4179. if (h < 120){
  4180. r = (120 - h) / 60;
  4181. g = h / 60;
  4182. b = 0;
  4183. }else if (h < 240){
  4184. r = 0;
  4185. g = (240 - h) / 60;
  4186. b = (h - 120) / 60;
  4187. }else{
  4188. r = (h - 240) / 60;
  4189. g = 0;
  4190. b = (360 - h) / 60;
  4191. }
  4192. r = Math.min(r, 1);
  4193. g = Math.min(g, 1);
  4194. b = Math.min(b, 1);
  4195. r = 2 * s * r + (1 - s);
  4196. g = 2 * s * g + (1 - s);
  4197. b = 2 * s * b + (1 - s);
  4198. if (l < 0.5){
  4199. r = l * r;
  4200. g = l * g;
  4201. b = l * b;
  4202. }else{
  4203. r = (1 - l) * r + 2 * l - 1;
  4204. g = (1 - l) * g + 2 * l - 1;
  4205. b = (1 - l) * b + 2 * l - 1;
  4206. }
  4207. r = Math.ceil(r * 255);
  4208. g = Math.ceil(g * 255);
  4209. b = Math.ceil(b * 255);
  4210. return [r, g, b];
  4211. }
  4212. dojo.provide("dojo.style");
  4213. dojo.require("dojo.dom");
  4214. dojo.require("dojo.uri.Uri");
  4215. dojo.require("dojo.graphics.color");
  4216. // values: content-box, border-box
  4217. dojo.style.boxSizing = {
  4218. marginBox: "margin-box",
  4219. borderBox: "border-box",
  4220. paddingBox: "padding-box",
  4221. contentBox: "content-box"
  4222. };
  4223. dojo.style.getBoxSizing = function(node)
  4224. {
  4225. if (dojo.render.html.ie || dojo.render.html.opera){
  4226. var cm = document["compatMode"];
  4227. if (cm == "BackCompat" || cm == "QuirksMode"){
  4228. return dojo.style.boxSizing.borderBox;
  4229. }else{
  4230. return dojo.style.boxSizing.contentBox;
  4231. }
  4232. }else{
  4233. if(arguments.length == 0){ node = document.documentElement; }
  4234. var sizing = dojo.style.getStyle(node, "-moz-box-sizing");
  4235. if(!sizing){ sizing = dojo.style.getStyle(node, "box-sizing"); }
  4236. return (sizing ? sizing : dojo.style.boxSizing.contentBox);
  4237. }
  4238. }
  4239. /*
  4240. The following several function use the dimensions shown below
  4241. +-------------------------+
  4242. | margin |
  4243. | +---------------------+ |
  4244. | | border | |
  4245. | | +-----------------+ | |
  4246. | | | padding | | |
  4247. | | | +-------------+ | | |
  4248. | | | | content | | | |
  4249. | | | +-------------+ | | |
  4250. | | +-|-------------|-+ | |
  4251. | +-|-|-------------|-|-+ |
  4252. +-|-|-|-------------|-|-|-+
  4253. | | | | | | | |
  4254. | | | |<- content ->| | | |
  4255. | |<------ inner ------>| |
  4256. |<-------- outer -------->|
  4257. +-------------------------+
  4258. * content-box
  4259. |m|b|p| |p|b|m|
  4260. | |<------ offset ----->| |
  4261. | | |<---- client --->| | |
  4262. | | | |<-- width -->| | | |
  4263. * border-box
  4264. |m|b|p| |p|b|m|
  4265. | |<------ offset ----->| |
  4266. | | |<---- client --->| | |
  4267. | |<------ width ------>| |
  4268. */
  4269. /*
  4270. Notes:
  4271. General:
  4272. - Uncomputable values are returned as NaN.
  4273. - setOuterWidth/Height return *false* if the outer size could not be computed, otherwise *true*.
  4274. - I (sjmiles) know no way to find the calculated values for auto-margins.
  4275. - All returned values are floating point in 'px' units. If a non-zero computed style value is not specified in 'px', NaN is returned.
  4276. FF:
  4277. - styles specified as '0' (unitless 0) show computed as '0pt'.
  4278. IE:
  4279. - clientWidth/Height are unreliable (0 unless the object has 'layout').
  4280. - margins must be specified in px, or 0 (in any unit) for any sizing function to work. Otherwise margins detect as 'auto'.
  4281. - padding can be empty or, if specified, must be in px, or 0 (in any unit) for any sizing function to work.
  4282. Safari:
  4283. - Safari defaults padding values to 'auto'.
  4284. See the unit tests for examples of (un)computable values in a given browser.
  4285. */
  4286. // FIXME: these work for most elements (e.g. DIV) but not all (e.g. TEXTAREA)
  4287. dojo.style.isBorderBox = function(node)
  4288. {
  4289. return (dojo.style.getBoxSizing(node) == dojo.style.boxSizing.borderBox);
  4290. }
  4291. dojo.style.getUnitValue = function (element, cssSelector, autoIsZero){
  4292. var result = { value: 0, units: 'px' };
  4293. var s = dojo.style.getComputedStyle(element, cssSelector);
  4294. if (s == '' || (s == 'auto' && autoIsZero)){ return result; }
  4295. if (dojo.lang.isUndefined(s)){
  4296. result.value = NaN;
  4297. }else{
  4298. // FIXME: is regex inefficient vs. parseInt or some manual test?
  4299. var match = s.match(/([\d.]+)([a-z%]*)/i);
  4300. if (!match){
  4301. result.value = NaN;
  4302. }else{
  4303. result.value = Number(match[1]);
  4304. result.units = match[2].toLowerCase();
  4305. }
  4306. }
  4307. return result;
  4308. }
  4309. dojo.style.getPixelValue = function (element, cssSelector, autoIsZero){
  4310. var result = dojo.style.getUnitValue(element, cssSelector, autoIsZero);
  4311. // FIXME: code exists for converting other units to px (see Dean Edward's IE7)
  4312. // but there are cross-browser complexities
  4313. if (isNaN(result.value) || (result.value && result.units != 'px')) { return NaN; }
  4314. return result.value;
  4315. }
  4316. dojo.style.getNumericStyle = dojo.style.getPixelValue; // backward compat
  4317. dojo.style.isPositionAbsolute = function(node){
  4318. return (dojo.style.getComputedStyle(node, 'position') == 'absolute');
  4319. }
  4320. dojo.style.getMarginWidth = function(node){
  4321. var autoIsZero = dojo.style.isPositionAbsolute(node);
  4322. var left = dojo.style.getPixelValue(node, "margin-left", autoIsZero);
  4323. var right = dojo.style.getPixelValue(node, "margin-right", autoIsZero);
  4324. return left + right;
  4325. }
  4326. dojo.style.getBorderWidth = function(node){
  4327. // the removed calculation incorrectly includes scrollbar
  4328. //if (node.clientWidth){
  4329. // return node.offsetWidth - node.clientWidth;
  4330. //}else
  4331. {
  4332. var left = (dojo.style.getStyle(node, 'border-left-style') == 'none' ? 0 : dojo.style.getPixelValue(node, "border-left-width"));
  4333. var right = (dojo.style.getStyle(node, 'border-right-style') == 'none' ? 0 : dojo.style.getPixelValue(node, "border-right-width"));
  4334. return left + right;
  4335. }
  4336. }
  4337. dojo.style.getPaddingWidth = function(node){
  4338. var left = dojo.style.getPixelValue(node, "padding-left", true);
  4339. var right = dojo.style.getPixelValue(node, "padding-right", true);
  4340. return left + right;
  4341. }
  4342. dojo.style.getContentWidth = function (node){
  4343. return node.offsetWidth - dojo.style.getPaddingWidth(node) - dojo.style.getBorderWidth(node);
  4344. }
  4345. dojo.style.getInnerWidth = function (node){
  4346. return node.offsetWidth;
  4347. }
  4348. dojo.style.getOuterWidth = function (node){
  4349. return dojo.style.getInnerWidth(node) + dojo.style.getMarginWidth(node);
  4350. }
  4351. dojo.style.setOuterWidth = function (node, pxWidth){
  4352. if (!dojo.style.isBorderBox(node)){
  4353. pxWidth -= dojo.style.getPaddingWidth(node) + dojo.style.getBorderWidth(node);
  4354. }
  4355. pxWidth -= dojo.style.getMarginWidth(node);
  4356. if (!isNaN(pxWidth) && pxWidth > 0){
  4357. node.style.width = pxWidth + 'px';
  4358. return true;
  4359. }else return false;
  4360. }
  4361. // FIXME: these aliases are actually the preferred names
  4362. dojo.style.getContentBoxWidth = dojo.style.getContentWidth;
  4363. dojo.style.getBorderBoxWidth = dojo.style.getInnerWidth;
  4364. dojo.style.getMarginBoxWidth = dojo.style.getOuterWidth;
  4365. dojo.style.setMarginBoxWidth = dojo.style.setOuterWidth;
  4366. dojo.style.getMarginHeight = function(node){
  4367. var autoIsZero = dojo.style.isPositionAbsolute(node);
  4368. var top = dojo.style.getPixelValue(node, "margin-top", autoIsZero);
  4369. var bottom = dojo.style.getPixelValue(node, "margin-bottom", autoIsZero);
  4370. return top + bottom;
  4371. }
  4372. dojo.style.getBorderHeight = function(node){
  4373. // this removed calculation incorrectly includes scrollbar
  4374. // if (node.clientHeight){
  4375. // return node.offsetHeight- node.clientHeight;
  4376. // }else
  4377. {
  4378. var top = (dojo.style.getStyle(node, 'border-top-style') == 'none' ? 0 : dojo.style.getPixelValue(node, "border-top-width"));
  4379. var bottom = (dojo.style.getStyle(node, 'border-bottom-style') == 'none' ? 0 : dojo.style.getPixelValue(node, "border-bottom-width"));
  4380. return top + bottom;
  4381. }
  4382. }
  4383. dojo.style.getPaddingHeight = function(node){
  4384. var top = dojo.style.getPixelValue(node, "padding-top", true);
  4385. var bottom = dojo.style.getPixelValue(node, "padding-bottom", true);
  4386. return top + bottom;
  4387. }
  4388. dojo.style.getContentHeight = function (node){
  4389. return node.offsetHeight - dojo.style.getPaddingHeight(node) - dojo.style.getBorderHeight(node);
  4390. }
  4391. dojo.style.getInnerHeight = function (node){
  4392. return node.offsetHeight; // FIXME: does this work?
  4393. }
  4394. dojo.style.getOuterHeight = function (node){
  4395. return dojo.style.getInnerHeight(node) + dojo.style.getMarginHeight(node);
  4396. }
  4397. dojo.style.setOuterHeight = function (node, pxHeight){
  4398. if (!dojo.style.isBorderBox(node)){
  4399. pxHeight -= dojo.style.getPaddingHeight(node) + dojo.style.getBorderHeight(node);
  4400. }
  4401. pxHeight -= dojo.style.getMarginHeight(node);
  4402. if (!isNaN(pxHeight) && pxHeight > 0){
  4403. node.style.height = pxHeight + 'px';
  4404. return true;
  4405. }else return false;
  4406. }
  4407. dojo.style.setContentWidth = function(node, pxWidth){
  4408. if (dojo.style.isBorderBox(node)){
  4409. pxWidth += dojo.style.getPaddingWidth(node) + dojo.style.getBorderWidth(node);
  4410. }
  4411. if (!isNaN(pxWidth) && pxWidth > 0){
  4412. node.style.width = pxWidth + 'px';
  4413. return true;
  4414. }else return false;
  4415. }
  4416. dojo.style.setContentHeight = function(node, pxHeight){
  4417. if (dojo.style.isBorderBox(node)){
  4418. pxHeight += dojo.style.getPaddingHeight(node) + dojo.style.getBorderHeight(node);
  4419. }
  4420. if (!isNaN(pxHeight) && pxHeight > 0){
  4421. node.style.height = pxHeight + 'px';
  4422. return true;
  4423. }else return false;
  4424. }
  4425. // FIXME: these aliases are actually the preferred names
  4426. dojo.style.getContentBoxHeight = dojo.style.getContentHeight;
  4427. dojo.style.getBorderBoxHeight = dojo.style.getInnerHeight;
  4428. dojo.style.getMarginBoxHeight = dojo.style.getOuterHeight;
  4429. dojo.style.setMarginBoxHeight = dojo.style.setOuterHeight;
  4430. dojo.style.getTotalOffset = function (node, type, includeScroll){
  4431. var typeStr = (type=="top") ? "offsetTop" : "offsetLeft";
  4432. var typeScroll = (type=="top") ? "scrollTop" : "scrollLeft";
  4433. var alt = (type=="top") ? "y" : "x";
  4434. var ret = 0;
  4435. if(node["offsetParent"]){
  4436. if(includeScroll && node.parentNode != document.body) {
  4437. ret -= dojo.style.sumAncestorProperties(node, typeScroll);
  4438. }
  4439. // FIXME: this is known not to work sometimes on IE 5.x since nodes
  4440. // soemtimes need to be "tickled" before they will display their
  4441. // offset correctly
  4442. do {
  4443. ret += node[typeStr];
  4444. node = node.offsetParent;
  4445. } while (node != document.getElementsByTagName("body")[0].parentNode && node != null);
  4446. }else if(node[alt]){
  4447. ret += node[alt];
  4448. }
  4449. return ret;
  4450. }
  4451. dojo.style.sumAncestorProperties = function (node, prop) {
  4452. if (!node) { return 0; } // FIXME: throw an error?
  4453. var retVal = 0;
  4454. while (node) {
  4455. var val = node[prop];
  4456. if (val) {
  4457. retVal += val - 0;
  4458. }
  4459. node = node.parentNode;
  4460. }
  4461. return retVal;
  4462. }
  4463. dojo.style.totalOffsetLeft = function (node, includeScroll){
  4464. return dojo.style.getTotalOffset(node, "left", includeScroll);
  4465. }
  4466. dojo.style.getAbsoluteX = dojo.style.totalOffsetLeft;
  4467. dojo.style.totalOffsetTop = function (node, includeScroll){
  4468. return dojo.style.getTotalOffset(node, "top", includeScroll);
  4469. }
  4470. dojo.style.getAbsoluteY = dojo.style.totalOffsetTop;
  4471. dojo.style.getAbsolutePosition = function(node, includeScroll) {
  4472. var position = [
  4473. dojo.style.getAbsoluteX(node, includeScroll),
  4474. dojo.style.getAbsoluteY(node, includeScroll)
  4475. ];
  4476. position.x = position[0];
  4477. position.y = position[1];
  4478. return position;
  4479. }
  4480. dojo.style.styleSheet = null;
  4481. // FIXME: this is a really basic stub for adding and removing cssRules, but
  4482. // it assumes that you know the index of the cssRule that you want to add
  4483. // or remove, making it less than useful. So we need something that can
  4484. // search for the selector that you you want to remove.
  4485. dojo.style.insertCssRule = function (selector, declaration, index) {
  4486. if (!dojo.style.styleSheet) {
  4487. if (document.createStyleSheet) { // IE
  4488. dojo.style.styleSheet = document.createStyleSheet();
  4489. } else if (document.styleSheets[0]) { // rest
  4490. // FIXME: should create a new style sheet here
  4491. // fall back on an exsiting style sheet
  4492. dojo.style.styleSheet = document.styleSheets[0];
  4493. } else { return null; } // fail
  4494. }
  4495. if (arguments.length < 3) { // index may == 0
  4496. if (dojo.style.styleSheet.cssRules) { // W3
  4497. index = dojo.style.styleSheet.cssRules.length;
  4498. } else if (dojo.style.styleSheet.rules) { // IE
  4499. index = dojo.style.styleSheet.rules.length;
  4500. } else { return null; } // fail
  4501. }
  4502. if (dojo.style.styleSheet.insertRule) { // W3
  4503. var rule = selector + " { " + declaration + " }";
  4504. return dojo.style.styleSheet.insertRule(rule, index);
  4505. } else if (dojo.style.styleSheet.addRule) { // IE
  4506. return dojo.style.styleSheet.addRule(selector, declaration, index);
  4507. } else { return null; } // fail
  4508. }
  4509. dojo.style.removeCssRule = function (index){
  4510. if(!dojo.style.styleSheet){
  4511. dojo.debug("no stylesheet defined for removing rules");
  4512. return false;
  4513. }
  4514. if(dojo.render.html.ie){
  4515. if(!index){
  4516. index = dojo.style.styleSheet.rules.length;
  4517. dojo.style.styleSheet.removeRule(index);
  4518. }
  4519. }else if(document.styleSheets[0]){
  4520. if(!index){
  4521. index = dojo.style.styleSheet.cssRules.length;
  4522. }
  4523. dojo.style.styleSheet.deleteRule(index);
  4524. }
  4525. return true;
  4526. }
  4527. dojo.style.insertCssFile = function (URI, doc, checkDuplicates){
  4528. if(!URI) { return; }
  4529. if(!doc){ doc = document; }
  4530. // Safari doesn't have this property, but it doesn't support
  4531. // styleSheets.href either so it beomces moot
  4532. if(doc.baseURI) { URI = new dojo.uri.Uri(doc.baseURI, URI); }
  4533. if(checkDuplicates && doc.styleSheets){
  4534. // get the host + port info from location
  4535. var loc = location.href.split("#")[0].substring(0, location.href.indexOf(location.pathname));
  4536. for(var i = 0; i < doc.styleSheets.length; i++){
  4537. if(doc.styleSheets[i].href && URI.toString() ==
  4538. new dojo.uri.Uri(doc.styleSheets[i].href.toString())) { return; }
  4539. }
  4540. }
  4541. var file = doc.createElement("link");
  4542. file.setAttribute("type", "text/css");
  4543. file.setAttribute("rel", "stylesheet");
  4544. file.setAttribute("href", URI);
  4545. var head = doc.getElementsByTagName("head")[0];
  4546. if(head){ // FIXME: why isn't this working on Opera 8?
  4547. head.appendChild(file);
  4548. }
  4549. }
  4550. dojo.style.getBackgroundColor = function (node) {
  4551. var color;
  4552. do{
  4553. color = dojo.style.getStyle(node, "background-color");
  4554. // Safari doesn't say "transparent"
  4555. if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; }
  4556. if(node == document.getElementsByTagName("body")[0]) { node = null; break; }
  4557. node = node.parentNode;
  4558. }while(node && dojo.lang.inArray(color, ["transparent", ""]));
  4559. if( color == "transparent" ) {
  4560. color = [255, 255, 255, 0];
  4561. } else {
  4562. color = dojo.graphics.color.extractRGB(color);
  4563. }
  4564. return color;
  4565. }
  4566. dojo.style.getComputedStyle = function (element, cssSelector, inValue) {
  4567. var value = inValue;
  4568. if (element.style.getPropertyValue) { // W3
  4569. value = element.style.getPropertyValue(cssSelector);
  4570. }
  4571. if(!value) {
  4572. if (document.defaultView) { // gecko
  4573. value = document.defaultView.getComputedStyle(element, "")
  4574. .getPropertyValue(cssSelector);
  4575. } else if (element.currentStyle) { // IE
  4576. value = element.currentStyle[dojo.style.toCamelCase(cssSelector)];
  4577. }
  4578. }
  4579. return value;
  4580. }
  4581. dojo.style.getStyle = function (element, cssSelector) {
  4582. var camelCased = dojo.style.toCamelCase(cssSelector);
  4583. var value = element.style[camelCased]; // dom-ish
  4584. return (value ? value : dojo.style.getComputedStyle(element, cssSelector, value));
  4585. }
  4586. dojo.style.toCamelCase = function (selector) {
  4587. var arr = selector.split('-'), cc = arr[0];
  4588. for(var i = 1; i < arr.length; i++) {
  4589. cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
  4590. }
  4591. return cc;
  4592. }
  4593. dojo.style.toSelectorCase = function (selector) {
  4594. return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase() ;
  4595. }
  4596. /* float between 0.0 (transparent) and 1.0 (opaque) */
  4597. dojo.style.setOpacity = function setOpacity (node, opacity, dontFixOpacity) {
  4598. node = dojo.byId(node);
  4599. var h = dojo.render.html;
  4600. if(!dontFixOpacity){
  4601. if( opacity >= 1.0){
  4602. if(h.ie){
  4603. dojo.style.clearOpacity(node);
  4604. return;
  4605. }else{
  4606. opacity = 0.999999;
  4607. }
  4608. }else if( opacity < 0.0){ opacity = 0; }
  4609. }
  4610. if(h.ie){
  4611. if(node.nodeName.toLowerCase() == "tr"){
  4612. // FIXME: is this too naive? will we get more than we want?
  4613. var tds = node.getElementsByTagName("td");
  4614. for(var x=0; x<tds.length; x++){
  4615. tds[x].style.filter = "Alpha(Opacity="+opacity*100+")";
  4616. }
  4617. }
  4618. node.style.filter = "Alpha(Opacity="+opacity*100+")";
  4619. }else if(h.moz){
  4620. node.style.opacity = opacity; // ffox 1.0 directly supports "opacity"
  4621. node.style.MozOpacity = opacity;
  4622. }else if(h.safari){
  4623. node.style.opacity = opacity; // 1.3 directly supports "opacity"
  4624. node.style.KhtmlOpacity = opacity;
  4625. }else{
  4626. node.style.opacity = opacity;
  4627. }
  4628. }
  4629. dojo.style.getOpacity = function getOpacity (node){
  4630. if(dojo.render.html.ie){
  4631. var opac = (node.filters && node.filters.alpha &&
  4632. typeof node.filters.alpha.opacity == "number"
  4633. ? node.filters.alpha.opacity : 100) / 100;
  4634. }else{
  4635. var opac = node.style.opacity || node.style.MozOpacity ||
  4636. node.style.KhtmlOpacity || 1;
  4637. }
  4638. return opac >= 0.999999 ? 1.0 : Number(opac);
  4639. }
  4640. dojo.style.clearOpacity = function clearOpacity (node) {
  4641. var h = dojo.render.html;
  4642. if(h.ie){
  4643. if( node.filters && node.filters.alpha ) {
  4644. node.style.filter = ""; // FIXME: may get rid of other filter effects
  4645. }
  4646. }else if(h.moz){
  4647. node.style.opacity = 1;
  4648. node.style.MozOpacity = 1;
  4649. }else if(h.safari){
  4650. node.style.opacity = 1;
  4651. node.style.KhtmlOpacity = 1;
  4652. }else{
  4653. node.style.opacity = 1;
  4654. }
  4655. }
  4656. dojo.provide("dojo.html");
  4657. dojo.require("dojo.dom");
  4658. dojo.require("dojo.style");
  4659. dojo.require("dojo.string");
  4660. dojo.lang.mixin(dojo.html, dojo.dom);
  4661. dojo.lang.mixin(dojo.html, dojo.style);
  4662. // FIXME: we are going to assume that we can throw any and every rendering
  4663. // engine into the IE 5.x box model. In Mozilla, we do this w/ CSS.
  4664. // Need to investigate for KHTML and Opera
  4665. dojo.html.clearSelection = function(){
  4666. try{
  4667. if(window["getSelection"]){
  4668. if(dojo.render.html.safari){
  4669. // pulled from WebCore/ecma/kjs_window.cpp, line 2536
  4670. window.getSelection().collapse();
  4671. }else{
  4672. window.getSelection().removeAllRanges();
  4673. }
  4674. }else if((document.selection)&&(document.selection.clear)){
  4675. document.selection.clear();
  4676. }
  4677. return true;
  4678. }catch(e){
  4679. dojo.debug(e);
  4680. return false;
  4681. }
  4682. }
  4683. dojo.html.disableSelection = function(element){
  4684. element = element||dojo.html.body();
  4685. var h = dojo.render.html;
  4686. if(h.mozilla){
  4687. element.style.MozUserSelect = "none";
  4688. }else if(h.safari){
  4689. element.style.KhtmlUserSelect = "none";
  4690. }else if(h.ie){
  4691. element.unselectable = "on";
  4692. }else{
  4693. return false;
  4694. }
  4695. return true;
  4696. }
  4697. dojo.html.enableSelection = function(element){
  4698. element = element||dojo.html.body();
  4699. var h = dojo.render.html;
  4700. if(h.mozilla){
  4701. element.style.MozUserSelect = "";
  4702. }else if(h.safari){
  4703. element.style.KhtmlUserSelect = "";
  4704. }else if(h.ie){
  4705. element.unselectable = "off";
  4706. }else{
  4707. return false;
  4708. }
  4709. return true;
  4710. }
  4711. dojo.html.selectElement = function(element){
  4712. if(document.selection && dojo.html.body().createTextRange){ // IE
  4713. var range = dojo.html.body().createTextRange();
  4714. range.moveToElementText(element);
  4715. range.select();
  4716. }else if(window["getSelection"]){
  4717. var selection = window.getSelection();
  4718. // FIXME: does this work on Safari?
  4719. if(selection["selectAllChildren"]){ // Mozilla
  4720. selection.selectAllChildren(element);
  4721. }
  4722. }
  4723. }
  4724. dojo.html.isSelectionCollapsed = function(){
  4725. if(document["selection"]){ // IE
  4726. return document.selection.createRange().text == "";
  4727. }else if(window["getSelection"]){
  4728. var selection = window.getSelection();
  4729. if(dojo.lang.isString(selection)){ // Safari
  4730. return selection == "";
  4731. }else{ // Mozilla/W3
  4732. return selection.isCollapsed;
  4733. }
  4734. }
  4735. }
  4736. dojo.html.getEventTarget = function(evt){
  4737. if(!evt) { evt = window.event || {} };
  4738. if(evt.srcElement) {
  4739. return evt.srcElement;
  4740. } else if(evt.target) {
  4741. return evt.target;
  4742. }
  4743. return null;
  4744. }
  4745. // FIXME: should the next set of functions take an optional document to operate
  4746. // on so as to be useful for getting this information from iframes?
  4747. dojo.html.getScrollTop = function(){
  4748. return document.documentElement.scrollTop || dojo.html.body().scrollTop || 0;
  4749. }
  4750. dojo.html.getScrollLeft = function(){
  4751. return document.documentElement.scrollLeft || dojo.html.body().scrollLeft || 0;
  4752. }
  4753. dojo.html.getDocumentWidth = function(){
  4754. dojo.deprecated("dojo.html.getDocument* has been deprecated in favor of dojo.html.getViewport*");
  4755. return dojo.html.getViewportWidth();
  4756. }
  4757. dojo.html.getDocumentHeight = function(){
  4758. dojo.deprecated("dojo.html.getDocument* has been deprecated in favor of dojo.html.getViewport*");
  4759. return dojo.html.getViewportHeight();
  4760. }
  4761. dojo.html.getDocumentSize = function(){
  4762. dojo.deprecated("dojo.html.getDocument* has been deprecated in favor of dojo.html.getViewport*");
  4763. return dojo.html.getViewportSize();
  4764. }
  4765. dojo.html.getViewportWidth = function(){
  4766. var w = 0;
  4767. if(window.innerWidth){
  4768. w = window.innerWidth;
  4769. }
  4770. if(dojo.exists(document, "documentElement.clientWidth")){
  4771. // IE6 Strict
  4772. var w2 = document.documentElement.clientWidth;
  4773. // this lets us account for scrollbars
  4774. if(!w || w2 && w2 < w) {
  4775. w = w2;
  4776. }
  4777. return w;
  4778. }
  4779. if(document.body){
  4780. // IE
  4781. return document.body.clientWidth;
  4782. }
  4783. return 0;
  4784. }
  4785. dojo.html.getViewportHeight = function(){
  4786. if (window.innerHeight){
  4787. return window.innerHeight;
  4788. }
  4789. if (dojo.exists(document, "documentElement.clientHeight")){
  4790. // IE6 Strict
  4791. return document.documentElement.clientHeight;
  4792. }
  4793. if (document.body){
  4794. // IE
  4795. return document.body.clientHeight;
  4796. }
  4797. return 0;
  4798. }
  4799. dojo.html.getViewportSize = function(){
  4800. var ret = [dojo.html.getViewportWidth(), dojo.html.getViewportHeight()];
  4801. ret.w = ret[0];
  4802. ret.h = ret[1];
  4803. return ret;
  4804. }
  4805. dojo.html.getScrollOffset = function(){
  4806. var ret = [0, 0];
  4807. if(window.pageYOffset){
  4808. ret = [window.pageXOffset, window.pageYOffset];
  4809. }else if(dojo.exists(document, "documentElement.scrollTop")){
  4810. ret = [document.documentElement.scrollLeft, document.documentElement.scrollTop];
  4811. } else if(document.body){
  4812. ret = [document.body.scrollLeft, document.body.scrollTop];
  4813. }
  4814. ret.x = ret[0];
  4815. ret.y = ret[1];
  4816. return ret;
  4817. }
  4818. dojo.html.getParentOfType = function(node, type){
  4819. dojo.deprecated("dojo.html.getParentOfType has been deprecated in favor of dojo.html.getParentByType*");
  4820. return dojo.html.getParentByType(node, type);
  4821. }
  4822. dojo.html.getParentByType = function(node, type) {
  4823. var parent = node;
  4824. type = type.toLowerCase();
  4825. while((parent)&&(parent.nodeName.toLowerCase()!=type)){
  4826. if(parent==(document["body"]||document["documentElement"])){
  4827. return null;
  4828. }
  4829. parent = parent.parentNode;
  4830. }
  4831. return parent;
  4832. }
  4833. // RAR: this function comes from nwidgets and is more-or-less unmodified.
  4834. // We should probably look ant Burst and f(m)'s equivalents
  4835. dojo.html.getAttribute = function(node, attr){
  4836. // FIXME: need to add support for attr-specific accessors
  4837. if((!node)||(!node.getAttribute)){
  4838. // if(attr !== 'nwType'){
  4839. // alert("getAttr of '" + attr + "' with bad node");
  4840. // }
  4841. return null;
  4842. }
  4843. var ta = typeof attr == 'string' ? attr : new String(attr);
  4844. // first try the approach most likely to succeed
  4845. var v = node.getAttribute(ta.toUpperCase());
  4846. if((v)&&(typeof v == 'string')&&(v!="")){ return v; }
  4847. // try returning the attributes value, if we couldn't get it as a string
  4848. if(v && v.value){ return v.value; }
  4849. // this should work on Opera 7, but it's a little on the crashy side
  4850. if((node.getAttributeNode)&&(node.getAttributeNode(ta))){
  4851. return (node.getAttributeNode(ta)).value;
  4852. }else if(node.getAttribute(ta)){
  4853. return node.getAttribute(ta);
  4854. }else if(node.getAttribute(ta.toLowerCase())){
  4855. return node.getAttribute(ta.toLowerCase());
  4856. }
  4857. return null;
  4858. }
  4859. /**
  4860. * Determines whether or not the specified node carries a value for the
  4861. * attribute in question.
  4862. */
  4863. dojo.html.hasAttribute = function(node, attr){
  4864. return dojo.html.getAttribute(node, attr) ? true : false;
  4865. }
  4866. /**
  4867. * Returns the string value of the list of CSS classes currently assigned
  4868. * directly to the node in question. Returns an empty string if no class attribute
  4869. * is found;
  4870. */
  4871. dojo.html.getClass = function(node){
  4872. if(!node){ return ""; }
  4873. var cs = "";
  4874. if(node.className){
  4875. cs = node.className;
  4876. }else if(dojo.html.hasAttribute(node, "class")){
  4877. cs = dojo.html.getAttribute(node, "class");
  4878. }
  4879. return dojo.string.trim(cs);
  4880. }
  4881. /**
  4882. * Returns an array of CSS classes currently assigned
  4883. * directly to the node in question. Returns an empty array if no classes
  4884. * are found;
  4885. */
  4886. dojo.html.getClasses = function(node) {
  4887. var c = dojo.html.getClass(node);
  4888. return (c == "") ? [] : c.split(/\s+/g);
  4889. }
  4890. /**
  4891. * Returns whether or not the specified classname is a portion of the
  4892. * class list currently applied to the node. Does not cover cascaded
  4893. * styles, only classes directly applied to the node.
  4894. */
  4895. dojo.html.hasClass = function(node, classname){
  4896. return dojo.lang.inArray(dojo.html.getClasses(node), classname);
  4897. }
  4898. /**
  4899. * Adds the specified class to the beginning of the class list on the
  4900. * passed node. This gives the specified class the highest precidence
  4901. * when style cascading is calculated for the node. Returns true or
  4902. * false; indicating success or failure of the operation, respectively.
  4903. */
  4904. dojo.html.prependClass = function(node, classStr){
  4905. if(!node){ return false; }
  4906. classStr += " " + dojo.html.getClass(node);
  4907. return dojo.html.setClass(node, classStr);
  4908. }
  4909. /**
  4910. * Adds the specified class to the end of the class list on the
  4911. * passed &node;. Returns &true; or &false; indicating success or failure.
  4912. */
  4913. dojo.html.addClass = function(node, classStr){
  4914. if (!node) { return false; }
  4915. if (dojo.html.hasClass(node, classStr)) {
  4916. return false;
  4917. }
  4918. classStr = dojo.string.trim(dojo.html.getClass(node) + " " + classStr);
  4919. return dojo.html.setClass(node, classStr);
  4920. }
  4921. /**
  4922. * Clobbers the existing list of classes for the node, replacing it with
  4923. * the list given in the 2nd argument. Returns true or false
  4924. * indicating success or failure.
  4925. */
  4926. dojo.html.setClass = function(node, classStr){
  4927. if(!node){ return false; }
  4928. var cs = new String(classStr);
  4929. try{
  4930. if(typeof node.className == "string"){
  4931. node.className = cs;
  4932. }else if(node.setAttribute){
  4933. node.setAttribute("class", classStr);
  4934. node.className = cs;
  4935. }else{
  4936. return false;
  4937. }
  4938. }catch(e){
  4939. dojo.debug("dojo.html.setClass() failed", e);
  4940. }
  4941. return true;
  4942. }
  4943. /**
  4944. * Removes the className from the node;. Returns
  4945. * true or false indicating success or failure.
  4946. */
  4947. dojo.html.removeClass = function(node, classStr, allowPartialMatches){
  4948. if(!node){ return false; }
  4949. var classStr = dojo.string.trim(new String(classStr));
  4950. try{
  4951. var cs = dojo.html.getClasses(node);
  4952. var nca = [];
  4953. if(allowPartialMatches){
  4954. for(var i = 0; i<cs.length; i++){
  4955. if(cs[i].indexOf(classStr) == -1){
  4956. nca.push(cs[i]);
  4957. }
  4958. }
  4959. }else{
  4960. for(var i=0; i<cs.length; i++){
  4961. if(cs[i] != classStr){
  4962. nca.push(cs[i]);
  4963. }
  4964. }
  4965. }
  4966. dojo.html.setClass(node, nca.join(" "));
  4967. }catch(e){
  4968. dojo.debug("dojo.html.removeClass() failed", e);
  4969. }
  4970. return true;
  4971. }
  4972. /**
  4973. * Replaces 'oldClass' and adds 'newClass' to node
  4974. */
  4975. dojo.html.replaceClass = function(node, newClass, oldClass) {
  4976. dojo.html.removeClass(node, oldClass);
  4977. dojo.html.addClass(node, newClass);
  4978. }
  4979. // Enum type for getElementsByClass classMatchType arg:
  4980. dojo.html.classMatchType = {
  4981. ContainsAll : 0, // all of the classes are part of the node's class (default)
  4982. ContainsAny : 1, // any of the classes are part of the node's class
  4983. IsOnly : 2 // only all of the classes are part of the node's class
  4984. }
  4985. /**
  4986. * Returns an array of nodes for the given classStr, children of a
  4987. * parent, and optionally of a certain nodeType
  4988. */
  4989. dojo.html.getElementsByClass = function(classStr, parent, nodeType, classMatchType){
  4990. if(!parent){ parent = document; }
  4991. var classes = classStr.split(/\s+/g);
  4992. var nodes = [];
  4993. if( classMatchType != 1 && classMatchType != 2 ) classMatchType = 0; // make it enum
  4994. var reClass = new RegExp("(\\s|^)((" + classes.join(")|(") + "))(\\s|$)");
  4995. // FIXME: doesn't have correct parent support!
  4996. if(!nodeType){ nodeType = "*"; }
  4997. var candidateNodes = parent.getElementsByTagName(nodeType);
  4998. outer:
  4999. for(var i = 0; i < candidateNodes.length; i++) {
  5000. var node = candidateNodes[i];
  5001. var nodeClasses = dojo.html.getClasses(node);
  5002. if(nodeClasses.length == 0) { continue outer; }
  5003. var matches = 0;
  5004. for(var j = 0; j < nodeClasses.length; j++) {
  5005. if( reClass.test(nodeClasses[j]) ) {
  5006. if( classMatchType == dojo.html.classMatchType.ContainsAny ) {
  5007. nodes.push(node);
  5008. continue outer;
  5009. } else {
  5010. matches++;
  5011. }
  5012. } else {
  5013. if( classMatchType == dojo.html.classMatchType.IsOnly ) {
  5014. continue outer;
  5015. }
  5016. }
  5017. }
  5018. if( matches == classes.length ) {
  5019. if( classMatchType == dojo.html.classMatchType.IsOnly && matches == nodeClasses.length ) {
  5020. nodes.push(node);
  5021. } else if( classMatchType == dojo.html.classMatchType.ContainsAll ) {
  5022. nodes.push(node);
  5023. }
  5024. }
  5025. }
  5026. return nodes;
  5027. }
  5028. dojo.html.getElementsByClassName = dojo.html.getElementsByClass;
  5029. /**
  5030. * Calculates the mouse's direction of gravity relative to the centre
  5031. * of the given node.
  5032. * <p>
  5033. * If you wanted to insert a node into a DOM tree based on the mouse
  5034. * position you might use the following code:
  5035. * <pre>
  5036. * if (gravity(node, e) & gravity.NORTH) { [insert before]; }
  5037. * else { [insert after]; }
  5038. * </pre>
  5039. *
  5040. * @param node The node
  5041. * @param e The event containing the mouse coordinates
  5042. * @return The directions, NORTH or SOUTH and EAST or WEST. These
  5043. * are properties of the function.
  5044. */
  5045. dojo.html.gravity = function(node, e){
  5046. var mousex = e.pageX || e.clientX + dojo.html.body().scrollLeft;
  5047. var mousey = e.pageY || e.clientY + dojo.html.body().scrollTop;
  5048. with (dojo.html) {
  5049. var nodecenterx = getAbsoluteX(node) + (getInnerWidth(node) / 2);
  5050. var nodecentery = getAbsoluteY(node) + (getInnerHeight(node) / 2);
  5051. }
  5052. with (dojo.html.gravity) {
  5053. return ((mousex < nodecenterx ? WEST : EAST) |
  5054. (mousey < nodecentery ? NORTH : SOUTH));
  5055. }
  5056. }
  5057. dojo.html.gravity.NORTH = 1;
  5058. dojo.html.gravity.SOUTH = 1 << 1;
  5059. dojo.html.gravity.EAST = 1 << 2;
  5060. dojo.html.gravity.WEST = 1 << 3;
  5061. dojo.html.overElement = function(element, e){
  5062. var mousex = e.pageX || e.clientX + dojo.html.body().scrollLeft;
  5063. var mousey = e.pageY || e.clientY + dojo.html.body().scrollTop;
  5064. with(dojo.html){
  5065. var top = getAbsoluteY(element);
  5066. var bottom = top + getInnerHeight(element);
  5067. var left = getAbsoluteX(element);
  5068. var right = left + getInnerWidth(element);
  5069. }
  5070. return (mousex >= left && mousex <= right &&
  5071. mousey >= top && mousey <= bottom);
  5072. }
  5073. /**
  5074. * Attempts to return the text as it would be rendered, with the line breaks
  5075. * sorted out nicely. Unfinished.
  5076. */
  5077. dojo.html.renderedTextContent = function(node){
  5078. var result = "";
  5079. if (node == null) { return result; }
  5080. for (var i = 0; i < node.childNodes.length; i++) {
  5081. switch (node.childNodes[i].nodeType) {
  5082. case 1: // ELEMENT_NODE
  5083. case 5: // ENTITY_REFERENCE_NODE
  5084. var display = "unknown";
  5085. try {
  5086. display = dojo.style.getStyle(node.childNodes[i], "display");
  5087. } catch(E) {}
  5088. switch (display) {
  5089. case "block": case "list-item": case "run-in":
  5090. case "table": case "table-row-group": case "table-header-group":
  5091. case "table-footer-group": case "table-row": case "table-column-group":
  5092. case "table-column": case "table-cell": case "table-caption":
  5093. // TODO: this shouldn't insert double spaces on aligning blocks
  5094. result += "\n";
  5095. result += dojo.html.renderedTextContent(node.childNodes[i]);
  5096. result += "\n";
  5097. break;
  5098. case "none": break;
  5099. default:
  5100. if(node.childNodes[i].tagName && node.childNodes[i].tagName.toLowerCase() == "br") {
  5101. result += "\n";
  5102. } else {
  5103. result += dojo.html.renderedTextContent(node.childNodes[i]);
  5104. }
  5105. break;
  5106. }
  5107. break;
  5108. case 3: // TEXT_NODE
  5109. case 2: // ATTRIBUTE_NODE
  5110. case 4: // CDATA_SECTION_NODE
  5111. var text = node.childNodes[i].nodeValue;
  5112. var textTransform = "unknown";
  5113. try {
  5114. textTransform = dojo.style.getStyle(node, "text-transform");
  5115. } catch(E) {}
  5116. switch (textTransform){
  5117. case "capitalize": text = dojo.string.capitalize(text); break;
  5118. case "uppercase": text = text.toUpperCase(); break;
  5119. case "lowercase": text = text.toLowerCase(); break;
  5120. default: break; // leave as is
  5121. }
  5122. // TODO: implement
  5123. switch (textTransform){
  5124. case "nowrap": break;
  5125. case "pre-wrap": break;
  5126. case "pre-line": break;
  5127. case "pre": break; // leave as is
  5128. default:
  5129. // remove whitespace and collapse first space
  5130. text = text.replace(/\s+/, " ");
  5131. if (/\s$/.test(result)) { text.replace(/^\s/, ""); }
  5132. break;
  5133. }
  5134. result += text;
  5135. break;
  5136. default:
  5137. break;
  5138. }
  5139. }
  5140. return result;
  5141. }
  5142. dojo.html.setActiveStyleSheet = function(title){
  5143. var i, a, main;
  5144. for(i=0; (a = document.getElementsByTagName("link")[i]); i++){
  5145. if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")){
  5146. a.disabled = true;
  5147. if (a.getAttribute("title") == title) { a.disabled = false; }
  5148. }
  5149. }
  5150. }
  5151. dojo.html.getActiveStyleSheet = function(){
  5152. var i, a;
  5153. // FIXME: getElementsByTagName returns a live collection. This seems like a
  5154. // bad key for iteration.
  5155. for(i=0; (a = document.getElementsByTagName("link")[i]); i++){
  5156. if (a.getAttribute("rel").indexOf("style") != -1 &&
  5157. a.getAttribute("title") && !a.disabled) { return a.getAttribute("title"); }
  5158. }
  5159. return null;
  5160. }
  5161. dojo.html.getPreferredStyleSheet = function(){
  5162. var i, a;
  5163. for(i=0; (a = document.getElementsByTagName("link")[i]); i++){
  5164. if(a.getAttribute("rel").indexOf("style") != -1
  5165. && a.getAttribute("rel").indexOf("alt") == -1
  5166. && a.getAttribute("title")) { return a.getAttribute("title"); }
  5167. }
  5168. return null;
  5169. }
  5170. dojo.html.body = function(){
  5171. return document.body || document.getElementsByTagName("body")[0];
  5172. }
  5173. dojo.html.createNodesFromText = function(txt, wrap){
  5174. var tn = document.createElement("div");
  5175. // tn.style.display = "none";
  5176. tn.style.visibility= "hidden";
  5177. document.body.appendChild(tn);
  5178. tn.innerHTML = txt;
  5179. tn.normalize();
  5180. if(wrap){
  5181. var ret = [];
  5182. // start hack
  5183. var fc = tn.firstChild;
  5184. ret[0] = ((fc.nodeValue == " ")||(fc.nodeValue == "\t")) ? fc.nextSibling : fc;
  5185. // end hack
  5186. // tn.style.display = "none";
  5187. document.body.removeChild(tn);
  5188. return ret;
  5189. }
  5190. var nodes = [];
  5191. for(var x=0; x<tn.childNodes.length; x++){
  5192. nodes.push(tn.childNodes[x].cloneNode(true));
  5193. }
  5194. tn.style.display = "none";
  5195. document.body.removeChild(tn);
  5196. return nodes;
  5197. }
  5198. // FIXME: this should be removed after 0.2 release
  5199. if(!dojo.evalObjPath("dojo.dom.createNodesFromText")){
  5200. dojo.dom.createNodesFromText = function() {
  5201. dojo.deprecated("dojo.dom.createNodesFromText", "use dojo.html.createNodesFromText instead");
  5202. return dojo.html.createNodesFromText.apply(dojo.html, arguments);
  5203. }
  5204. }
  5205. dojo.html.isVisible = function(node){
  5206. // FIXME: this should also look at visibility!
  5207. return dojo.style.getComputedStyle(node||this.domNode, "display") != "none";
  5208. }
  5209. dojo.html.show = function(node){
  5210. if(node.style){
  5211. node.style.display = dojo.lang.inArray(['tr', 'td', 'th'], node.tagName.toLowerCase()) ? "" : "block";
  5212. }
  5213. }
  5214. dojo.html.hide = function(node){
  5215. if(node.style){
  5216. node.style.display = "none";
  5217. }
  5218. }
  5219. // in: coordinate array [x,y,w,h] or dom node
  5220. // return: coordinate array
  5221. dojo.html.toCoordinateArray = function(coords, includeScroll) {
  5222. if(dojo.lang.isArray(coords)){
  5223. // coords is already an array (of format [x,y,w,h]), just return it
  5224. while ( coords.length < 4 ) { coords.push(0); }
  5225. while ( coords.length > 4 ) { coords.pop(); }
  5226. var ret = coords;
  5227. } else {
  5228. // coords is an dom object (or dom object id); return it's coordinates
  5229. var node = dojo.byId(coords);
  5230. var ret = [
  5231. dojo.html.getAbsoluteX(node, includeScroll),
  5232. dojo.html.getAbsoluteY(node, includeScroll),
  5233. dojo.html.getInnerWidth(node),
  5234. dojo.html.getInnerHeight(node)
  5235. ];
  5236. }
  5237. ret.x = ret[0];
  5238. ret.y = ret[1];
  5239. ret.w = ret[2];
  5240. ret.h = ret[3];
  5241. return ret;
  5242. };
  5243. /* TODO: merge placeOnScreen and placeOnScreenPoint to make 1 function that allows you
  5244. * to define which corner(s) you want to bind to. Something like so:
  5245. *
  5246. * kes(node, desiredX, desiredY, "TR")
  5247. * kes(node, [desiredX, desiredY], ["TR", "BL"])
  5248. *
  5249. * TODO: make this function have variable call sigs
  5250. *
  5251. * kes(node, ptArray, cornerArray, padding, hasScroll)
  5252. * kes(node, ptX, ptY, cornerA, cornerB, cornerC, paddingArray, hasScroll)
  5253. */
  5254. /**
  5255. * Keeps 'node' in the visible area of the screen while trying to
  5256. * place closest to desiredX, desiredY. The input coordinates are
  5257. * expected to be the desired screen position, not accounting for
  5258. * scrolling. If you already accounted for scrolling, set 'hasScroll'
  5259. * to true. Set padding to either a number or array for [paddingX, paddingY]
  5260. * to put some buffer around the element you want to position.
  5261. * NOTE: node is assumed to be absolutely or relatively positioned.
  5262. *
  5263. * Alternate call sig:
  5264. * placeOnScreen(node, [x, y], padding, hasScroll)
  5265. *
  5266. * Examples:
  5267. * placeOnScreen(node, 100, 200)
  5268. * placeOnScreen("myId", [800, 623], 5)
  5269. * placeOnScreen(node, 234, 3284, [2, 5], true)
  5270. */
  5271. dojo.html.placeOnScreen = function(node, desiredX, desiredY, padding, hasScroll) {
  5272. if(dojo.lang.isArray(desiredX)) {
  5273. hasScroll = padding;
  5274. padding = desiredY;
  5275. desiredY = desiredX[1];
  5276. desiredX = desiredX[0];
  5277. }
  5278. if(!isNaN(padding)) {
  5279. padding = [Number(padding), Number(padding)];
  5280. } else if(!dojo.lang.isArray(padding)) {
  5281. padding = [0, 0];
  5282. }
  5283. var scroll = dojo.html.getScrollOffset();
  5284. var view = dojo.html.getViewportSize();
  5285. node = dojo.byId(node);
  5286. var w = node.offsetWidth + padding[0];
  5287. var h = node.offsetHeight + padding[1];
  5288. if(hasScroll) {
  5289. desiredX -= scroll.x;
  5290. desiredY -= scroll.y;
  5291. }
  5292. var x = desiredX + w;
  5293. if(x > view.w) {
  5294. x = view.w - w;
  5295. } else {
  5296. x = desiredX;
  5297. }
  5298. x = Math.max(padding[0], x) + scroll.x;
  5299. var y = desiredY + h;
  5300. if(y > view.h) {
  5301. y = view.h - h;
  5302. } else {
  5303. y = desiredY;
  5304. }
  5305. y = Math.max(padding[1], y) + scroll.y;
  5306. node.style.left = x + "px";
  5307. node.style.top = y + "px";
  5308. var ret = [x, y];
  5309. ret.x = x;
  5310. ret.y = y;
  5311. return ret;
  5312. }
  5313. /**
  5314. * Like placeOnScreenPoint except that it attempts to keep one of the node's
  5315. * corners at desiredX, desiredY. Also note that padding is only taken into
  5316. * account if none of the corners can be kept and thus placeOnScreenPoint falls
  5317. * back to placeOnScreen to place the node.
  5318. *
  5319. * Examples placing node at mouse position (where e = [Mouse event]):
  5320. * placeOnScreenPoint(node, e.clientX, e.clientY);
  5321. */
  5322. dojo.html.placeOnScreenPoint = function(node, desiredX, desiredY, padding, hasScroll) {
  5323. if(dojo.lang.isArray(desiredX)) {
  5324. hasScroll = padding;
  5325. padding = desiredY;
  5326. desiredY = desiredX[1];
  5327. desiredX = desiredX[0];
  5328. }
  5329. var scroll = dojo.html.getScrollOffset();
  5330. var view = dojo.html.getViewportSize();
  5331. node = dojo.byId(node);
  5332. var w = node.offsetWidth;
  5333. var h = node.offsetHeight;
  5334. if(hasScroll) {
  5335. desiredX -= scroll.x;
  5336. desiredY -= scroll.y;
  5337. }
  5338. var x = -1, y = -1;
  5339. //dojo.debug(desiredX + w, "<=", view.w, "&&", desiredY + h, "<=", view.h);
  5340. if(desiredX + w <= view.w && desiredY + h <= view.h) { // TL
  5341. x = desiredX;
  5342. y = desiredY;
  5343. //dojo.debug("TL", x, y);
  5344. }
  5345. //dojo.debug(desiredX, "<=", view.w, "&&", desiredY + h, "<=", view.h);
  5346. if((x < 0 || y < 0) && desiredX <= view.w && desiredY + h <= view.h) { // TR
  5347. x = desiredX - w;
  5348. y = desiredY;
  5349. //dojo.debug("TR", x, y);
  5350. }
  5351. //dojo.debug(desiredX + w, "<=", view.w, "&&", desiredY, "<=", view.h);
  5352. if((x < 0 || y < 0) && desiredX + w <= view.w && desiredY <= view.h) { // BL
  5353. x = desiredX;
  5354. y = desiredY - h;
  5355. //dojo.debug("BL", x, y);
  5356. }
  5357. //dojo.debug(desiredX, "<=", view.w, "&&", desiredY, "<=", view.h);
  5358. if((x < 0 || y < 0) && desiredX <= view.w && desiredY <= view.h) { // BR
  5359. x = desiredX - w;
  5360. y = desiredY - h;
  5361. //dojo.debug("BR", x, y);
  5362. }
  5363. if(x < 0 || y < 0 || (x + w > view.w) || (y + h > view.h)) {
  5364. return dojo.html.placeOnScreen(node, desiredX, desiredY, padding, hasScroll);
  5365. }
  5366. x += scroll.x;
  5367. y += scroll.y;
  5368. node.style.left = x + "px";
  5369. node.style.top = y + "px";
  5370. var ret = [x, y];
  5371. ret.x = x;
  5372. ret.y = y;
  5373. return ret;
  5374. }
  5375. /**
  5376. * For IE z-index schenanigans
  5377. * See Dialog widget for sample use
  5378. */
  5379. dojo.html.BackgroundIframe = function() {
  5380. if(this.ie) {
  5381. this.iframe = document.createElement("<iframe frameborder='0' src='about:blank'>");
  5382. var s = this.iframe.style;
  5383. s.position = "absolute";
  5384. s.left = s.top = "0px";
  5385. s.zIndex = 2;
  5386. s.display = "none";
  5387. dojo.style.setOpacity(this.iframe, 0.0);
  5388. dojo.html.body().appendChild(this.iframe);
  5389. } else {
  5390. this.enabled = false;
  5391. }
  5392. }
  5393. dojo.lang.extend(dojo.html.BackgroundIframe, {
  5394. ie: dojo.render.html.ie,
  5395. enabled: true,
  5396. visibile: false,
  5397. iframe: null,
  5398. sizeNode: null,
  5399. sizeCoords: null,
  5400. size: function(node /* or coords */) {
  5401. if(!this.ie || !this.enabled) { return; }
  5402. if(dojo.dom.isNode(node)) {
  5403. this.sizeNode = node;
  5404. } else if(arguments.length > 0) {
  5405. this.sizeNode = null;
  5406. this.sizeCoords = node;
  5407. }
  5408. this.update();
  5409. },
  5410. update: function() {
  5411. if(!this.ie || !this.enabled) { return; }
  5412. if(this.sizeNode) {
  5413. this.sizeCoords = dojo.html.toCoordinateArray(this.sizeNode, true);
  5414. } else if(this.sizeCoords) {
  5415. this.sizeCoords = dojo.html.toCoordinateArray(this.sizeCoords, true);
  5416. } else {
  5417. return;
  5418. }
  5419. var s = this.iframe.style;
  5420. var dims = this.sizeCoords;
  5421. s.width = dims.w + "px";
  5422. s.height = dims.h + "px";
  5423. s.left = dims.x + "px";
  5424. s.top = dims.y + "px";
  5425. },
  5426. setZIndex: function(node /* or number */) {
  5427. if(!this.ie || !this.enabled) { return; }
  5428. if(dojo.dom.isNode(node)) {
  5429. this.iframe.zIndex = dojo.html.getStyle(node, "z-index") - 1;
  5430. } else if(!isNaN(node)) {
  5431. this.iframe.zIndex = node;
  5432. }
  5433. },
  5434. show: function(node /* or coords */) {
  5435. if(!this.ie || !this.enabled) { return; }
  5436. this.size(node);
  5437. this.iframe.style.display = "block";
  5438. },
  5439. hide: function() {
  5440. if(!this.ie) { return; }
  5441. var s = this.iframe.style;
  5442. s.display = "none";
  5443. s.width = s.height = "1px";
  5444. },
  5445. remove: function() {
  5446. dojo.dom.removeNode(this.iframe);
  5447. }
  5448. });
  5449. dojo.provide("dojo.math.curves");
  5450. dojo.require("dojo.math");
  5451. /* Curves from Dan's 13th lib stuff.
  5452. * See: http://pupius.co.uk/js/Toolkit.Drawing.js
  5453. * http://pupius.co.uk/dump/dojo/Dojo.Math.js
  5454. */
  5455. dojo.math.curves = {
  5456. //Creates a straight line object
  5457. Line: function(start, end) {
  5458. this.start = start;
  5459. this.end = end;
  5460. this.dimensions = start.length;
  5461. for(var i = 0; i < start.length; i++) {
  5462. start[i] = Number(start[i]);
  5463. }
  5464. for(var i = 0; i < end.length; i++) {
  5465. end[i] = Number(end[i]);
  5466. }
  5467. //simple function to find point on an n-dimensional, straight line
  5468. this.getValue = function(n) {
  5469. var retVal = new Array(this.dimensions);
  5470. for(var i=0;i<this.dimensions;i++)
  5471. retVal[i] = ((this.end[i] - this.start[i]) * n) + this.start[i];
  5472. return retVal;
  5473. }
  5474. return this;
  5475. },
  5476. //Takes an array of points, the first is the start point, the last is end point and the ones in
  5477. //between are the Bezier control points.
  5478. Bezier: function(pnts) {
  5479. this.getValue = function(step) {
  5480. if(step >= 1) return this.p[this.p.length-1]; // if step>=1 we must be at the end of the curve
  5481. if(step <= 0) return this.p[0]; // if step<=0 we must be at the start of the curve
  5482. var retVal = new Array(this.p[0].length);
  5483. for(var k=0;j<this.p[0].length;k++) { retVal[k]=0; }
  5484. for(var j=0;j<this.p[0].length;j++) {
  5485. var C=0; var D=0;
  5486. for(var i=0;i<this.p.length;i++) {
  5487. C += this.p[i][j] * this.p[this.p.length-1][0]
  5488. * dojo.math.bernstein(step,this.p.length,i);
  5489. }
  5490. for(var l=0;l<this.p.length;l++) {
  5491. D += this.p[this.p.length-1][0] * dojo.math.bernstein(step,this.p.length,l);
  5492. }
  5493. retVal[j] = C/D;
  5494. }
  5495. return retVal;
  5496. }
  5497. this.p = pnts;
  5498. return this;
  5499. },
  5500. //Catmull-Rom Spline - allows you to interpolate a smooth curve through a set of points in n-dimensional space
  5501. CatmullRom : function(pnts,c) {
  5502. this.getValue = function(step) {
  5503. var percent = step * (this.p.length-1);
  5504. var node = Math.floor(percent);
  5505. var progress = percent - node;
  5506. var i0 = node-1; if(i0 < 0) i0 = 0;
  5507. var i = node;
  5508. var i1 = node+1; if(i1 >= this.p.length) i1 = this.p.length-1;
  5509. var i2 = node+2; if(i2 >= this.p.length) i2 = this.p.length-1;
  5510. var u = progress;
  5511. var u2 = progress*progress;
  5512. var u3 = progress*progress*progress;
  5513. var retVal = new Array(this.p[0].length);
  5514. for(var k=0;k<this.p[0].length;k++) {
  5515. var x1 = ( -this.c * this.p[i0][k] ) + ( (2 - this.c) * this.p[i][k] ) + ( (this.c-2) * this.p[i1][k] ) + ( this.c * this.p[i2][k] );
  5516. var x2 = ( 2 * this.c * this.p[i0][k] ) + ( (this.c-3) * this.p[i][k] ) + ( (3 - 2 * this.c) * this.p[i1][k] ) + ( -this.c * this.p[i2][k] );
  5517. var x3 = ( -this.c * this.p[i0][k] ) + ( this.c * this.p[i1][k] );
  5518. var x4 = this.p[i][k];
  5519. retVal[k] = x1*u3 + x2*u2 + x3*u + x4;
  5520. }
  5521. return retVal;
  5522. }
  5523. if(!c) this.c = 0.7;
  5524. else this.c = c;
  5525. this.p = pnts;
  5526. return this;
  5527. },
  5528. // FIXME: This is the bad way to do a partial-arc with 2 points. We need to have the user
  5529. // supply the radius, otherwise we always get a half-circle between the two points.
  5530. Arc : function(start, end, ccw) {
  5531. var center = dojo.math.points.midpoint(start, end);
  5532. var sides = dojo.math.points.translate(dojo.math.points.invert(center), start);
  5533. var rad = Math.sqrt(Math.pow(sides[0], 2) + Math.pow(sides[1], 2));
  5534. var theta = dojo.math.radToDeg(Math.atan(sides[1]/sides[0]));
  5535. if( sides[0] < 0 ) {
  5536. theta -= 90;
  5537. } else {
  5538. theta += 90;
  5539. }
  5540. dojo.math.curves.CenteredArc.call(this, center, rad, theta, theta+(ccw?-180:180));
  5541. },
  5542. // Creates an arc object, with center and radius (Top of arc = 0 degrees, increments clockwise)
  5543. // center => 2D point for center of arc
  5544. // radius => scalar quantity for radius of arc
  5545. // start => to define an arc specify start angle (default: 0)
  5546. // end => to define an arc specify start angle
  5547. CenteredArc : function(center, radius, start, end) {
  5548. this.center = center;
  5549. this.radius = radius;
  5550. this.start = start || 0;
  5551. this.end = end;
  5552. this.getValue = function(n) {
  5553. var retVal = new Array(2);
  5554. var theta = dojo.math.degToRad(this.start+((this.end-this.start)*n));
  5555. retVal[0] = this.center[0] + this.radius*Math.sin(theta);
  5556. retVal[1] = this.center[1] - this.radius*Math.cos(theta);
  5557. return retVal;
  5558. }
  5559. return this;
  5560. },
  5561. // Special case of Arc (start = 0, end = 360)
  5562. Circle : function(center, radius) {
  5563. dojo.math.curves.CenteredArc.call(this, center, radius, 0, 360);
  5564. return this;
  5565. },
  5566. Path : function() {
  5567. var curves = [];
  5568. var weights = [];
  5569. var ranges = [];
  5570. var totalWeight = 0;
  5571. this.add = function(curve, weight) {
  5572. if( weight < 0 ) { dojo.raise("dojo.math.curves.Path.add: weight cannot be less than 0"); }
  5573. curves.push(curve);
  5574. weights.push(weight);
  5575. totalWeight += weight;
  5576. computeRanges();
  5577. }
  5578. this.remove = function(curve) {
  5579. for(var i = 0; i < curves.length; i++) {
  5580. if( curves[i] == curve ) {
  5581. curves.splice(i, 1);
  5582. totalWeight -= weights.splice(i, 1)[0];
  5583. break;
  5584. }
  5585. }
  5586. computeRanges();
  5587. }
  5588. this.removeAll = function() {
  5589. curves = [];
  5590. weights = [];
  5591. totalWeight = 0;
  5592. }
  5593. this.getValue = function(n) {
  5594. var found = false, value = 0;
  5595. for(var i = 0; i < ranges.length; i++) {
  5596. var r = ranges[i];
  5597. //w(r.join(" ... "));
  5598. if( n >= r[0] && n < r[1] ) {
  5599. var subN = (n - r[0]) / r[2];
  5600. value = curves[i].getValue(subN);
  5601. found = true;
  5602. break;
  5603. }
  5604. }
  5605. // FIXME: Do we want to assume we're at the end?
  5606. if( !found ) {
  5607. value = curves[curves.length-1].getValue(1);
  5608. }
  5609. for(j = 0; j < i; j++) {
  5610. value = dojo.math.points.translate(value, curves[j].getValue(1));
  5611. }
  5612. return value;
  5613. }
  5614. function computeRanges() {
  5615. var start = 0;
  5616. for(var i = 0; i < weights.length; i++) {
  5617. var end = start + weights[i] / totalWeight;
  5618. var len = end - start;
  5619. ranges[i] = [start, end, len];
  5620. start = end;
  5621. }
  5622. }
  5623. return this;
  5624. }
  5625. };
  5626. dojo.provide("dojo.animation");
  5627. dojo.provide("dojo.animation.Animation");
  5628. dojo.require("dojo.lang");
  5629. dojo.require("dojo.math");
  5630. dojo.require("dojo.math.curves");
  5631. /*
  5632. Animation package based off of Dan Pupius' work on Animations:
  5633. http://pupius.co.uk/js/Toolkit.Drawing.js
  5634. */
  5635. dojo.animation.Animation = function(curve, duration, accel, repeatCount, rate) {
  5636. // public properties
  5637. this.curve = curve;
  5638. this.duration = duration;
  5639. this.repeatCount = repeatCount || 0;
  5640. this.rate = rate || 10;
  5641. if(accel) {
  5642. if(dojo.lang.isFunction(accel.getValue)) {
  5643. this.accel = accel;
  5644. } else {
  5645. var i = 0.35*accel+0.5; // 0.15 <= i <= 0.85
  5646. this.accel = new dojo.math.curves.CatmullRom([[0], [i], [1]], 0.45);
  5647. }
  5648. }
  5649. }
  5650. dojo.lang.extend(dojo.animation.Animation, {
  5651. // public properties
  5652. curve: null,
  5653. duration: 0,
  5654. repeatCount: 0,
  5655. accel: null,
  5656. // events
  5657. onBegin: null,
  5658. onAnimate: null,
  5659. onEnd: null,
  5660. onPlay: null,
  5661. onPause: null,
  5662. onStop: null,
  5663. handler: null,
  5664. // "private" properties
  5665. _animSequence: null,
  5666. _startTime: null,
  5667. _endTime: null,
  5668. _lastFrame: null,
  5669. _timer: null,
  5670. _percent: 0,
  5671. _active: false,
  5672. _paused: false,
  5673. _startRepeatCount: 0,
  5674. // public methods
  5675. play: function(gotoStart) {
  5676. if( gotoStart ) {
  5677. clearTimeout(this._timer);
  5678. this._active = false;
  5679. this._paused = false;
  5680. this._percent = 0;
  5681. } else if( this._active && !this._paused ) {
  5682. return;
  5683. }
  5684. this._startTime = new Date().valueOf();
  5685. if( this._paused ) {
  5686. this._startTime -= (this.duration * this._percent / 100);
  5687. }
  5688. this._endTime = this._startTime + this.duration;
  5689. this._lastFrame = this._startTime;
  5690. var e = new dojo.animation.AnimationEvent(this, null, this.curve.getValue(this._percent),
  5691. this._startTime, this._startTime, this._endTime, this.duration, this._percent, 0);
  5692. this._active = true;
  5693. this._paused = false;
  5694. if( this._percent == 0 ) {
  5695. if(!this._startRepeatCount) {
  5696. this._startRepeatCount = this.repeatCount;
  5697. }
  5698. e.type = "begin";
  5699. if(typeof this.handler == "function") { this.handler(e); }
  5700. if(typeof this.onBegin == "function") { this.onBegin(e); }
  5701. }
  5702. e.type = "play";
  5703. if(typeof this.handler == "function") { this.handler(e); }
  5704. if(typeof this.onPlay == "function") { this.onPlay(e); }
  5705. if(this._animSequence) { this._animSequence._setCurrent(this); }
  5706. //dojo.lang.hitch(this, cycle)();
  5707. this._cycle();
  5708. },
  5709. pause: function() {
  5710. clearTimeout(this._timer);
  5711. if( !this._active ) { return; }
  5712. this._paused = true;
  5713. var e = new dojo.animation.AnimationEvent(this, "pause", this.curve.getValue(this._percent),
  5714. this._startTime, new Date().valueOf(), this._endTime, this.duration, this._percent, 0);
  5715. if(typeof this.handler == "function") { this.handler(e); }
  5716. if(typeof this.onPause == "function") { this.onPause(e); }
  5717. },
  5718. playPause: function() {
  5719. if( !this._active || this._paused ) {
  5720. this.play();
  5721. } else {
  5722. this.pause();
  5723. }
  5724. },
  5725. gotoPercent: function(pct, andPlay) {
  5726. clearTimeout(this._timer);
  5727. this._active = true;
  5728. this._paused = true;
  5729. this._percent = pct;
  5730. if( andPlay ) { this.play(); }
  5731. },
  5732. stop: function(gotoEnd) {
  5733. clearTimeout(this._timer);
  5734. var step = this._percent / 100;
  5735. if( gotoEnd ) {
  5736. step = 1;
  5737. }
  5738. var e = new dojo.animation.AnimationEvent(this, "stop", this.curve.getValue(step),
  5739. this._startTime, new Date().valueOf(), this._endTime, this.duration, this._percent, Math.round(fps));
  5740. if(typeof this.handler == "function") { this.handler(e); }
  5741. if(typeof this.onStop == "function") { this.onStop(e); }
  5742. this._active = false;
  5743. this._paused = false;
  5744. },
  5745. status: function() {
  5746. if( this._active ) {
  5747. return this._paused ? "paused" : "playing";
  5748. } else {
  5749. return "stopped";
  5750. }
  5751. },
  5752. // "private" methods
  5753. _cycle: function() {
  5754. clearTimeout(this._timer);
  5755. if( this._active ) {
  5756. var curr = new Date().valueOf();
  5757. var step = (curr - this._startTime) / (this._endTime - this._startTime);
  5758. fps = 1000 / (curr - this._lastFrame);
  5759. this._lastFrame = curr;
  5760. if( step >= 1 ) {
  5761. step = 1;
  5762. this._percent = 100;
  5763. } else {
  5764. this._percent = step * 100;
  5765. }
  5766. // Perform accelleration
  5767. if(this.accel && this.accel.getValue) {
  5768. step = this.accel.getValue(step);
  5769. }
  5770. var e = new dojo.animation.AnimationEvent(this, "animate", this.curve.getValue(step),
  5771. this._startTime, curr, this._endTime, this.duration, this._percent, Math.round(fps));
  5772. if(typeof this.handler == "function") { this.handler(e); }
  5773. if(typeof this.onAnimate == "function") { this.onAnimate(e); }
  5774. if( step < 1 ) {
  5775. this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
  5776. } else {
  5777. e.type = "end";
  5778. this._active = false;
  5779. if(typeof this.handler == "function") { this.handler(e); }
  5780. if(typeof this.onEnd == "function") { this.onEnd(e); }
  5781. if( this.repeatCount > 0 ) {
  5782. this.repeatCount--;
  5783. this.play(true);
  5784. } else if( this.repeatCount == -1 ) {
  5785. this.play(true);
  5786. } else {
  5787. if(this._startRepeatCount) {
  5788. this.repeatCount = this._startRepeatCount;
  5789. this._startRepeatCount = 0;
  5790. }
  5791. if( this._animSequence ) {
  5792. this._animSequence._playNext();
  5793. }
  5794. }
  5795. }
  5796. }
  5797. }
  5798. });
  5799. dojo.animation.AnimationEvent = function(anim, type, coords, sTime, cTime, eTime, dur, pct, fps) {
  5800. this.type = type; // "animate", "begin", "end", "play", "pause", "stop"
  5801. this.animation = anim;
  5802. this.coords = coords;
  5803. this.x = coords[0];
  5804. this.y = coords[1];
  5805. this.z = coords[2];
  5806. this.startTime = sTime;
  5807. this.currentTime = cTime;
  5808. this.endTime = eTime;
  5809. this.duration = dur;
  5810. this.percent = pct;
  5811. this.fps = fps;
  5812. };
  5813. dojo.lang.extend(dojo.animation.AnimationEvent, {
  5814. coordsAsInts: function() {
  5815. var cints = new Array(this.coords.length);
  5816. for(var i = 0; i < this.coords.length; i++) {
  5817. cints[i] = Math.round(this.coords[i]);
  5818. }
  5819. return cints;
  5820. }
  5821. });
  5822. dojo.animation.AnimationSequence = function(repeatCount) {
  5823. this.repeatCount = repeatCount || 0;
  5824. }
  5825. dojo.lang.extend(dojo.animation.AnimationSequence, {
  5826. repeateCount: 0,
  5827. _anims: [],
  5828. _currAnim: -1,
  5829. onBegin: null,
  5830. onEnd: null,
  5831. onNext: null,
  5832. handler: null,
  5833. add: function() {
  5834. for(var i = 0; i < arguments.length; i++) {
  5835. this._anims.push(arguments[i]);
  5836. arguments[i]._animSequence = this;
  5837. }
  5838. },
  5839. remove: function(anim) {
  5840. for(var i = 0; i < this._anims.length; i++) {
  5841. if( this._anims[i] == anim ) {
  5842. this._anims[i]._animSequence = null;
  5843. this._anims.splice(i, 1);
  5844. break;
  5845. }
  5846. }
  5847. },
  5848. removeAll: function() {
  5849. for(var i = 0; i < this._anims.length; i++) {
  5850. this._anims[i]._animSequence = null;
  5851. }
  5852. this._anims = [];
  5853. this._currAnim = -1;
  5854. },
  5855. clear: function() {
  5856. this.removeAll();
  5857. },
  5858. play: function(gotoStart) {
  5859. if( this._anims.length == 0 ) { return; }
  5860. if( gotoStart || !this._anims[this._currAnim] ) {
  5861. this._currAnim = 0;
  5862. }
  5863. if( this._anims[this._currAnim] ) {
  5864. if( this._currAnim == 0 ) {
  5865. var e = {type: "begin", animation: this._anims[this._currAnim]};
  5866. if(typeof this.handler == "function") { this.handler(e); }
  5867. if(typeof this.onBegin == "function") { this.onBegin(e); }
  5868. }
  5869. this._anims[this._currAnim].play(gotoStart);
  5870. }
  5871. },
  5872. pause: function() {
  5873. if( this._anims[this._currAnim] ) {
  5874. this._anims[this._currAnim].pause();
  5875. }
  5876. },
  5877. playPause: function() {
  5878. if( this._anims.length == 0 ) { return; }
  5879. if( this._currAnim == -1 ) { this._currAnim = 0; }
  5880. if( this._anims[this._currAnim] ) {
  5881. this._anims[this._currAnim].playPause();
  5882. }
  5883. },
  5884. stop: function() {
  5885. if( this._anims[this._currAnim] ) {
  5886. this._anims[this._currAnim].stop();
  5887. }
  5888. },
  5889. status: function() {
  5890. if( this._anims[this._currAnim] ) {
  5891. return this._anims[this._currAnim].status();
  5892. } else {
  5893. return "stopped";
  5894. }
  5895. },
  5896. _setCurrent: function(anim) {
  5897. for(var i = 0; i < this._anims.length; i++) {
  5898. if( this._anims[i] == anim ) {
  5899. this._currAnim = i;
  5900. break;
  5901. }
  5902. }
  5903. },
  5904. _playNext: function() {
  5905. if( this._currAnim == -1 || this._anims.length == 0 ) { return; }
  5906. this._currAnim++;
  5907. if( this._anims[this._currAnim] ) {
  5908. var e = {type: "next", animation: this._anims[this._currAnim]};
  5909. if(typeof this.handler == "function") { this.handler(e); }
  5910. if(typeof this.onNext == "function") { this.onNext(e); }
  5911. this._anims[this._currAnim].play(true);
  5912. } else {
  5913. var e = {type: "end", animation: this._anims[this._anims.length-1]};
  5914. if(typeof this.handler == "function") { this.handler(e); }
  5915. if(typeof this.onEnd == "function") { this.onEnd(e); }
  5916. if(this.repeatCount > 0) {
  5917. this._currAnim = 0;
  5918. this.repeatCount--;
  5919. this._anims[this._currAnim].play(true);
  5920. } else if(this.repeatCount == -1) {
  5921. this._currAnim = 0;
  5922. this._anims[this._currAnim].play(true);
  5923. } else {
  5924. this._currAnim = -1;
  5925. }
  5926. }
  5927. }
  5928. });
  5929. dojo.hostenv.conditionalLoadModule({
  5930. common: ["dojo.animation.Animation", false, false]
  5931. });
  5932. dojo.hostenv.moduleLoaded("dojo.animation.*");
  5933. dojo.provide("dojo.fx.html");
  5934. dojo.require("dojo.html");
  5935. dojo.require("dojo.style");
  5936. dojo.require("dojo.lang");
  5937. dojo.require("dojo.animation.*");
  5938. dojo.require("dojo.event.*");
  5939. dojo.require("dojo.graphics.color");
  5940. dojo.fx.html._makeFadeable = function(node){
  5941. if(dojo.render.html.ie){
  5942. // only set the zoom if the "tickle" value would be the same as the
  5943. // default
  5944. if( (node.style.zoom.length == 0) &&
  5945. (dojo.style.getStyle(node, "zoom") == "normal") ){
  5946. // make sure the node "hasLayout"
  5947. // NOTE: this has been tested with larger and smaller user-set text
  5948. // sizes and works fine
  5949. node.style.zoom = "1";
  5950. // node.style.zoom = "normal";
  5951. }
  5952. // don't set the width to auto if it didn't already cascade that way.
  5953. // We don't want to f anyones designs
  5954. if( (node.style.width.length == 0) &&
  5955. (dojo.style.getStyle(node, "width") == "auto") ){
  5956. node.style.width = "auto";
  5957. }
  5958. }
  5959. }
  5960. dojo.fx.html.fadeOut = function(node, duration, callback, dontPlay) {
  5961. return dojo.fx.html.fade(node, duration, dojo.style.getOpacity(node), 0, callback, dontPlay);
  5962. };
  5963. dojo.fx.html.fadeIn = function(node, duration, callback, dontPlay) {
  5964. return dojo.fx.html.fade(node, duration, dojo.style.getOpacity(node), 1, callback, dontPlay);
  5965. };
  5966. dojo.fx.html.fadeHide = function(node, duration, callback, dontPlay) {
  5967. node = dojo.byId(node);
  5968. if(!duration) { duration = 150; } // why not have a default?
  5969. return dojo.fx.html.fadeOut(node, duration, function(node) {
  5970. node.style.display = "none";
  5971. if(typeof callback == "function") { callback(node); }
  5972. });
  5973. };
  5974. dojo.fx.html.fadeShow = function(node, duration, callback, dontPlay) {
  5975. node = dojo.byId(node);
  5976. if(!duration) { duration = 150; } // why not have a default?
  5977. node.style.display = "block";
  5978. return dojo.fx.html.fade(node, duration, 0, 1, callback, dontPlay);
  5979. };
  5980. dojo.fx.html.fade = function(node, duration, startOpac, endOpac, callback, dontPlay) {
  5981. node = dojo.byId(node);
  5982. dojo.fx.html._makeFadeable(node);
  5983. var anim = new dojo.animation.Animation(
  5984. new dojo.math.curves.Line([startOpac],[endOpac]),
  5985. duration, 0);
  5986. dojo.event.connect(anim, "onAnimate", function(e) {
  5987. dojo.style.setOpacity(node, e.x);
  5988. });
  5989. if(callback) {
  5990. dojo.event.connect(anim, "onEnd", function(e) {
  5991. callback(node, anim);
  5992. });
  5993. }
  5994. if(!dontPlay) { anim.play(true); }
  5995. return anim;
  5996. };
  5997. dojo.fx.html.slideTo = function(node, duration, endCoords, callback, dontPlay) {
  5998. if(!dojo.lang.isNumber(duration)) {
  5999. var tmp = duration;
  6000. duration = endCoords;
  6001. endCoords = tmp;
  6002. }
  6003. node = dojo.byId(node);
  6004. var top = node.offsetTop;
  6005. var left = node.offsetLeft;
  6006. var pos = dojo.style.getComputedStyle(node, 'position');
  6007. if (pos == 'relative' || pos == 'static') {
  6008. top = parseInt(dojo.style.getComputedStyle(node, 'top')) || 0;
  6009. left = parseInt(dojo.style.getComputedStyle(node, 'left')) || 0;
  6010. }
  6011. return dojo.fx.html.slide(node, duration, [left, top],
  6012. endCoords, callback, dontPlay);
  6013. };
  6014. dojo.fx.html.slideBy = function(node, duration, coords, callback, dontPlay) {
  6015. if(!dojo.lang.isNumber(duration)) {
  6016. var tmp = duration;
  6017. duration = coords;
  6018. coords = tmp;
  6019. }
  6020. node = dojo.byId(node);
  6021. var top = node.offsetTop;
  6022. var left = node.offsetLeft;
  6023. var pos = dojo.style.getComputedStyle(node, 'position');
  6024. if (pos == 'relative' || pos == 'static') {
  6025. top = parseInt(dojo.style.getComputedStyle(node, 'top')) || 0;
  6026. left = parseInt(dojo.style.getComputedStyle(node, 'left')) || 0;
  6027. }
  6028. return dojo.fx.html.slideTo(node, duration, [left+coords[0], top+coords[1]],
  6029. callback, dontPlay);
  6030. };
  6031. dojo.fx.html.slide = function(node, duration, startCoords, endCoords, callback, dontPlay) {
  6032. if(!dojo.lang.isNumber(duration)) {
  6033. var tmp = duration;
  6034. duration = endCoords;
  6035. endCoords = startCoords;
  6036. startCoords = tmp;
  6037. }
  6038. node = dojo.byId(node);
  6039. if (dojo.style.getComputedStyle(node, 'position') == 'static') {
  6040. node.style.position = 'relative';
  6041. }
  6042. var anim = new dojo.animation.Animation(
  6043. new dojo.math.curves.Line(startCoords, endCoords),
  6044. duration, 0);
  6045. dojo.event.connect(anim, "onAnimate", function(e) {
  6046. with( node.style ) {
  6047. left = e.x + "px";
  6048. top = e.y + "px";
  6049. }
  6050. });
  6051. if(callback) {
  6052. dojo.event.connect(anim, "onEnd", function(e) {
  6053. callback(node, anim);
  6054. });
  6055. }
  6056. if(!dontPlay) { anim.play(true); }
  6057. return anim;
  6058. };
  6059. // Fade from startColor to the node's background color
  6060. dojo.fx.html.colorFadeIn = function(node, duration, startColor, delay, callback, dontPlay) {
  6061. if(!dojo.lang.isNumber(duration)) {
  6062. var tmp = duration;
  6063. duration = startColor;
  6064. startColor = tmp;
  6065. }
  6066. node = dojo.byId(node);
  6067. var color = dojo.html.getBackgroundColor(node);
  6068. var bg = dojo.style.getStyle(node, "background-color").toLowerCase();
  6069. var wasTransparent = bg == "transparent" || bg == "rgba(0, 0, 0, 0)";
  6070. while(color.length > 3) { color.pop(); }
  6071. var rgb = new dojo.graphics.color.Color(startColor).toRgb();
  6072. var anim = dojo.fx.html.colorFade(node, duration, startColor, color, callback, true);
  6073. dojo.event.connect(anim, "onEnd", function(e) {
  6074. if( wasTransparent ) {
  6075. node.style.backgroundColor = "transparent";
  6076. }
  6077. });
  6078. if( delay > 0 ) {
  6079. node.style.backgroundColor = "rgb(" + rgb.join(",") + ")";
  6080. if(!dontPlay) { setTimeout(function(){anim.play(true)}, delay); }
  6081. } else {
  6082. if(!dontPlay) { anim.play(true); }
  6083. }
  6084. return anim;
  6085. };
  6086. // alias for (probably?) common use/terminology
  6087. dojo.fx.html.highlight = dojo.fx.html.colorFadeIn;
  6088. dojo.fx.html.colorFadeFrom = dojo.fx.html.colorFadeIn;
  6089. // Fade from node's background color to endColor
  6090. dojo.fx.html.colorFadeOut = function(node, duration, endColor, delay, callback, dontPlay) {
  6091. if(!dojo.lang.isNumber(duration)) {
  6092. var tmp = duration;
  6093. duration = endColor;
  6094. endColor = tmp;
  6095. }
  6096. node = dojo.byId(node);
  6097. var color = new dojo.graphics.color.Color(dojo.html.getBackgroundColor(node)).toRgb();
  6098. var rgb = new dojo.graphics.color.Color(endColor).toRgb();
  6099. var anim = dojo.fx.html.colorFade(node, duration, color, rgb, callback, delay > 0 || dontPlay);
  6100. if( delay > 0 ) {
  6101. node.style.backgroundColor = "rgb(" + color.join(",") + ")";
  6102. if(!dontPlay) { setTimeout(function(){anim.play(true)}, delay); }
  6103. }
  6104. return anim;
  6105. };
  6106. // FIXME: not sure which name is better. an alias here may be bad.
  6107. dojo.fx.html.unhighlight = dojo.fx.html.colorFadeOut;
  6108. dojo.fx.html.colorFadeTo = dojo.fx.html.colorFadeOut;
  6109. // Fade node background from startColor to endColor
  6110. dojo.fx.html.colorFade = function(node, duration, startColor, endColor, callback, dontPlay) {
  6111. if(!dojo.lang.isNumber(duration)) {
  6112. var tmp = duration;
  6113. duration = endColor;
  6114. endColor = startColor;
  6115. startColor = tmp;
  6116. }
  6117. node = dojo.byId(node);
  6118. var startRgb = new dojo.graphics.color.Color(startColor).toRgb();
  6119. var endRgb = new dojo.graphics.color.Color(endColor).toRgb();
  6120. var anim = new dojo.animation.Animation(
  6121. new dojo.math.curves.Line(startRgb, endRgb),
  6122. duration, 0);
  6123. dojo.event.connect(anim, "onAnimate", function(e) {
  6124. node.style.backgroundColor = "rgb(" + e.coordsAsInts().join(",") + ")";
  6125. });
  6126. if(callback) {
  6127. dojo.event.connect(anim, "onEnd", function(e) {
  6128. callback(node, anim);
  6129. });
  6130. }
  6131. if( !dontPlay ) { anim.play(true); }
  6132. return anim;
  6133. };
  6134. dojo.fx.html.wipeIn = function(node, duration, callback, dontPlay) {
  6135. node = dojo.byId(node);
  6136. var savedHeight = dojo.html.getStyle(node, "height");
  6137. var dispType = dojo.lang.inArray(node.tagName.toLowerCase(), ['tr', 'td', 'th']) ? "" : "block";
  6138. node.style.display = dispType;
  6139. var height = node.offsetHeight;
  6140. var anim = dojo.fx.html.wipeInToHeight(node, duration, height, function(e) {
  6141. node.style.height = savedHeight || "auto";
  6142. if(callback) { callback(node, anim); }
  6143. }, dontPlay);
  6144. };
  6145. dojo.fx.html.wipeInToHeight = function(node, duration, height, callback, dontPlay) {
  6146. node = dojo.byId(node);
  6147. var savedOverflow = dojo.html.getStyle(node, "overflow");
  6148. // FIXME: should we be setting display to something other than "" for the table elements?
  6149. node.style.height = "0px";
  6150. node.style.display = "none";
  6151. if(savedOverflow == "visible") {
  6152. node.style.overflow = "hidden";
  6153. }
  6154. var dispType = dojo.lang.inArray(node.tagName.toLowerCase(), ['tr', 'td', 'th']) ? "" : "block";
  6155. node.style.display = dispType;
  6156. var anim = new dojo.animation.Animation(
  6157. new dojo.math.curves.Line([0], [height]),
  6158. duration, 0);
  6159. dojo.event.connect(anim, "onAnimate", function(e) {
  6160. node.style.height = Math.round(e.x) + "px";
  6161. });
  6162. dojo.event.connect(anim, "onEnd", function(e) {
  6163. if(savedOverflow != "visible") {
  6164. node.style.overflow = savedOverflow;
  6165. }
  6166. if(callback) { callback(node, anim); }
  6167. });
  6168. if( !dontPlay ) { anim.play(true); }
  6169. return anim;
  6170. }
  6171. dojo.fx.html.wipeOut = function(node, duration, callback, dontPlay) {
  6172. node = dojo.byId(node);
  6173. var savedOverflow = dojo.html.getStyle(node, "overflow");
  6174. var savedHeight = dojo.html.getStyle(node, "height");
  6175. var height = node.offsetHeight;
  6176. node.style.overflow = "hidden";
  6177. var anim = new dojo.animation.Animation(
  6178. new dojo.math.curves.Line([height], [0]),
  6179. duration, 0);
  6180. dojo.event.connect(anim, "onAnimate", function(e) {
  6181. node.style.height = Math.round(e.x) + "px";
  6182. });
  6183. dojo.event.connect(anim, "onEnd", function(e) {
  6184. node.style.display = "none";
  6185. node.style.overflow = savedOverflow;
  6186. node.style.height = savedHeight || "auto";
  6187. if(callback) { callback(node, anim); }
  6188. });
  6189. if( !dontPlay ) { anim.play(true); }
  6190. return anim;
  6191. };
  6192. dojo.fx.html.explode = function(start, endNode, duration, callback, dontPlay) {
  6193. var startCoords = dojo.html.toCoordinateArray(start);
  6194. var outline = document.createElement("div");
  6195. with(outline.style) {
  6196. position = "absolute";
  6197. border = "1px solid black";
  6198. display = "none";
  6199. }
  6200. dojo.html.body().appendChild(outline);
  6201. endNode = dojo.byId(endNode);
  6202. with(endNode.style) {
  6203. visibility = "hidden";
  6204. display = "block";
  6205. }
  6206. var endCoords = dojo.html.toCoordinateArray(endNode);
  6207. with(endNode.style) {
  6208. display = "none";
  6209. visibility = "visible";
  6210. }
  6211. var anim = new dojo.animation.Animation(
  6212. new dojo.math.curves.Line(startCoords, endCoords),
  6213. duration, 0
  6214. );
  6215. dojo.event.connect(anim, "onBegin", function(e) {
  6216. outline.style.display = "block";
  6217. });
  6218. dojo.event.connect(anim, "onAnimate", function(e) {
  6219. with(outline.style) {
  6220. left = e.x + "px";
  6221. top = e.y + "px";
  6222. width = e.coords[2] + "px";
  6223. height = e.coords[3] + "px";
  6224. }
  6225. });
  6226. dojo.event.connect(anim, "onEnd", function() {
  6227. endNode.style.display = "block";
  6228. outline.parentNode.removeChild(outline);
  6229. if(callback) { callback(endNode, anim); }
  6230. });
  6231. if(!dontPlay) { anim.play(); }
  6232. return anim;
  6233. };
  6234. dojo.fx.html.implode = function(startNode, end, duration, callback, dontPlay) {
  6235. var startCoords = dojo.html.toCoordinateArray(startNode);
  6236. var endCoords = dojo.html.toCoordinateArray(end);
  6237. startNode = dojo.byId(startNode);
  6238. var outline = document.createElement("div");
  6239. with(outline.style) {
  6240. position = "absolute";
  6241. border = "1px solid black";
  6242. display = "none";
  6243. }
  6244. dojo.html.body().appendChild(outline);
  6245. var anim = new dojo.animation.Animation(
  6246. new dojo.math.curves.Line(startCoords, endCoords),
  6247. duration, 0
  6248. );
  6249. dojo.event.connect(anim, "onBegin", function(e) {
  6250. startNode.style.display = "none";
  6251. outline.style.display = "block";
  6252. });
  6253. dojo.event.connect(anim, "onAnimate", function(e) {
  6254. with(outline.style) {
  6255. left = e.x + "px";
  6256. top = e.y + "px";
  6257. width = e.coords[2] + "px";
  6258. height = e.coords[3] + "px";
  6259. }
  6260. });
  6261. dojo.event.connect(anim, "onEnd", function() {
  6262. outline.parentNode.removeChild(outline);
  6263. if(callback) { callback(startNode, anim); }
  6264. });
  6265. if(!dontPlay) { anim.play(); }
  6266. return anim;
  6267. };
  6268. dojo.fx.html.Exploder = function(triggerNode, boxNode) {
  6269. triggerNode = dojo.byId(triggerNode);
  6270. boxNode = dojo.byId(boxNode);
  6271. var _this = this;
  6272. // custom options
  6273. this.waitToHide = 500;
  6274. this.timeToShow = 100;
  6275. this.waitToShow = 200;
  6276. this.timeToHide = 70;
  6277. this.autoShow = false;
  6278. this.autoHide = false;
  6279. var animShow = null;
  6280. var animHide = null;
  6281. var showTimer = null;
  6282. var hideTimer = null;
  6283. var startCoords = null;
  6284. var endCoords = null;
  6285. this.showing = false;
  6286. this.onBeforeExplode = null;
  6287. this.onAfterExplode = null;
  6288. this.onBeforeImplode = null;
  6289. this.onAfterImplode = null;
  6290. this.onExploding = null;
  6291. this.onImploding = null;
  6292. this.timeShow = function() {
  6293. clearTimeout(showTimer);
  6294. showTimer = setTimeout(_this.show, _this.waitToShow);
  6295. }
  6296. this.show = function() {
  6297. clearTimeout(showTimer);
  6298. clearTimeout(hideTimer);
  6299. //triggerNode.blur();
  6300. if( (animHide && animHide.status() == "playing")
  6301. || (animShow && animShow.status() == "playing")
  6302. || _this.showing ) { return; }
  6303. if(typeof _this.onBeforeExplode == "function") { _this.onBeforeExplode(triggerNode, boxNode); }
  6304. animShow = dojo.fx.html.explode(triggerNode, boxNode, _this.timeToShow, function(e) {
  6305. _this.showing = true;
  6306. if(typeof _this.onAfterExplode == "function") { _this.onAfterExplode(triggerNode, boxNode); }
  6307. });
  6308. if(typeof _this.onExploding == "function") {
  6309. dojo.event.connect(animShow, "onAnimate", this, "onExploding");
  6310. }
  6311. }
  6312. this.timeHide = function() {
  6313. clearTimeout(showTimer);
  6314. clearTimeout(hideTimer);
  6315. if(_this.showing) {
  6316. hideTimer = setTimeout(_this.hide, _this.waitToHide);
  6317. }
  6318. }
  6319. this.hide = function() {
  6320. clearTimeout(showTimer);
  6321. clearTimeout(hideTimer);
  6322. if( animShow && animShow.status() == "playing" ) {
  6323. return;
  6324. }
  6325. _this.showing = false;
  6326. if(typeof _this.onBeforeImplode == "function") { _this.onBeforeImplode(triggerNode, boxNode); }
  6327. animHide = dojo.fx.html.implode(boxNode, triggerNode, _this.timeToHide, function(e){
  6328. if(typeof _this.onAfterImplode == "function") { _this.onAfterImplode(triggerNode, boxNode); }
  6329. });
  6330. if(typeof _this.onImploding == "function") {
  6331. dojo.event.connect(animHide, "onAnimate", this, "onImploding");
  6332. }
  6333. }
  6334. // trigger events
  6335. dojo.event.connect(triggerNode, "onclick", function(e) {
  6336. if(_this.showing) {
  6337. _this.hide();
  6338. } else {
  6339. _this.show();
  6340. }
  6341. });
  6342. dojo.event.connect(triggerNode, "onmouseover", function(e) {
  6343. if(_this.autoShow) {
  6344. _this.timeShow();
  6345. }
  6346. });
  6347. dojo.event.connect(triggerNode, "onmouseout", function(e) {
  6348. if(_this.autoHide) {
  6349. _this.timeHide();
  6350. }
  6351. });
  6352. // box events
  6353. dojo.event.connect(boxNode, "onmouseover", function(e) {
  6354. clearTimeout(hideTimer);
  6355. });
  6356. dojo.event.connect(boxNode, "onmouseout", function(e) {
  6357. if(_this.autoHide) {
  6358. _this.timeHide();
  6359. }
  6360. });
  6361. // document events
  6362. dojo.event.connect(document.documentElement || dojo.html.body(), "onclick", function(e) {
  6363. if(_this.autoHide && _this.showing
  6364. && !dojo.dom.isDescendantOf(e.target, boxNode)
  6365. && !dojo.dom.isDescendantOf(e.target, triggerNode) ) {
  6366. _this.hide();
  6367. }
  6368. });
  6369. return this;
  6370. };
  6371. dojo.lang.mixin(dojo.fx, dojo.fx.html);
  6372. dojo.hostenv.conditionalLoadModule({
  6373. browser: ["dojo.fx.html"]
  6374. });
  6375. dojo.hostenv.moduleLoaded("dojo.fx.*");
  6376. dojo.provide("dojo.graphics.htmlEffects");
  6377. dojo.require("dojo.fx.*");
  6378. dj_deprecated("dojo.graphics.htmlEffects is deprecated, use dojo.fx.html instead");
  6379. dojo.graphics.htmlEffects = dojo.fx.html;
  6380. dojo.hostenv.conditionalLoadModule({
  6381. browser: ["dojo.graphics.htmlEffects"]
  6382. });
  6383. dojo.hostenv.moduleLoaded("dojo.graphics.*");