if(typeof dojo == "undefined"){ /** * @file bootstrap1.js * * summary: First file that is loaded that 'bootstraps' the entire dojo library suite. * note: Must run before hostenv_*.js file. * * @author Copyright 2004 Mark D. Anderson (mda@discerning.com) * TODOC: should the copyright be changed to Dojo Foundation? * @license Licensed under the Academic Free License 2.1 http://www.opensource.org/licenses/afl-2.1.php * * $Id: dojo.js.uncompressed.js,v 1.1 2006/09/08 05:57:55 penguinc Exp $ */ // TODOC: HOW TO DOC THE BELOW? // @global: djConfig // summary: // Application code can set the global 'djConfig' prior to loading // the library to override certain global settings for how dojo works. // description: The variables that can be set are as follows: // - isDebug: false // - allowQueryConfig: false // - baseScriptUri: "" // - baseRelativePath: "" // - libraryScriptUri: "" // - iePreventClobber: false // - ieClobberMinimal: true // - locale: undefined // - extraLocale: undefined // - preventBackButtonFix: true // - searchIds: [] // - parseWidgets: true // TODOC: HOW TO DOC THESE VARIABLES? // TODOC: IS THIS A COMPLETE LIST? // note: // 'djConfig' does not exist under 'dojo.*' so that it can be set before the // 'dojo' variable exists. // note: // Setting any of these variables *after* the library has loaded does nothing at all. // TODOC: is this still true? Release notes for 0.3 indicated they could be set after load. // //TODOC: HOW TO DOC THIS? // @global: dj_global // summary: // an alias for the top-level global object in the host environment // (e.g., the window object in a browser). // description: // Refer to 'dj_global' rather than referring to window to ensure your // code runs correctly in contexts other than web browsers (eg: Rhino on a server). // TODO: replace this with dojo._currentContext var dj_global = this; function dj_undef(/*String*/ name, /*Object?*/ object){ //summary: Returns true if 'name' is defined on 'object' (or globally if 'object' is null). //description: Note that 'defined' and 'exists' are not the same concept. //Before dojo.global() is defined, object can not be null if(object==null){ object = dojo.global(); } // exception if object is not an Object return (typeof object[name] == "undefined"); // Boolean } // make sure djConfig is defined if(dj_undef("djConfig", this)){ var djConfig = {}; } //TODOC: HOW TO DOC THIS? // dojo is the root variable of (almost all) our public symbols -- make sure it is defined. if(dj_undef("dojo", this)){ var dojo = {}; } //These are private variables, and should not be used; use dojo.global() and dojo.doc() instead //this variable should probably have a better name dojo._currentContext = this; if(!dj_undef("document", dojo._currentContext)){ dojo._currentDocument = this.document; } // Override locale setting, if specified dojo.locale = djConfig.locale; //TODOC: HOW TO DOC THIS? dojo.version = { // summary: version number of this instance of dojo. major: 0, minor: 0, patch: 0, flag: "dev", revision: Number("$Rev: 4898 $".match(/[0-9]+/)[0]), toString: function(){ with(dojo.version){ return major + "." + minor + "." + patch + flag + " (" + revision + ")"; // String } } } dojo.evalProp = function(/*String*/ name, /*Object*/ object, /*Boolean?*/ create){ // summary: Returns 'object[name]'. If not defined and 'create' is true, will return a new Object. // description: // Returns null if 'object[name]' is not defined and 'create' is not true. // Note: 'defined' and 'exists' are not the same concept. return (object && !dj_undef(name, object) ? object[name] : (create ? (object[name]={}) : undefined)); // mixed } dojo.parseObjPath = function(/*String*/ path, /*Object?*/ context, /*Boolean?*/ create){ // summary: Parse string path to an object, and return corresponding object reference and property name. // description: // Returns an object with two properties, 'obj' and 'prop'. // 'obj[prop]' is the reference indicated by 'path'. // path: Path to an object, in the form "A.B.C". // context: Object to use as root of path. Defaults to 'dj_global'. // create: If true, Objects will be created at any point along the 'path' that is undefined. var object = (context != null ? context : dj_global); var names = path.split('.'); var prop = names.pop(); for (var i=0,l=names.length;i 1) { dh.modulesLoadedListeners.push(function() { obj[fcnName](); }); } //Added for xdomain loading. dojo.addOnLoad is used to //indicate callbacks after doing some dojo.require() statements. //In the xdomain case, if all the requires are loaded (after initial //page load), then immediately call any listeners. if(dh.post_load_ && dh.inFlightCount == 0 && !dh.loadNotifying){ dh.callLoaded(); } } dojo.addOnUnload = function(obj, fcnName){ var dh = dojo.hostenv; if(arguments.length == 1){ dh.unloadListeners.push(obj); } else if(arguments.length > 1) { dh.unloadListeners.push(function() { obj[fcnName](); }); } } dojo.hostenv.modulesLoaded = function(){ if(this.post_load_){ return; } if((this.loadUriStack.length==0)&&(this.getTextStack.length==0)){ if(this.inFlightCount > 0){ dojo.debug("files still in flight!"); return; } dojo.hostenv.callLoaded(); } } dojo.hostenv.callLoaded = function(){ if(typeof setTimeout == "object"){ setTimeout("dojo.hostenv.loaded();", 0); }else{ dojo.hostenv.loaded(); } } dojo.hostenv.getModuleSymbols = function(modulename) { var syms = modulename.split("."); for(var i = syms.length - 1; i > 0; i--){ var parentModule = syms.slice(0, i).join("."); var parentModulePath = this.getModulePrefix(parentModule); if(parentModulePath != parentModule){ syms.splice(0, i, parentModulePath); break; } } return syms; } //list of all defined namespaces dojo._namespaces = {}; (function(){ //list of namespaces being loaded, to prevent recursion var loadingNamespaces = {}; //list of all namespaces that were needed, but didn't have the required file in the dojo/src/namespaces folder. //This list ensures that a namespace will only be looked for once, rather than repeatedly trying to load the namespace descriptor file var failedNamespaces = {}; //This returns a namespace with the given short name. If the namespace has not been loaded already, it tries to load it. dojo.getNamespace = function(nsPrefix){ if(!dojo._namespaces[nsPrefix] && !failedNamespaces[nsPrefix]){ var req = dojo.require; var nsFile = "dojo.namespaces."+nsPrefix; if(!loadingNamespaces[nsFile]){ loadingNamespaces[nsFile]=true; req(nsFile, false, true); loadingNamespaces[nsFile]=false; if(!dojo._namespaces[nsPrefix]){ failedNamespaces[nsPrefix] = true; //only look for a namespace once } } } return dojo._namespaces[nsPrefix]; }; })(); /** * loadModule("A.B") first checks to see if symbol A.B is defined. * If it is, it is simply returned (nothing to do). * * If it is not defined, it will look for "A/B.js" in the script root directory, * followed by "A.js". * * It throws if it cannot find a file to load, or if the symbol A.B is not * defined after loading. * * It returns the object A.B. * * This does nothing about importing symbols into the current package. * It is presumed that the caller will take care of that. For example, to import * all symbols: * * with (dojo.hostenv.loadModule("A.B")) { * ... * } * * And to import just the leaf symbol: * * var B = dojo.hostenv.loadModule("A.B"); * ... * * dj_load is an alias for dojo.hostenv.loadModule */ dojo.hostenv._global_omit_module_check = false; dojo.hostenv.loadModule = function(modulename, exact_only, omit_module_check){ if(!modulename){ return; } omit_module_check = this._global_omit_module_check || omit_module_check; var module = this.findModule(modulename, false); if(module){ return module; } // protect against infinite recursion from mutual dependencies if(dj_undef(modulename, this.loading_modules_)){ this.addedToLoadingCount.push(modulename); } this.loading_modules_[modulename] = 1; // convert periods to slashes var relpath = modulename.replace(/\./g, '/') + '.js'; var nsyms = modulename.split("."); if(djConfig.autoLoadNamespace){ dojo.getNamespace(nsyms[0]); } var syms = this.getModuleSymbols(modulename); var startedRelative = ((syms[0].charAt(0) != '/')&&(!syms[0].match(/^\w+:/))); var last = syms[syms.length - 1]; // figure out if we're looking for a full package, if so, we want to do // things slightly diffrently if(last=="*"){ modulename = (nsyms.slice(0, -1)).join('.'); while(syms.length){ syms.pop(); syms.push(this.pkgFileName); relpath = syms.join("/") + '.js'; if(startedRelative && (relpath.charAt(0)=="/")){ relpath = relpath.slice(1); } ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null)); if(ok){ break; } syms.pop(); } }else{ relpath = syms.join("/") + '.js'; modulename = nsyms.join('.'); var ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null)); if((!ok)&&(!exact_only)){ syms.pop(); while(syms.length){ relpath = syms.join('/') + '.js'; ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null)); if(ok){ break; } syms.pop(); relpath = syms.join('/') + '/'+this.pkgFileName+'.js'; if(startedRelative && (relpath.charAt(0)=="/")){ relpath = relpath.slice(1); } ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null)); if(ok){ break; } } } if((!ok)&&(!omit_module_check)){ dojo.raise("Could not load '" + modulename + "'; last tried '" + relpath + "'"); } } // check that the symbol was defined //Don't bother if we're doing xdomain (asynchronous) loading. if(!omit_module_check && !this["isXDomain"]){ // pass in false so we can give better error module = this.findModule(modulename, false); if(!module){ dojo.raise("symbol '" + modulename + "' is not defined after loading '" + relpath + "'"); } } return module; } /** * startPackage("A.B") follows the path, and at each level creates a new empty * object or uses what already exists. It returns the result. */ dojo.hostenv.startPackage = function(packname){ var modref = dojo.evalObjPath((packname.split(".").slice(0, -1)).join('.')); this.loaded_modules_[(new String(packname)).toLowerCase()] = modref; var syms = packname.split(/\./); if(syms[syms.length-1]=="*"){ syms.pop(); } return dojo.evalObjPath(syms.join("."), true); } /** * findModule("A.B") returns the object A.B if it exists, otherwise null. * @param modulename A string like 'A.B'. * @param must_exist Optional, defualt false. throw instead of returning null * if the module does not currently exist. */ dojo.hostenv.findModule = function(modulename, must_exist){ // check cache /* if(!dj_undef(modulename, this.modules_)){ return this.modules_[modulename]; } */ var lmn = (new String(modulename)).toLowerCase(); if(this.loaded_modules_[lmn]){ return this.loaded_modules_[lmn]; } // see if symbol is defined anyway var module = dojo.evalObjPath(modulename); if((modulename)&&(typeof module != 'undefined')&&(module)){ this.loaded_modules_[lmn] = module; return module; } if(must_exist){ dojo.raise("no loaded module named '" + modulename + "'"); } return null; } //Start of old bootstrap2: /* * This method taks a "map" of arrays which one can use to optionally load dojo * modules. The map is indexed by the possible dojo.hostenv.name_ values, with * two additional values: "default" and "common". The items in the "default" * array will be loaded if none of the other items have been choosen based on * the hostenv.name_ item. The items in the "common" array will _always_ be * loaded, regardless of which list is chosen. Here's how it's normally * called: * * dojo.kwCompoundRequire({ * browser: [ * ["foo.bar.baz", true, true], // an example that passes multiple args to loadModule() * "foo.sample.*", * "foo.test, * ], * default: [ "foo.sample.*" ], * common: [ "really.important.module.*" ] * }); */ dojo.kwCompoundRequire = function(modMap){ var common = modMap["common"]||[]; var result = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]); for(var x=0; x 1){ var paramStr = params[1]; var pairs = paramStr.split("&"); for(var x in pairs){ var sp = pairs[x].split("="); // FIXME: is this eval dangerous? if((sp[0].length > 9)&&(sp[0].substr(0, 9) == "djConfig.")){ var opt = sp[0].substr(9); try{ djConfig[opt]=eval(sp[1]); }catch(e){ djConfig[opt]=sp[1]; } } } } } if(((djConfig["baseScriptUri"] == "")||(djConfig["baseRelativePath"] == "")) &&(document && document.getElementsByTagName)){ var scripts = document.getElementsByTagName("script"); var rePkg = /(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i; for(var i = 0; i < scripts.length; i++) { var src = scripts[i].getAttribute("src"); if(!src) { continue; } var m = src.match(rePkg); if(m) { var root = src.substring(0, m.index); if(src.indexOf("bootstrap1") > -1) { root += "../"; } if(!this["djConfig"]) { djConfig = {}; } if(djConfig["baseScriptUri"] == "") { djConfig["baseScriptUri"] = root; } if(djConfig["baseRelativePath"] == "") { djConfig["baseRelativePath"] = root; } break; } } } // fill in the rendering support information in dojo.render.* var dr = dojo.render; var drh = dojo.render.html; var drs = dojo.render.svg; var dua = (drh.UA = navigator.userAgent); var dav = (drh.AV = navigator.appVersion); var t = true; var f = false; drh.capable = t; drh.support.builtin = t; dr.ver = parseFloat(drh.AV); dr.os.mac = dav.indexOf("Macintosh") >= 0; dr.os.win = dav.indexOf("Windows") >= 0; // could also be Solaris or something, but it's the same browser dr.os.linux = dav.indexOf("X11") >= 0; drh.opera = dua.indexOf("Opera") >= 0; drh.khtml = (dav.indexOf("Konqueror") >= 0)||(dav.indexOf("Safari") >= 0); drh.safari = dav.indexOf("Safari") >= 0; var geckoPos = dua.indexOf("Gecko"); drh.mozilla = drh.moz = (geckoPos >= 0)&&(!drh.khtml); if (drh.mozilla) { // gecko version is YYYYMMDD drh.geckoVersion = dua.substring(geckoPos + 6, geckoPos + 14); } drh.ie = (document.all)&&(!drh.opera); drh.ie50 = drh.ie && dav.indexOf("MSIE 5.0")>=0; drh.ie55 = drh.ie && dav.indexOf("MSIE 5.5")>=0; drh.ie60 = drh.ie && dav.indexOf("MSIE 6.0")>=0; drh.ie70 = drh.ie && dav.indexOf("MSIE 7.0")>=0; // TODO: is the HTML LANG attribute relevant? dojo.locale = dojo.locale || (drh.ie ? navigator.userLanguage : navigator.language).toLowerCase(); dr.vml.capable=drh.ie; drs.capable = f; drs.support.plugin = f; drs.support.builtin = f; var tdoc = window["document"]; var tdi = tdoc["implementation"]; if((tdi)&&(tdi["hasFeature"])&&(tdi.hasFeature("org.w3c.dom.svg", "1.0"))){ drs.capable = t; drs.support.builtin = t; drs.support.plugin = f; } // webkits after 420 support SVG natively. The test string is "AppleWebKit/420+" if(drh.safari){ var tmp = dua.split("AppleWebKit/")[1]; var ver = parseFloat(tmp.split(" ")[0]); if(ver >= 420){ drs.capable = t; drs.support.builtin = t; drs.support.plugin = f; } } })(); dojo.hostenv.startPackage("dojo.hostenv"); dojo.render.name = dojo.hostenv.name_ = 'browser'; dojo.hostenv.searchIds = []; // These are in order of decreasing likelihood; this will change in time. dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; dojo.hostenv.getXmlhttpObject = function(){ var http = null; var last_e = null; try{ http = new XMLHttpRequest(); }catch(e){} if(!http){ for(var i=0; i<3; ++i){ var progid = dojo.hostenv._XMLHTTP_PROGIDS[i]; try{ http = new ActiveXObject(progid); }catch(e){ last_e = e; } if(http){ dojo.hostenv._XMLHTTP_PROGIDS = [progid]; // so faster next time break; } } /*if(http && !http.toString) { http.toString = function() { "[object XMLHttpRequest]"; } }*/ } if(!http){ return dojo.raise("XMLHTTP not available", last_e); } return http; } /** * Read the contents of the specified uri and return those contents. * * @param uri A relative or absolute uri. If absolute, it still must be in the * same "domain" as we are. * * @param async_cb If not specified, load synchronously. If specified, load * asynchronously, and use async_cb as the progress handler which takes the * xmlhttp object as its argument. If async_cb, this function returns null. * * @param fail_ok Default false. If fail_ok and !async_cb and loading fails, * return null instead of throwing. */ dojo.hostenv._blockAsync = false; dojo.hostenv.getText = function(uri, async_cb, fail_ok){ // need to block async callbacks from snatching this thread as the result // of an async callback might call another sync XHR, this hangs khtml forever // hostenv._blockAsync must also be checked in BrowserIO's watchInFlight() // NOTE: must be declared before scope switches ie. this.getXmlhttpObject() if(!async_cb){ this._blockAsync = true; } var http = this.getXmlhttpObject(); function isDocumentOk(http){ var stat = http["status"]; // allow a 304 use cache, needed in konq (is this compliant with the http spec?) return Boolean((!stat)||((200 <= stat)&&(300 > stat))||(stat==304)); } if(async_cb){ var _this = this, timer = null, gbl = dojo.global(); var xhr = dojo.evalObjPath("dojo.io.XMLHTTPTransport"); http.onreadystatechange = function(){ if(timer){ gbl.clearTimeout(timer); timer = null; } if(_this._blockAsync || (xhr && xhr._blockAsync)){ timer = gbl.setTimeout(function () { http.onreadystatechange.apply(this); }, 10); }else{ if(4==http.readyState){ if(isDocumentOk(http)){ // dojo.debug("LOADED URI: "+uri); async_cb(http.responseText); } } } } } http.open('GET', uri, async_cb ? true : false); try{ http.send(null); if(async_cb){ return null; } if(!isDocumentOk(http)){ var err = Error("Unable to load "+uri+" status:"+ http.status); err.status = http.status; err.responseText = http.responseText; throw err; } }catch(e){ this._blockAsync = false; if((fail_ok)&&(!async_cb)){ return null; }else{ throw e; } } this._blockAsync = false; return http.responseText; } /* * It turns out that if we check *right now*, as this script file is being loaded, * then the last script element in the window DOM is ourselves. * That is because any subsequent script elements haven't shown up in the document * object yet. */ /* function dj_last_script_src() { var scripts = window.document.getElementsByTagName('script'); if(scripts.length < 1){ dojo.raise("No script elements in window.document, so can't figure out my script src"); } var script = scripts[scripts.length - 1]; var src = script.src; if(!src){ dojo.raise("Last script element (out of " + scripts.length + ") has no src"); } return src; } if(!dojo.hostenv["library_script_uri_"]){ dojo.hostenv.library_script_uri_ = dj_last_script_src(); } */ dojo.hostenv.defaultDebugContainerId = 'dojoDebug'; dojo.hostenv._println_buffer = []; dojo.hostenv._println_safe = false; dojo.hostenv.println = function (line){ if(!dojo.hostenv._println_safe){ dojo.hostenv._println_buffer.push(line); }else{ try { var console = document.getElementById(djConfig.debugContainerId ? djConfig.debugContainerId : dojo.hostenv.defaultDebugContainerId); if(!console) { console = dojo.body(); } var div = document.createElement("div"); div.appendChild(document.createTextNode(line)); console.appendChild(div); } catch (e) { try{ // safari needs the output wrapped in an element for some reason document.write("
" + line + "
"); }catch(e2){ window.status = line; } } } } dojo.addOnLoad(function(){ dojo.hostenv._println_safe = true; while(dojo.hostenv._println_buffer.length > 0){ dojo.hostenv.println(dojo.hostenv._println_buffer.shift()); } }); function dj_addNodeEvtHdlr(node, evtName, fp, capture){ var oldHandler = node["on"+evtName] || function(){}; node["on"+evtName] = function(){ fp.apply(node, arguments); oldHandler.apply(node, arguments); } return true; } /* Uncomment this to allow init after DOMLoad, not after window.onload // Mozilla exposes the event we could use if (dojo.render.html.mozilla) { document.addEventListener("DOMContentLoaded", dj_load_init, null); } // for Internet Explorer. readyState will not be achieved on init call, but dojo doesn't need it //Tighten up the comments below to allow init after DOMLoad, not after window.onload / * @cc_on @ * / / * @if (@_win32) document.write(", //which will be treated as an external javascript file in IE var xscript = dojo.doc().createElement('script'); xscript.src = "javascript:'dojo.html.createExternalElement=function(doc, tag){return doc.createElement(tag);}'"; dojo.doc().getElementsByTagName("head")[0].appendChild(xscript); })(); } }else{ //for other browsers, simply use document.createElement //is enough dojo.html.createExternalElement = function(doc, tag){ return doc.createElement(tag); } } dojo.html._callDeprecated = function(inFunc, replFunc, args, argName, retValue){ dojo.deprecated("dojo.html." + inFunc, "replaced by dojo.html." + replFunc + "(" + (argName ? "node, {"+ argName + ": " + argName + "}" : "" ) + ")" + (retValue ? "." + retValue : ""), "0.5"); var newArgs = []; if(argName){ var argsIn = {}; argsIn[argName] = args[1]; newArgs.push(args[0]); newArgs.push(argsIn); } else { newArgs = args } var ret = dojo.html[replFunc].apply(dojo.html, args); if(retValue){ return ret[retValue]; } else { return ret; } } dojo.html.getViewportWidth = function(){ return dojo.html._callDeprecated("getViewportWidth", "getViewport", arguments, null, "width"); } dojo.html.getViewportHeight = function(){ return dojo.html._callDeprecated("getViewportHeight", "getViewport", arguments, null, "height"); } dojo.html.getViewportSize = function(){ return dojo.html._callDeprecated("getViewportSize", "getViewport", arguments); } dojo.html.getScrollTop = function(){ return dojo.html._callDeprecated("getScrollTop", "getScroll", arguments, null, "top"); } dojo.html.getScrollLeft = function(){ return dojo.html._callDeprecated("getScrollLeft", "getScroll", arguments, null, "left"); } dojo.html.getScrollOffset = function(){ return dojo.html._callDeprecated("getScrollOffset", "getScroll", arguments, null, "offset"); } dojo.provide("dojo.html.layout"); dojo.html.sumAncestorProperties = function(node, prop){ node = dojo.byId(node); if(!node){ return 0; } // FIXME: throw an error? var retVal = 0; while(node){ if(dojo.html.getComputedStyle(node, 'position') == 'fixed'){ return 0; } var val = node[prop]; if(val){ retVal += val - 0; if(node==dojo.body()){ break; }// opera and khtml #body & #html has the same values, we only need one value } node = node.parentNode; } return retVal; } dojo.html.setStyleAttributes = function(node, attributes) { node = dojo.byId(node); var splittedAttribs=attributes.replace(/(;)?\s*$/, "").split(";"); for(var i=0; i0){ ret.x += isNaN(n) ? 0 : n; } var m = curnode["offsetTop"]; ret.y += isNaN(m) ? 0 : m; curnode = curnode.offsetParent; }while((curnode != endNode)&&(curnode != null)); }else if(node["x"]&&node["y"]){ ret.x += isNaN(node.x) ? 0 : node.x; ret.y += isNaN(node.y) ? 0 : node.y; } } // account for document scrolling! if(includeScroll){ var scroll = dojo.html.getScroll(); ret.y += scroll.top; ret.x += scroll.left; } var extentFuncArray=[dojo.html.getPaddingExtent, dojo.html.getBorderExtent, dojo.html.getMarginExtent]; if(nativeBoxType > targetBoxType){ for(var i=targetBoxType;inativeBoxType;--i){ ret.y -= extentFuncArray[i-1](node, 'top'); ret.x -= extentFuncArray[i-1](node, 'left'); } } ret.top = ret.y; ret.left = ret.x; return ret; } dojo.html.isPositionAbsolute = function(node){ return (dojo.html.getComputedStyle(node, 'position') == 'absolute') } dojo.html._sumPixelValues = function(node, selectors, autoIsZero){ var total = 0; for(var x=0; x 4 ) { coords.pop(); } var ret = { left: coords[0], top: coords[1], width: coords[2], height: coords[3] }; }else if(!coords.nodeType && !(coords instanceof String || typeof coords == "string") && ('width' in coords || 'height' in coords || 'left' in coords || 'x' in coords || 'top' in coords || 'y' in coords)){ // coords is a coordinate object or at least part of one var ret = { left: coords.left||coords.x||0, top: coords.top||coords.y||0, width: coords.width||0, height: coords.height||0 }; }else{ // coords is an dom object (or dom object id); return it's coordinates var node = dojo.byId(coords); var pos = dojo.html.abs(node, includeScroll); var marginbox = dojo.html.getMarginBox(node); var ret = { left: pos.left, top: pos.top, width: marginbox.width, height: marginbox.height }; } ret.x = ret.left; ret.y = ret.top; return ret; } dojo.html.setMarginBoxWidth = dojo.html.setOuterWidth = function(node, width){ return dojo.html._callDeprecated("setMarginBoxWidth", "setMarginBox", arguments, "width"); } dojo.html.setMarginBoxHeight = dojo.html.setOuterHeight = function(){ return dojo.html._callDeprecated("setMarginBoxHeight", "setMarginBox", arguments, "height"); } dojo.html.getMarginBoxWidth = dojo.html.getOuterWidth = function(){ return dojo.html._callDeprecated("getMarginBoxWidth", "getMarginBox", arguments, null, "width"); } dojo.html.getMarginBoxHeight = dojo.html.getOuterHeight = function(){ return dojo.html._callDeprecated("getMarginBoxHeight", "getMarginBox", arguments, null, "height"); } dojo.html.getTotalOffset = function(node, type, includeScroll){ return dojo.html._callDeprecated("getTotalOffset", "getAbsolutePosition", arguments, null, type); } dojo.html.getAbsoluteX = function(node, includeScroll){ return dojo.html._callDeprecated("getAbsoluteX", "getAbsolutePosition", arguments, null, "x"); } dojo.html.getAbsoluteY = function(node, includeScroll){ return dojo.html._callDeprecated("getAbsoluteY", "getAbsolutePosition", arguments, null, "y"); } dojo.html.totalOffsetLeft = function(node, includeScroll){ return dojo.html._callDeprecated("totalOffsetLeft", "getAbsolutePosition", arguments, null, "left"); } dojo.html.totalOffsetTop = function(node, includeScroll){ return dojo.html._callDeprecated("totalOffsetTop", "getAbsolutePosition", arguments, null, "top"); } dojo.html.getMarginWidth = function(node){ return dojo.html._callDeprecated("getMarginWidth", "getMargin", arguments, null, "width"); } dojo.html.getMarginHeight = function(node){ return dojo.html._callDeprecated("getMarginHeight", "getMargin", arguments, null, "height"); } dojo.html.getBorderWidth = function(node){ return dojo.html._callDeprecated("getBorderWidth", "getBorder", arguments, null, "width"); } dojo.html.getBorderHeight = function(node){ return dojo.html._callDeprecated("getBorderHeight", "getBorder", arguments, null, "height"); } dojo.html.getPaddingWidth = function(node){ return dojo.html._callDeprecated("getPaddingWidth", "getPadding", arguments, null, "width"); } dojo.html.getPaddingHeight = function(node){ return dojo.html._callDeprecated("getPaddingHeight", "getPadding", arguments, null, "height"); } dojo.html.getPadBorderWidth = function(node){ return dojo.html._callDeprecated("getPadBorderWidth", "getPadBorder", arguments, null, "width"); } dojo.html.getPadBorderHeight = function(node){ return dojo.html._callDeprecated("getPadBorderHeight", "getPadBorder", arguments, null, "height"); } dojo.html.getBorderBoxWidth = dojo.html.getInnerWidth = function(){ return dojo.html._callDeprecated("getBorderBoxWidth", "getBorderBox", arguments, null, "width"); } dojo.html.getBorderBoxHeight = dojo.html.getInnerHeight = function(){ return dojo.html._callDeprecated("getBorderBoxHeight", "getBorderBox", arguments, null, "height"); } dojo.html.getContentBoxWidth = dojo.html.getContentWidth = function(){ return dojo.html._callDeprecated("getContentBoxWidth", "getContentBox", arguments, null, "width"); } dojo.html.getContentBoxHeight = dojo.html.getContentHeight = function(){ return dojo.html._callDeprecated("getContentBoxHeight", "getContentBox", arguments, null, "height"); } dojo.html.setContentBoxWidth = dojo.html.setContentWidth = function(node, width){ return dojo.html._callDeprecated("setContentBoxWidth", "setContentBox", arguments, "width"); } dojo.html.setContentBoxHeight = dojo.html.setContentHeight = function(node, height){ return dojo.html._callDeprecated("setContentBoxHeight", "setContentBox", arguments, "height"); } dojo.provide("dojo.html.util"); // Get the window object where the element is placed in. dojo.html.getElementWindow = function(element){ return dojo.html.getDocumentWindow( element.ownerDocument ); } // Get window object associated with document doc dojo.html.getDocumentWindow = function(doc){ // With Safari, there is not wa to retrieve the window from the document, so we must fix it. if(dojo.render.html.safari && !doc._parentWindow){ /* This is a Safari specific function that fix the reference to the parent window from the document object. */ var fix=function(win){ win.document._parentWindow=win; for(var i=0; i * If you wanted to insert a node into a DOM tree based on the mouse * position you might use the following code: *
 * if (gravity(node, e) & gravity.NORTH) { [insert before]; }
 * else { [insert after]; }
 * 
* * @param node The node * @param e The event containing the mouse coordinates * @return The directions, NORTH or SOUTH and EAST or WEST. These * are properties of the function. */ dojo.html.gravity = function(node, e){ node = dojo.byId(node); var mouse = dojo.html.getCursorPosition(e); with (dojo.html) { var absolute = getAbsolutePosition(node, true); var bb = getBorderBox(node); var nodecenterx = absolute.x + (bb.width / 2); var nodecentery = absolute.y + (bb.height / 2); } with (dojo.html.gravity) { return ((mouse.x < nodecenterx ? WEST : EAST) | (mouse.y < nodecentery ? NORTH : SOUTH)); } } dojo.html.gravity.NORTH = 1; dojo.html.gravity.SOUTH = 1 << 1; dojo.html.gravity.EAST = 1 << 2; dojo.html.gravity.WEST = 1 << 3; dojo.html.overElement = function(element, e){ element = dojo.byId(element); var mouse = dojo.html.getCursorPosition(e); with(dojo.html){ var bb = getBorderBox(element); var absolute = getAbsolutePosition(element, true); var top = absolute.y; var bottom = top + bb.height; var left = absolute.x; var right = left + bb.width; } return (mouse.x >= left && mouse.x <= right && mouse.y >= top && mouse.y <= bottom); } /** * Attempts to return the text as it would be rendered, with the line breaks * sorted out nicely. Unfinished. */ dojo.html.renderedTextContent = function(node){ node = dojo.byId(node); var result = ""; if (node == null) { return result; } for (var i = 0; i < node.childNodes.length; i++) { switch (node.childNodes[i].nodeType) { case 1: // ELEMENT_NODE case 5: // ENTITY_REFERENCE_NODE var display = "unknown"; try { display = dojo.html.getStyle(node.childNodes[i], "display"); } catch(E) {} switch (display) { case "block": case "list-item": case "run-in": case "table": case "table-row-group": case "table-header-group": case "table-footer-group": case "table-row": case "table-column-group": case "table-column": case "table-cell": case "table-caption": // TODO: this shouldn't insert double spaces on aligning blocks result += "\n"; result += dojo.html.renderedTextContent(node.childNodes[i]); result += "\n"; break; case "none": break; default: if(node.childNodes[i].tagName && node.childNodes[i].tagName.toLowerCase() == "br") { result += "\n"; } else { result += dojo.html.renderedTextContent(node.childNodes[i]); } break; } break; case 3: // TEXT_NODE case 2: // ATTRIBUTE_NODE case 4: // CDATA_SECTION_NODE var text = node.childNodes[i].nodeValue; var textTransform = "unknown"; try { textTransform = dojo.html.getStyle(node, "text-transform"); } catch(E) {} switch (textTransform){ case "capitalize": var words = text.split(' '); for(var i=0; i]/i).test(txt.replace(/^\s+/))) { txt = "" + txt + "
"; tableType = "cell"; } else if((/^]/i).test(txt.replace(/^\s+/))) { txt = "" + txt + "
"; tableType = "row"; } else if((/^<(thead|tbody|tfoot)[\s\r\n>]/i).test(txt.replace(/^\s+/))) { txt = "" + txt + "
"; tableType = "section"; } tn.innerHTML = txt; if(tn["normalize"]){ tn.normalize(); } var parent = null; switch(tableType) { case "cell": parent = tn.getElementsByTagName("tr")[0]; break; case "row": parent = tn.getElementsByTagName("tbody")[0]; break; case "section": parent = tn.getElementsByTagName("table")[0]; break; default: parent = tn; break; } /* this doesn't make much sense, I'm assuming it just meant trim() so wrap was replaced with trim if(wrap){ var ret = []; // start hack var fc = tn.firstChild; ret[0] = ((fc.nodeValue == " ")||(fc.nodeValue == "\t")) ? fc.nextSibling : fc; // end hack // tn.style.display = "none"; dojo.body().removeChild(tn); return ret; } */ var nodes = []; for(var x=0; x view.width) { x = view.width - w; match = false; } else { x = tryX; } x = Math.max(padding[0], x) + scroll.x; var y = tryY + h; if(y > view.height) { y = view.height - h; match = false; } else { y = tryY; } y = Math.max(padding[1], y) + scroll.y; if(match){ //perfect match, return now bestx = x; besty = y; bestDistance = 0; break; }else{ //not perfect, find out whether it is better than the saved one var dist = Math.pow(x-tryX-scroll.x,2)+Math.pow(y-tryY-scroll.y,2); if(bestDistance > dist){ bestDistance = dist; bestx = x; besty = y; } } } if(!tryOnly){ node.style.left = bestx + "px"; node.style.top = besty + "px"; } return { left: bestx, top: besty, x: bestx, y: besty, dist: bestDistance }; } /** * Like placeOnScreenPoint except that it attempts to keep one of the node's * corners at desiredX, desiredY. Favors the bottom right position * * Examples placing node at mouse position (where e = [Mouse event]): * placeOnScreenPoint(node, e.clientX, e.clientY); */ dojo.html.placeOnScreenPoint = function(node, desiredX, desiredY, padding, hasScroll) { dojo.deprecated("dojo.html.placeOnScreenPoint", "use dojo.html.placeOnScreen() instead", "0.5"); return dojo.html.placeOnScreen(node, desiredX, desiredY, padding, hasScroll, ['TL', 'TR', 'BL', 'BR']); } /** * Like placeOnScreen, except it accepts aroundNode instead of x.y * and attempts to place node around it. aroundType (see * dojo.html.boxSizing in html/layout.js) determines which box of the * aroundNode should be used to calculate the outer box. * aroundCorners specify Which corner of aroundNode should be * used to place the node => which corner(s) of node to use (see the * corners parameter in dojo.html.placeOnScreen) * aroundCorners: {'TL': 'BL', 'BL': 'TL'} */ dojo.html.placeOnScreenAroundElement = function(node, aroundNode, padding, aroundType, aroundCorners, tryOnly){ var best, bestDistance=Infinity; aroundNode = dojo.byId(aroundNode); var oldDisplay = aroundNode.style.display; aroundNode.style.display=""; var mb = dojo.html.getElementBox(aroundNode, aroundType); var aroundNodeW = mb.width; var aroundNodeH = mb.height; var aroundNodePos = dojo.html.getAbsolutePosition(aroundNode, true, aroundType); aroundNode.style.display=oldDisplay; for(var nodeCorner in aroundCorners){ var pos, desiredX, desiredY; var corners = aroundCorners[nodeCorner]; desiredX = aroundNodePos.x + (nodeCorner.charAt(1)=='L' ? 0 : aroundNodeW); desiredY = aroundNodePos.y + (nodeCorner.charAt(0)=='T' ? 0 : aroundNodeH); pos = dojo.html.placeOnScreen(node, desiredX, desiredY, padding, true, corners, true); if(pos.dist == 0){ best = pos; break; }else{ //not perfect, find out whether it is better than the saved one if(bestDistance > pos.dist){ bestDistance = pos.dist; best = pos; } } } if(!tryOnly){ node.style.left = best.left + "px"; node.style.top = best.top + "px"; } return best; } //scrollIntoView in some implementation is broken, use our own dojo.html.scrollIntoView = function(node){ if(!node){ return; } // don't rely on that node.scrollIntoView works just because the function is there // it doesnt work in Konqueror or Opera even though the function is there and probably // not safari either // dont like browser sniffs implementations but sometimes you have to use it if(dojo.render.html.ie){ //only call scrollIntoView if there is a scrollbar for this menu, //otherwise, scrollIntoView will scroll the window scrollbar if(dojo.html.getBorderBox(node.parentNode).height < node.parentNode.scrollHeight){ node.scrollIntoView(false); } }else if(dojo.render.html.mozilla){ // IE, mozilla node.scrollIntoView(false); }else{ var parent = node.parentNode; var parentBottom = parent.scrollTop + dojo.html.getBorderBox(parent).height; var nodeBottom = node.offsetTop + dojo.html.getMarginBox(node).height; if(parentBottom < nodeBottom){ parent.scrollTop += (nodeBottom - parentBottom); }else if(parent.scrollTop > node.offsetTop){ parent.scrollTop -= (parent.scrollTop - node.offsetTop); } } } dojo.provide("dojo.html.display"); dojo.html._toggle = function(node, tester, setter){ node = dojo.byId(node); setter(node, !tester(node)); return tester(node); } // show/hide are library constructs // show() // if the node.style.display == 'none' then // set style.display to '' or the value cached by hide() dojo.html.show = function(node){ node = dojo.byId(node); if(dojo.html.getStyleProperty(node, 'display')=='none'){ dojo.html.setStyle(node, 'display', (node.dojoDisplayCache||'')); node.dojoDisplayCache = undefined; // cannot use delete on a node in IE6 } } // if the node.style.display == 'none' then // set style.display to '' or the value cached by hide() dojo.html.hide = function(node){ node = dojo.byId(node); if(typeof node["dojoDisplayCache"] == "undefined"){ // it could == '', so we cannot say !node.dojoDisplayCount var d = dojo.html.getStyleProperty(node, 'display') if(d!='none'){ node.dojoDisplayCache = d; } } dojo.html.setStyle(node, 'display', 'none'); } // setShowing() calls show() if showing is true, hide() otherwise dojo.html.setShowing = function(node, showing){ dojo.html[(showing ? 'show' : 'hide')](node); } // isShowing() is true if the node.style.display is not 'none' // FIXME: returns true if node is bad, isHidden would be easier to make correct dojo.html.isShowing = function(node){ return (dojo.html.getStyleProperty(node, 'display') != 'none'); } // Call setShowing() on node with the complement of isShowing(), then return the new value of isShowing() dojo.html.toggleShowing = function(node){ return dojo.html._toggle(node, dojo.html.isShowing, dojo.html.setShowing); } // display is a CSS concept // Simple mapping of tag names to display values // FIXME: simplistic dojo.html.displayMap = { tr: '', td: '', th: '', img: 'inline', span: 'inline', input: 'inline', button: 'inline' }; // Suggest a value for the display property that will show 'node' based on it's tag dojo.html.suggestDisplayByTagName = function(node) { node = dojo.byId(node); if(node && node.tagName){ var tag = node.tagName.toLowerCase(); return (tag in dojo.html.displayMap ? dojo.html.displayMap[tag] : 'block'); } } // setDisplay() sets the value of style.display to value of 'display' parameter if it is a string. // Otherwise, if 'display' is false, set style.display to 'none'. // Finally, set 'display' to a suggested display value based on the node's tag dojo.html.setDisplay = function(node, display){ dojo.html.setStyle(node, 'display', ((display instanceof String || typeof display == "string") ? display : (display ? dojo.html.suggestDisplayByTagName(node) : 'none'))); } // isDisplayed() is true if the the computed display style for node is not 'none' // FIXME: returns true if node is bad, isNotDisplayed would be easier to make correct dojo.html.isDisplayed = function(node){ return (dojo.html.getComputedStyle(node, 'display') != 'none'); } // Call setDisplay() on node with the complement of isDisplayed(), then // return the new value of isDisplayed() dojo.html.toggleDisplay = function(node){ return dojo.html._toggle(node, dojo.html.isDisplayed, dojo.html.setDisplay); } // visibility is a CSS concept // setVisibility() sets the value of style.visibility to value of // 'visibility' parameter if it is a string. // Otherwise, if 'visibility' is false, set style.visibility to 'hidden'. // Finally, set style.visibility to 'visible'. dojo.html.setVisibility = function(node, visibility){ dojo.html.setStyle(node, 'visibility', ((visibility instanceof String || typeof visibility == "string") ? visibility : (visibility ? 'visible' : 'hidden'))); } // isVisible() is true if the the computed visibility style for node is not 'hidden' // FIXME: returns true if node is bad, isInvisible would be easier to make correct dojo.html.isVisible = function(node){ return (dojo.html.getComputedStyle(node, 'visibility') != 'hidden'); } // Call setVisibility() on node with the complement of isVisible(), then // return the new value of isVisible() dojo.html.toggleVisibility = function(node){ return dojo.html._toggle(node, dojo.html.isVisible, dojo.html.setVisibility); } /* float between 0.0 (transparent) and 1.0 (opaque) */ dojo.html.setOpacity = function(node, opacity, dontFixOpacity){ node = dojo.byId(node); var h = dojo.render.html; if(!dontFixOpacity){ if( opacity >= 1.0){ if(h.ie){ dojo.html.clearOpacity(node); return; }else{ opacity = 0.999999; } }else if( opacity < 0.0){ opacity = 0; } } if(h.ie){ if(node.nodeName.toLowerCase() == "tr"){ // FIXME: is this too naive? will we get more than we want? var tds = node.getElementsByTagName("td"); for(var x=0; x= 0.999999 ? 1.0 : Number(opac); } dojo.provide("dojo.lfx.Animation"); dojo.provide("dojo.lfx.Line"); /* Animation package based on Dan Pupius' work: http://pupius.co.uk/js/Toolkit.Drawing.js */ dojo.lfx.Line = function(start, end){ this.start = start; this.end = end; if(dojo.lang.isArray(start)){ var diff = []; dojo.lang.forEach(this.start, function(s,i){ diff[i] = this.end[i] - s; }, this); this.getValue = function(/*float*/ n){ var res = []; dojo.lang.forEach(this.start, function(s, i){ res[i] = (diff[i] * n) + s; }, this); return res; } }else{ var diff = end - start; this.getValue = function(/*float*/ n){ // summary: returns the point on the line // n: a floating point number greater than 0 and less than 1 return (diff * n) + this.start; } } } dojo.lfx.easeDefault = function(n){ // sin wave easing. All the cool kids are doing it. return (0.5+((Math.sin( (n+1.5) * Math.PI))/2)); } dojo.lfx.easeIn = function(n){ // summary: returns the point on an easing curve // n: a floating point number greater than 0 and less than 1 return Math.pow(n, 3); } dojo.lfx.easeOut = function(n){ // summary: returns the point on the line // n: a floating point number greater than 0 and less than 1 return ( 1 - Math.pow(1 - n, 3) ); } dojo.lfx.easeInOut = function(n){ // summary: returns the point on the line // n: a floating point number greater than 0 and less than 1 return ( (3 * Math.pow(n, 2)) - (2 * Math.pow(n, 3)) ); } dojo.lfx.IAnimation = function(){} dojo.lang.extend(dojo.lfx.IAnimation, { // public properties curve: null, duration: 1000, easing: null, repeatCount: 0, rate: 25, // events handler: null, beforeBegin: null, onBegin: null, onAnimate: null, onEnd: null, onPlay: null, onPause: null, onStop: null, // public methods play: null, pause: null, stop: null, connect: function(evt, scope, newFunc){ if(!newFunc){ newFunc = scope; scope = this; } newFunc = dojo.lang.hitch(scope, newFunc); var oldFunc = this[evt]||function(){}; this[evt] = function(){ var ret = oldFunc.apply(this, arguments); newFunc.apply(this, arguments); return ret; } return this; }, fire: function(evt, args){ if(this[evt]){ this[evt].apply(this, (args||[])); } return this; }, repeat: function(count){ this.repeatCount = count; return this; }, // private properties _active: false, _paused: false }); dojo.lfx.Animation = function( /*Object*/ handlers, /*int*/ duration, /*Array*/ curve, /*function*/ easing, /*int*/ repeatCount, /*int*/ rate){ // summary // a generic animation object that fires callbacks into it's handlers // object at various states // handlers // object { // handler: function(){}, // onstart: function(){}, // onstop: function(){}, // onanimate: function(){} // } dojo.lfx.IAnimation.call(this); if(dojo.lang.isNumber(handlers)||(!handlers && duration.getValue)){ // no handlers argument: rate = repeatCount; repeatCount = easing; easing = curve; curve = duration; duration = handlers; handlers = null; }else if(handlers.getValue||dojo.lang.isArray(handlers)){ // no handlers or duration: rate = easing; repeatCount = curve; easing = duration; curve = handlers; duration = null; handlers = null; } if(dojo.lang.isArray(curve)){ this.curve = new dojo.lfx.Line(curve[0], curve[1]); }else{ this.curve = curve; } if(duration != null && duration > 0){ this.duration = duration; } if(repeatCount){ this.repeatCount = repeatCount; } if(rate){ this.rate = rate; } if(handlers){ dojo.lang.forEach([ "handler", "beforeBegin", "onBegin", "onEnd", "onPlay", "onStop", "onAnimate" ], function(item){ if(handlers[item]){ this.connect(item, handlers[item]); } }, this); } if(easing && dojo.lang.isFunction(easing)){ this.easing=easing; } } dojo.inherits(dojo.lfx.Animation, dojo.lfx.IAnimation); dojo.lang.extend(dojo.lfx.Animation, { // "private" properties _startTime: null, _endTime: null, _timer: null, _percent: 0, _startRepeatCount: 0, // public methods play: function(delay, gotoStart){ if(gotoStart){ clearTimeout(this._timer); this._active = false; this._paused = false; this._percent = 0; }else if(this._active && !this._paused){ return this; } this.fire("handler", ["beforeBegin"]); this.fire("beforeBegin"); if(delay > 0){ setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay); return this; } this._startTime = new Date().valueOf(); if(this._paused){ this._startTime -= (this.duration * this._percent / 100); } this._endTime = this._startTime + this.duration; this._active = true; this._paused = false; var step = this._percent / 100; var value = this.curve.getValue(step); if(this._percent == 0 ){ if(!this._startRepeatCount){ this._startRepeatCount = this.repeatCount; } this.fire("handler", ["begin", value]); this.fire("onBegin", [value]); } this.fire("handler", ["play", value]); this.fire("onPlay", [value]); this._cycle(); return this; }, pause: function(){ clearTimeout(this._timer); if(!this._active){ return this; } this._paused = true; var value = this.curve.getValue(this._percent / 100); this.fire("handler", ["pause", value]); this.fire("onPause", [value]); return this; }, gotoPercent: function(pct, andPlay){ clearTimeout(this._timer); this._active = true; this._paused = true; this._percent = pct; if(andPlay){ this.play(); } return this; }, stop: function(gotoEnd){ clearTimeout(this._timer); var step = this._percent / 100; if(gotoEnd){ step = 1; } var value = this.curve.getValue(step); this.fire("handler", ["stop", value]); this.fire("onStop", [value]); this._active = false; this._paused = false; return this; }, status: function(){ if(this._active){ return this._paused ? "paused" : "playing"; }else{ return "stopped"; } return this; }, // "private" methods _cycle: function(){ clearTimeout(this._timer); if(this._active){ var curr = new Date().valueOf(); var step = (curr - this._startTime) / (this._endTime - this._startTime); if(step >= 1){ step = 1; this._percent = 100; }else{ this._percent = step * 100; } // Perform easing if((this.easing)&&(dojo.lang.isFunction(this.easing))){ step = this.easing(step); } var value = this.curve.getValue(step); this.fire("handler", ["animate", value]); this.fire("onAnimate", [value]); if( step < 1 ){ this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate); }else{ this._active = false; this.fire("handler", ["end"]); this.fire("onEnd"); if(this.repeatCount > 0){ this.repeatCount--; this.play(null, true); }else if(this.repeatCount == -1){ this.play(null, true); }else{ if(this._startRepeatCount){ this.repeatCount = this._startRepeatCount; this._startRepeatCount = 0; } } } } return this; } }); dojo.lfx.Combine = function(){ dojo.lfx.IAnimation.call(this); this._anims = []; this._animsEnded = 0; var anims = arguments; if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){ anims = anims[0]; } dojo.lang.forEach(anims, function(anim){ this._anims.push(anim); anim.connect("onEnd", dojo.lang.hitch(this, "_onAnimsEnded")); }, this); } dojo.inherits(dojo.lfx.Combine, dojo.lfx.IAnimation); dojo.lang.extend(dojo.lfx.Combine, { // private members _animsEnded: 0, // public methods play: function(delay, gotoStart){ if( !this._anims.length ){ return this; } this.fire("beforeBegin"); if(delay > 0){ setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay); return this; } if(gotoStart || this._anims[0].percent == 0){ this.fire("onBegin"); } this.fire("onPlay"); this._animsCall("play", null, gotoStart); return this; }, pause: function(){ this.fire("onPause"); this._animsCall("pause"); return this; }, stop: function(gotoEnd){ this.fire("onStop"); this._animsCall("stop", gotoEnd); return this; }, // private methods _onAnimsEnded: function(){ this._animsEnded++; if(this._animsEnded >= this._anims.length){ this.fire("onEnd"); } return this; }, _animsCall: function(funcName){ var args = []; if(arguments.length > 1){ for(var i = 1 ; i < arguments.length ; i++){ args.push(arguments[i]); } } var _this = this; dojo.lang.forEach(this._anims, function(anim){ anim[funcName](args); }, _this); return this; } }); dojo.lfx.Chain = function() { dojo.lfx.IAnimation.call(this); this._anims = []; this._currAnim = -1; var anims = arguments; if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){ anims = anims[0]; } var _this = this; dojo.lang.forEach(anims, function(anim, i, anims_arr){ this._anims.push(anim); if(i < anims_arr.length - 1){ anim.connect("onEnd", dojo.lang.hitch(this, "_playNext") ); }else{ anim.connect("onEnd", dojo.lang.hitch(this, function(){ this.fire("onEnd"); }) ); } }, this); } dojo.inherits(dojo.lfx.Chain, dojo.lfx.IAnimation); dojo.lang.extend(dojo.lfx.Chain, { // private members _currAnim: -1, // public methods play: function(delay, gotoStart){ if( !this._anims.length ) { return this; } if( gotoStart || !this._anims[this._currAnim] ) { this._currAnim = 0; } var currentAnimation = this._anims[this._currAnim]; this.fire("beforeBegin"); if(delay > 0){ setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay); return this; } if(currentAnimation){ if(this._currAnim == 0){ this.fire("handler", ["begin", this._currAnim]); this.fire("onBegin", [this._currAnim]); } this.fire("onPlay", [this._currAnim]); currentAnimation.play(null, gotoStart); } return this; }, pause: function(){ if( this._anims[this._currAnim] ) { this._anims[this._currAnim].pause(); this.fire("onPause", [this._currAnim]); } return this; }, playPause: function(){ if(this._anims.length == 0){ return this; } if(this._currAnim == -1){ this._currAnim = 0; } var currAnim = this._anims[this._currAnim]; if( currAnim ) { if( !currAnim._active || currAnim._paused ) { this.play(); } else { this.pause(); } } return this; }, stop: function(){ var currAnim = this._anims[this._currAnim]; if(currAnim){ currAnim.stop(); this.fire("onStop", [this._currAnim]); } return currAnim; }, // private methods _playNext: function(){ if( this._currAnim == -1 || this._anims.length == 0 ) { return this; } this._currAnim++; if( this._anims[this._currAnim] ){ this._anims[this._currAnim].play(null, true); } return this; } }); dojo.lfx.combine = function(){ var anims = arguments; if(dojo.lang.isArray(arguments[0])){ anims = arguments[0]; } if(anims.length == 1){ return anims[0]; } return new dojo.lfx.Combine(anims); } dojo.lfx.chain = function(){ var anims = arguments; if(dojo.lang.isArray(arguments[0])){ anims = arguments[0]; } if(anims.length == 1){ return anims[0]; } return new dojo.lfx.Chain(anims); } dojo.provide("dojo.graphics.color"); // TODO: rewrite the "x2y" methods to take advantage of the parsing // abilities of the Color object. Also, beef up the Color // object (as possible) to parse most common formats // takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa) dojo.graphics.color.Color = function(r, g, b, a) { // dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]); if(dojo.lang.isArray(r)) { this.r = r[0]; this.g = r[1]; this.b = r[2]; this.a = r[3]||1.0; } else if(dojo.lang.isString(r)) { var rgb = dojo.graphics.color.extractRGB(r); this.r = rgb[0]; this.g = rgb[1]; this.b = rgb[2]; this.a = g||1.0; } else if(r instanceof dojo.graphics.color.Color) { this.r = r.r; this.b = r.b; this.g = r.g; this.a = r.a; } else { this.r = r; this.g = g; this.b = b; this.a = a; } } dojo.graphics.color.Color.fromArray = function(arr) { return new dojo.graphics.color.Color(arr[0], arr[1], arr[2], arr[3]); } dojo.lang.extend(dojo.graphics.color.Color, { toRgb: function(includeAlpha) { if(includeAlpha) { return this.toRgba(); } else { return [this.r, this.g, this.b]; } }, toRgba: function() { return [this.r, this.g, this.b, this.a]; }, toHex: function() { return dojo.graphics.color.rgb2hex(this.toRgb()); }, toCss: function() { return "rgb(" + this.toRgb().join() + ")"; }, toString: function() { return this.toHex(); // decent default? }, blend: function(color, weight) { return dojo.graphics.color.blend(this.toRgb(), new dojo.graphics.color.Color(color).toRgb(), weight); } }); dojo.graphics.color.named = { white: [255,255,255], black: [0,0,0], red: [255,0,0], green: [0,255,0], blue: [0,0,255], navy: [0,0,128], gray: [128,128,128], silver: [192,192,192] }; // blend colors a and b (both as RGB array or hex strings) with weight from -1 to +1, 0 being a 50/50 blend dojo.graphics.color.blend = function(a, b, weight) { if(typeof a == "string") { return dojo.graphics.color.blendHex(a, b, weight); } if(!weight) { weight = 0; } else if(weight > 1) { weight = 1; } else if(weight < -1) { weight = -1; } var c = new Array(3); for(var i = 0; i < 3; i++) { var half = Math.abs(a[i] - b[i])/2; c[i] = Math.floor(Math.min(a[i], b[i]) + half + (half * weight)); } return c; } // very convenient blend that takes and returns hex values // (will get called automatically by blend when blend gets strings) dojo.graphics.color.blendHex = function(a, b, weight) { return dojo.graphics.color.rgb2hex(dojo.graphics.color.blend(dojo.graphics.color.hex2rgb(a), dojo.graphics.color.hex2rgb(b), weight)); } // get RGB array from css-style color declarations dojo.graphics.color.extractRGB = function(color) { var hex = "0123456789abcdef"; color = color.toLowerCase(); if( color.indexOf("rgb") == 0 ) { var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i); var ret = matches.splice(1, 3); return ret; } else { var colors = dojo.graphics.color.hex2rgb(color); if(colors) { return colors; } else { // named color (how many do we support?) return dojo.graphics.color.named[color] || [255, 255, 255]; } } } dojo.graphics.color.hex2rgb = function(hex) { var hexNum = "0123456789ABCDEF"; var rgb = new Array(3); if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); } hex = hex.toUpperCase(); if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") { return null; } if( hex.length == 3 ) { rgb[0] = hex.charAt(0) + hex.charAt(0) rgb[1] = hex.charAt(1) + hex.charAt(1) rgb[2] = hex.charAt(2) + hex.charAt(2); } else { rgb[0] = hex.substring(0, 2); rgb[1] = hex.substring(2, 4); rgb[2] = hex.substring(4); } for(var i = 0; i < rgb.length; i++) { rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1)); } return rgb; } dojo.graphics.color.rgb2hex = function(r, g, b) { if(dojo.lang.isArray(r)) { g = r[1] || 0; b = r[2] || 0; r = r[0] || 0; } var ret = dojo.lang.map([r, g, b], function(x) { x = new Number(x); var s = x.toString(16); while(s.length < 2) { s = "0" + s; } return s; }); ret.unshift("#"); return ret.join(""); } dojo.provide("dojo.html.color"); dojo.html.getBackgroundColor = function(node){ node = dojo.byId(node); var color; do{ color = dojo.html.getStyle(node, "background-color"); // Safari doesn't say "transparent" if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; } if(node == document.getElementsByTagName("body")[0]) { node = null; break; } node = node.parentNode; }while(node && dojo.lang.inArray(["transparent", ""], color)); if(color == "transparent"){ color = [255, 255, 255, 0]; }else{ color = dojo.graphics.color.extractRGB(color); } return color; } dojo.provide("dojo.lfx.html"); dojo.lfx.html._byId = function(nodes){ if(!nodes){ return []; } if(dojo.lang.isArrayLike(nodes)){ if(!nodes.alreadyChecked){ var n = []; dojo.lang.forEach(nodes, function(node){ n.push(dojo.byId(node)); }); n.alreadyChecked = true; return n; }else{ return nodes; } }else{ var n = []; n.push(dojo.byId(nodes)); n.alreadyChecked = true; return n; } } dojo.lfx.html.propertyAnimation = function( /*DOMNode*/ nodes, /*Array*/ propertyMap, /*int*/ duration, /*function*/ easing, /*Object*/ handlers){ nodes = dojo.lfx.html._byId(nodes); var targs = { "propertyMap": propertyMap, "nodes": nodes, "duration": duration, "easing": easing||dojo.lfx.easeDefault }; var setEmUp = function(args){ if(args.nodes.length==1){ // FIXME: we're only supporting start-value filling when one node is // passed var pm = args.propertyMap; if(!dojo.lang.isArray(args.propertyMap)){ // it's stupid to have to pack an array with a set of objects // when you can just pass in an object list var parr = []; for(var pname in pm){ pm[pname].property = pname; parr.push(pm[pname]); } pm = args.propertyMap = parr; } dojo.lang.forEach(pm, function(prop){ if(dj_undef("start", prop)){ if(prop.property != "opacity"){ prop.start = parseInt(dojo.html.getComputedStyle(args.nodes[0], prop.property)); }else{ prop.start = dojo.html.getOpacity(args.nodes[0]); } } }); } } var coordsAsInts = function(coords){ var cints = []; dojo.lang.forEach(coords, function(c){ cints.push(Math.round(c)); }); return cints; } var setStyle = function(n, style){ n = dojo.byId(n); if(!n || !n.style){ return; } for(var s in style){ if(s == "opacity"){ dojo.html.setOpacity(n, style[s]); }else{ n.style[s] = style[s]; } } } var propLine = function(properties){ this._properties = properties; this.diffs = new Array(properties.length); dojo.lang.forEach(properties, function(prop, i){ // calculate the end - start to optimize a bit if(dojo.lang.isFunction(prop.start)){ prop.start = prop.start(prop, i); } if(dojo.lang.isFunction(prop.end)){ prop.end = prop.end(prop, i); } if(dojo.lang.isArray(prop.start)){ // don't loop through the arrays this.diffs[i] = null; }else if(prop.start instanceof dojo.graphics.color.Color){ // save these so we don't have to call toRgb() every getValue() call prop.startRgb = prop.start.toRgb(); prop.endRgb = prop.end.toRgb(); }else{ this.diffs[i] = prop.end - prop.start; } }, this); this.getValue = function(n){ var ret = {}; dojo.lang.forEach(this._properties, function(prop, i){ var value = null; if(dojo.lang.isArray(prop.start)){ // FIXME: what to do here? }else if(prop.start instanceof dojo.graphics.color.Color){ value = (prop.units||"rgb") + "("; for(var j = 0 ; j < prop.startRgb.length ; j++){ value += Math.round(((prop.endRgb[j] - prop.startRgb[j]) * n) + prop.startRgb[j]) + (j < prop.startRgb.length - 1 ? "," : ""); } value += ")"; }else{ value = ((this.diffs[i]) * n) + prop.start + (prop.property != "opacity" ? prop.units||"px" : ""); } ret[dojo.html.toCamelCase(prop.property)] = value; }, this); return ret; } } var anim = new dojo.lfx.Animation({ beforeBegin: function(){ setEmUp(targs); anim.curve = new propLine(targs.propertyMap); }, onAnimate: function(propValues){ dojo.lang.forEach(targs.nodes, function(node){ setStyle(node, propValues); }); } }, targs.duration, null, targs.easing ); if(handlers){ for(var x in handlers){ if(dojo.lang.isFunction(handlers[x])){ anim.connect(x, anim, handlers[x]); } } } return anim; } dojo.lfx.html._makeFadeable = function(nodes){ var makeFade = function(node){ if(dojo.render.html.ie){ // only set the zoom if the "tickle" value would be the same as the // default if( (node.style.zoom.length == 0) && (dojo.html.getStyle(node, "zoom") == "normal") ){ // make sure the node "hasLayout" // NOTE: this has been tested with larger and smaller user-set text // sizes and works fine node.style.zoom = "1"; // node.style.zoom = "normal"; } // don't set the width to auto if it didn't already cascade that way. // We don't want to f anyones designs if( (node.style.width.length == 0) && (dojo.html.getStyle(node, "width") == "auto") ){ node.style.width = "auto"; } } } if(dojo.lang.isArrayLike(nodes)){ dojo.lang.forEach(nodes, makeFade); }else{ makeFade(nodes); } } dojo.lfx.html.fade = function(nodes, values, duration, easing, callback){ nodes = dojo.lfx.html._byId(nodes); var props = { property: "opacity" }; if(!dj_undef("start", values)){ props.start = values.start; }else{ props.start = function(){ return dojo.html.getOpacity(nodes[0]); }; } if(!dj_undef("end", values)){ props.end = values.end; }else{ dojo.raise("dojo.lfx.html.fade needs an end value"); } var anim = dojo.lfx.propertyAnimation(nodes, [ props ], duration, easing); anim.connect("beforeBegin", function(){ dojo.lfx.html._makeFadeable(nodes); }); if(callback){ anim.connect("onEnd", function(){ callback(nodes, anim); }); } return anim; } dojo.lfx.html.fadeIn = function(nodes, duration, easing, callback){ return dojo.lfx.html.fade(nodes, { end: 1 }, duration, easing, callback); } dojo.lfx.html.fadeOut = function(nodes, duration, easing, callback){ return dojo.lfx.html.fade(nodes, { end: 0 }, duration, easing, callback); } dojo.lfx.html.fadeShow = function(nodes, duration, easing, callback){ nodes=dojo.lfx.html._byId(nodes); dojo.lang.forEach(nodes, function(node){ dojo.html.setOpacity(node, 0.0); }); var anim = dojo.lfx.html.fadeIn(nodes, duration, easing, callback); anim.connect("beforeBegin", function(){ if(dojo.lang.isArrayLike(nodes)){ dojo.lang.forEach(nodes, dojo.html.show); }else{ dojo.html.show(nodes); } }); return anim; } dojo.lfx.html.fadeHide = function(nodes, duration, easing, callback){ var anim = dojo.lfx.html.fadeOut(nodes, duration, easing, function(){ if(dojo.lang.isArrayLike(nodes)){ dojo.lang.forEach(nodes, dojo.html.hide); }else{ dojo.html.hide(nodes); } if(callback){ callback(nodes, anim); } }); return anim; } dojo.lfx.html.wipeIn = function(nodes, duration, easing, callback){ nodes = dojo.lfx.html._byId(nodes); var anims = []; dojo.lang.forEach(nodes, function(node){ var oprop = { overflow: null }; var anim = dojo.lfx.propertyAnimation(node, { "height": { start: 0, end: function(){ return node.scrollHeight; } } }, duration, easing); anim.connect("beforeBegin", function(){ oprop.overflow = dojo.html.getStyle(node, "overflow"); with(node.style){ if(oprop.overflow == "visible") { overflow = "hidden"; } visibility = "visible"; height = "0px"; } dojo.html.show(node); }); anim.connect("onEnd", function(){ with(node.style){ overflow = oprop.overflow; // height = "auto"; height = ""; visibility = "visible"; } if(callback){ callback(node, anim); } }); anims.push(anim); }); return dojo.lfx.combine(anims); } dojo.lfx.html.wipeOut = function(nodes, duration, easing, callback){ nodes = dojo.lfx.html._byId(nodes); var anims = []; dojo.lang.forEach(nodes, function(node){ var oprop = { overflow: null }; var anim = dojo.lfx.propertyAnimation(node, { "height": { start: function(){ return dojo.html.getContentBox(node).height; }, end: 0 } }, duration, easing, { "beforeBegin": function(){ oprop.overflow = dojo.html.getStyle(node, "overflow"); if(oprop.overflow == "visible") { node.style.overflow = "hidden"; } node.style.visibility = "visible"; dojo.html.show(node); }, "onEnd": function(){ // dojo.html.hide(node); with(node.style){ overflow = oprop.overflow; visibility = "hidden"; height = ""; } if(callback){ callback(node, anim); } } } ); anims.push(anim); }); return dojo.lfx.combine(anims); } dojo.lfx.html.slideTo = function(nodes, coords, duration, easing, callback){ nodes = dojo.lfx.html._byId(nodes); var anims = []; var compute = dojo.html.getComputedStyle; if(dojo.lang.isArray(coords)){ dojo.deprecated('dojo.lfx.html.slideTo(node, array)', 'use dojo.lfx.html.slideTo(node, {top: value, left: value});', '0.5'); coords = { top: coords[0], left: coords[1] }; } dojo.lang.forEach(nodes, function(node){ var top = null; var left = null; var init = (function(){ var innerNode = node; return function(){ var pos = compute(innerNode, 'position'); top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0); left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0); if (!dojo.lang.inArray(['absolute', 'relative'], pos)) { var ret = dojo.html.abs(innerNode, true); dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;"); top = ret.y; left = ret.x; } } })(); init(); var anim = dojo.lfx.propertyAnimation(node, { "top": { start: top, end: (coords.top||0) }, "left": { start: left, end: (coords.left||0) } }, duration, easing, { "beforeBegin": init } ); if(callback){ anim.connect("onEnd", function(){ callback(nodes, anim); }); } anims.push(anim); }); return dojo.lfx.combine(anims); } dojo.lfx.html.slideBy = function(nodes, coords, duration, easing, callback){ nodes = dojo.lfx.html._byId(nodes); var anims = []; var compute = dojo.html.getComputedStyle; if(dojo.lang.isArray(coords)){ dojo.deprecated('dojo.lfx.html.slideBy(node, array)', 'use dojo.lfx.html.slideBy(node, {top: value, left: value});', '0.5'); coords = { top: coords[0], left: coords[1] }; } dojo.lang.forEach(nodes, function(node){ var top = null; var left = null; var init = (function(){ var innerNode = node; return function(){ var pos = compute(innerNode, 'position'); top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0); left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0); if (!dojo.lang.inArray(['absolute', 'relative'], pos)) { var ret = dojo.html.abs(innerNode, true); dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;"); top = ret.y; left = ret.x; } } })(); init(); var anim = dojo.lfx.propertyAnimation(node, { "top": { start: top, end: top+(coords.top||0) }, "left": { start: left, end: left+(coords.left||0) } }, duration, easing).connect("beforeBegin", init); if(callback){ anim.connect("onEnd", function(){ callback(nodes, anim); }); } anims.push(anim); }); return dojo.lfx.combine(anims); } dojo.lfx.html.explode = function(start, endNode, duration, easing, callback){ var h = dojo.html; start = dojo.byId(start); endNode = dojo.byId(endNode); var startCoords = h.toCoordinateObject(start, true); var outline = document.createElement("div"); h.copyStyle(outline, endNode); with(outline.style){ position = "absolute"; display = "none"; // border = "1px solid black"; } dojo.body().appendChild(outline); with(endNode.style){ visibility = "hidden"; display = "block"; } var endCoords = h.toCoordinateObject(endNode, true); outline.style.backgroundColor = h.getStyle(endNode, "background-color").toLowerCase(); with(endNode.style){ display = "none"; visibility = "visible"; } var props = { opacity: { start: 0.3, end: 1.0 } }; dojo.lang.forEach(["height", "width", "top", "left"], function(type){ props[type] = { start: startCoords[type], end: endCoords[type] } }); var anim = new dojo.lfx.propertyAnimation(outline, props, duration, easing, { "beforeBegin": function(){ h.setDisplay(outline, "block"); }, "onEnd": function(){ h.setDisplay(endNode, "block"); outline.parentNode.removeChild(outline); } } ); if(callback){ anim.connect("onEnd", function(){ callback(endNode, anim); }); } return anim; } dojo.lfx.html.implode = function(startNode, end, duration, easing, callback){ var h = dojo.html; startNode = dojo.byId(startNode); end = dojo.byId(end); var startCoords = dojo.html.toCoordinateObject(startNode, true); var endCoords = dojo.html.toCoordinateObject(end, true); var outline = document.createElement("div"); dojo.html.copyStyle(outline, startNode); dojo.html.setOpacity(outline, 0.3); with(outline.style){ position = "absolute"; display = "none"; backgroundColor = h.getStyle(startNode, "background-color").toLowerCase(); } dojo.body().appendChild(outline); var props = { opacity: { start: 1.0, end: 0.3 } }; dojo.lang.forEach(["height", "width", "top", "left"], function(type){ props[type] = { start: startCoords[type], end: endCoords[type] } }); var anim = new dojo.lfx.propertyAnimation(outline, props, duration, easing, { "beforeBegin": function(){ dojo.html.hide(startNode); dojo.html.show(outline); }, "onEnd": function(){ outline.parentNode.removeChild(outline); } } ); if(callback){ anim.connect("onEnd", function(){ callback(startNode, anim); }); } return anim; } dojo.lfx.html.highlight = function(nodes, startColor, duration, easing, callback){ nodes = dojo.lfx.html._byId(nodes); var anims = []; dojo.lang.forEach(nodes, function(node){ var color = dojo.html.getBackgroundColor(node); var bg = dojo.html.getStyle(node, "background-color").toLowerCase(); var bgImage = dojo.html.getStyle(node, "background-image"); var wasTransparent = (bg == "transparent" || bg == "rgba(0, 0, 0, 0)"); while(color.length > 3) { color.pop(); } var rgb = new dojo.graphics.color.Color(startColor); var endRgb = new dojo.graphics.color.Color(color); var anim = dojo.lfx.propertyAnimation(node, { "background-color": { start: rgb, end: endRgb } }, duration, easing, { "beforeBegin": function(){ if(bgImage){ node.style.backgroundImage = "none"; } node.style.backgroundColor = "rgb(" + rgb.toRgb().join(",") + ")"; }, "onEnd": function(){ if(bgImage){ node.style.backgroundImage = bgImage; } if(wasTransparent){ node.style.backgroundColor = "transparent"; } if(callback){ callback(node, anim); } } } ); anims.push(anim); }); return dojo.lfx.combine(anims); } dojo.lfx.html.unhighlight = function(nodes, endColor, duration, easing, callback){ nodes = dojo.lfx.html._byId(nodes); var anims = []; dojo.lang.forEach(nodes, function(node){ var color = new dojo.graphics.color.Color(dojo.html.getBackgroundColor(node)); var rgb = new dojo.graphics.color.Color(endColor); var bgImage = dojo.html.getStyle(node, "background-image"); var anim = dojo.lfx.propertyAnimation(node, { "background-color": { start: color, end: rgb } }, duration, easing, { "beforeBegin": function(){ if(bgImage){ node.style.backgroundImage = "none"; } node.style.backgroundColor = "rgb(" + color.toRgb().join(",") + ")"; }, "onEnd": function(){ if(callback){ callback(node, anim); } } } ); anims.push(anim); }); return dojo.lfx.combine(anims); } dojo.lang.mixin(dojo.lfx, dojo.lfx.html); dojo.provide("dojo.lfx.*"); dojo.provide("dojo.lfx.toggle"); dojo.lfx.toggle.plain = { show: function(node, duration, easing, callback){ dojo.html.show(node); if(dojo.lang.isFunction(callback)){ callback(); } }, hide: function(node, duration, easing, callback){ dojo.html.hide(node); if(dojo.lang.isFunction(callback)){ callback(); } } } dojo.lfx.toggle.fade = { show: function(node, duration, easing, callback){ dojo.lfx.fadeShow(node, duration, easing, callback).play(); }, hide: function(node, duration, easing, callback){ dojo.lfx.fadeHide(node, duration, easing, callback).play(); } } dojo.lfx.toggle.wipe = { show: function(node, duration, easing, callback){ dojo.lfx.wipeIn(node, duration, easing, callback).play(); }, hide: function(node, duration, easing, callback){ dojo.lfx.wipeOut(node, duration, easing, callback).play(); } } dojo.lfx.toggle.explode = { show: function(node, duration, easing, callback, explodeSrc){ dojo.lfx.explode(explodeSrc||{x:0,y:0,width:0,height:0}, node, duration, easing, callback).play(); }, hide: function(node, duration, easing, callback, explodeSrc){ dojo.lfx.implode(node, explodeSrc||{x:0,y:0,width:0,height:0}, duration, easing, callback).play(); } } dojo.provide("dojo.widget.HtmlWidget"); dojo.declare("dojo.widget.HtmlWidget", dojo.widget.DomWidget, { widgetType: "HtmlWidget", templateCssPath: null, templatePath: null, // for displaying/hiding widget toggle: "plain", toggleDuration: 150, animationInProgress: false, initialize: function(args, frag){ }, postMixInProperties: function(args, frag){ // now that we know the setting for toggle, get toggle object // (default to plain toggler if user specified toggler not present) this.toggleObj = dojo.lfx.toggle[this.toggle.toLowerCase()] || dojo.lfx.toggle.plain; }, getContainerHeight: function(){ // NOTE: container height must be returned as the INNER height dojo.unimplemented("dojo.widget.HtmlWidget.getContainerHeight"); }, getContainerWidth: function(){ return this.parent.domNode.offsetWidth; }, setNativeHeight: function(height){ var ch = this.getContainerHeight(); }, createNodesFromText: function(txt, wrap){ return dojo.html.createNodesFromText(txt, wrap); }, destroyRendering: function(finalize){ try{ if(!finalize && this.domNode){ dojo.event.browser.clean(this.domNode); } this.domNode.parentNode.removeChild(this.domNode); delete this.domNode; }catch(e){ /* squelch! */ } }, ///////////////////////////////////////////////////////// // Displaying/hiding the widget ///////////////////////////////////////////////////////// isShowing: function(){ return dojo.html.isShowing(this.domNode); }, toggleShowing: function(){ // dojo.html.toggleShowing(this.domNode); if(this.isHidden){ this.show(); }else{ this.hide(); } }, show: function(){ this.animationInProgress=true; this.isHidden = false; this.toggleObj.show(this.domNode, this.toggleDuration, null, dojo.lang.hitch(this, this.onShow), this.explodeSrc); }, // called after the show() animation has completed onShow: function(){ this.animationInProgress=false; this.checkSize(); }, hide: function(){ this.animationInProgress = true; this.isHidden = true; this.toggleObj.hide(this.domNode, this.toggleDuration, null, dojo.lang.hitch(this, this.onHide), this.explodeSrc); }, // called after the hide() animation has completed onHide: function(){ this.animationInProgress=false; }, ////////////////////////////////////////////////////////////////////////////// // Sizing related methods // If the parent changes size then for each child it should call either // - resizeTo(): size the child explicitly // - or checkSize(): notify the child the the parent has changed size ////////////////////////////////////////////////////////////////////////////// // Test if my size has changed. // If width & height are specified then that's my new size; otherwise, // query outerWidth/outerHeight of my domNode _isResized: function(w, h){ // If I'm not being displayed then disregard (show() must // check if the size has changed) if(!this.isShowing()){ return false; } // If my parent has been resized and I have style="height: 100%" // or something similar then my size has changed too. var wh = dojo.html.getMarginBox(this.domNode); var width=w||wh.width; var height=h||wh.height; if(this.width == width && this.height == height){ return false; } this.width=width; this.height=height; return true; }, // Called when my parent has changed size, but my parent won't call resizeTo(). // This is useful if my size is height:100% or something similar. // Also called whenever I am shown, because the first time I am shown I may need // to do size calculations. checkSize: function(){ if(!this._isResized()){ return; } this.onResized(); }, // Explicitly set this widget's size (in pixels). resizeTo: function(w, h){ if(!this._isResized(w,h)){ return; } dojo.html.setMarginBox(this.domNode, { width: w, height: h }); this.onResized(); }, resizeSoon: function(){ if(this.isShowing()){ dojo.lang.setTimeout(this, this.onResized, 0); } }, // Called when my size has changed. // Must notify children if their size has (possibly) changed onResized: function(){ dojo.lang.forEach(this.children, function(child){ if (child["checkSize"]) child.checkSize(); }); } }); dojo.provide("dojo.widget.*");