1(function(){ 2 if(window.dojoConfig == null) 3 window.dojoConfig = {}; 4 if(window.dojoConfig.packages == null) 5 window.dojoConfig.packages = []; 6 7 var packages = { 8 "dojo" : {location: "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo"}, 9 "dijit":{location: "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit"}, 10 "dojox":{location: "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojox"}, 11 "dpage":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/dpage"}, 12 "footable":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/footable"}, 13 "jquery":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/jquery",main : "jquery"}, 14 "jquery-ui":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/jquery-ui"}, 15 "jQueryPrivate":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/jQueryPrivate",main: "jQueryPrivate"}, 16 "xstyle":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/xstyle"}, 17 "dpageRoot":{location: "https://svc.mt.gov/itsd/dpage"}, 18 "put-selector":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/put-selector"} 19 }; 20 21 //allow these to be overridden. 22 for(var i=0; i<window.dojoConfig.packages.length;i++){ 23 if(packages[window.dojoConfig.packages[i]] != null){ 24 delete packages[window.dojoConfig.packages[i]]; 25 } 26 } 27 28 //add in required package configs. 29 for(var p in packages){ 30 if(packages.hasOwnProperty(p)){ 31 packages[p].name = p; 32 window.dojoConfig.packages.push(packages[p]); 33 } 34 } 35})(); 36 37/* 38 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. 39 Available via Academic Free License >= 2.1 OR the modified BSD license. 40 see: http://dojotoolkit.org/license for details 41*/ 42 43/* 44 This is an optimized version of Dojo, built for deployment and not for 45 development. To get sources and documentation, please visit: 46 47 http://dojotoolkit.org 48*/ 49 50(function( 51 userConfig, 52 defaultConfig 53){ 54 // summary: 55 // This is the "source loader" and is the entry point for Dojo during development. You may also load Dojo with 56 // any AMD-compliant loader via the package main module dojo/main. 57 // description: 58 // This is the "source loader" for Dojo. It provides an AMD-compliant loader that can be configured 59 // to operate in either synchronous or asynchronous modes. After the loader is defined, dojo is loaded 60 // IAW the package main module dojo/main. In the event you wish to use a foreign loader, you may load dojo as a package 61 // via the package main module dojo/main and this loader is not required; see dojo/package.json for details. 62 // 63 // In order to keep compatibility with the v1.x line, this loader includes additional machinery that enables 64 // the dojo.provide, dojo.require et al API. This machinery is loaded by default, but may be dynamically removed 65 // via the has.js API and statically removed via the build system. 66 // 67 // This loader includes sniffing machinery to determine the environment; the following environments are supported: 68 // 69 // - browser 70 // - node.js 71 // - rhino 72 // 73 // This is the so-called "source loader". As such, it includes many optional features that may be discarded by 74 // building a customized version with the build system. 75 76 // Design and Implementation Notes 77 // 78 // This is a dojo-specific adaption of bdLoad, donated to the dojo foundation by Altoviso LLC. 79 // 80 // This function defines an AMD-compliant (http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition) 81 // loader that can be configured to operate in either synchronous or asynchronous modes. 82 // 83 // Since this machinery implements a loader, it does not have the luxury of using a load system and/or 84 // leveraging a utility library. This results in an unpleasantly long file; here is a road map of the contents: 85 // 86 // 1. Small library for use implementing the loader. 87 // 2. Define the has.js API; this is used throughout the loader to bracket features. 88 // 3. Define the node.js and rhino sniffs and sniff. 89 // 4. Define the loader's data. 90 // 5. Define the configuration machinery. 91 // 6. Define the script element sniffing machinery and sniff for configuration data. 92 // 7. Configure the loader IAW the provided user, default, and sniffing data. 93 // 8. Define the global require function. 94 // 9. Define the module resolution machinery. 95 // 10. Define the module and plugin module definition machinery 96 // 11. Define the script injection machinery. 97 // 12. Define the window load detection. 98 // 13. Define the logging API. 99 // 14. Define the tracing API. 100 // 16. Define the AMD define function. 101 // 17. Define the dojo v1.x provide/require machinery--so called "legacy" modes. 102 // 18. Publish global variables. 103 // 104 // Language and Acronyms and Idioms 105 // 106 // moduleId: a CJS module identifier, (used for public APIs) 107 // mid: moduleId (used internally) 108 // packageId: a package identifier (used for public APIs) 109 // pid: packageId (used internally); the implied system or default package has pid==="" 110 // pack: package is used internally to reference a package object (since javascript has reserved words including "package") 111 // prid: plugin resource identifier 112 // The integer constant 1 is used in place of true and 0 in place of false. 113 114 // define a minimal library to help build the loader 115 var noop = function(){ 116 }, 117 118 isEmpty = function(it){ 119 for(var p in it){ 120 return 0; 121 } 122 return 1; 123 }, 124 125 toString = {}.toString, 126 127 isFunction = function(it){ 128 return toString.call(it) == "[object Function]"; 129 }, 130 131 isString = function(it){ 132 return toString.call(it) == "[object String]"; 133 }, 134 135 isArray = function(it){ 136 return toString.call(it) == "[object Array]"; 137 }, 138 139 forEach = function(vector, callback){ 140 if(vector){ 141 for(var i = 0; i < vector.length;){ 142 callback(vector[i++]); 143 } 144 } 145 }, 146 147 mix = function(dest, src){ 148 for(var p in src){ 149 dest[p] = src[p]; 150 } 151 return dest; 152 }, 153 154 makeError = function(error, info){ 155 return mix(new Error(error), {src:"dojoLoader", info:info}); 156 }, 157 158 uidSeed = 1, 159 160 uid = function(){ 161 // Returns a unique identifier (within the lifetime of the document) of the form /_d+/. 162 return "_" + uidSeed++; 163 }, 164 165 // FIXME: how to doc window.require() api 166 167 // this will be the global require function; define it immediately so we can start hanging things off of it 168 req = function( 169 config, //(object, optional) hash of configuration properties 170 dependencies, //(array of commonjs.moduleId, optional) list of modules to be loaded before applying c
vendor: 61,510 bytes, lines 170-1904
170allback 171 callback //(function, optional) lambda expression to apply to module values implied by dependencies 172 ){ 173 return contextRequire(config, dependencies, callback, 0, req); 174 }, 175 176 // the loader uses the has.js API to control feature inclusion/exclusion; define then use throughout 177 global = this, 178 179 doc = global.document, 180 181 element = doc && doc.createElement("DiV"), 182 183 has = req.has = function(name){ 184 return isFunction(hasCache[name]) ? (hasCache[name] = hasCache[name](global, doc, element)) : hasCache[name]; 185 }, 186 187 hasCache = has.cache = defaultConfig.hasCache; 188 189 has.add = function(name, test, now, force){ 190 (hasCache[name]===undefined || force) && (hasCache[name] = test); 191 return now && has(name); 192 }; 193 194 0 && has.add("host-node", userConfig.has && "host-node" in userConfig.has ? 195 userConfig.has["host-node"] : 196 (typeof process == "object" && process.versions && process.versions.node && process.versions.v8)); 197 if( 0 ){ 198 // fixup the default config for node.js environment 199 require("./_base/configNode.js").config(defaultConfig); 200 // remember node's require (with respect to baseUrl==dojo's root) 201 defaultConfig.loaderPatch.nodeRequire = require; 202 } 203 204 0 && has.add("host-rhino", userConfig.has && "host-rhino" in userConfig.has ? 205 userConfig.has["host-rhino"] : 206 (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object"))); 207 if( 0 ){ 208 // owing to rhino's lame feature that hides the source of the script, give the user a way to specify the baseUrl... 209 for(var baseUrl = userConfig.baseUrl || ".", arg, rhinoArgs = this.arguments, i = 0; i < rhinoArgs.length;){ 210 arg = (rhinoArgs[i++] + "").split("="); 211 if(arg[0] == "baseUrl"){ 212 baseUrl = arg[1]; 213 break; 214 } 215 } 216 load(baseUrl + "/_base/configRhino.js"); 217 rhinoDojoConfig(defaultConfig, baseUrl, rhinoArgs); 218 } 219 220 has.add("host-webworker", ((typeof WorkerGlobalScope !== 'undefined') && (self instanceof WorkerGlobalScope))); 221 if(has("host-webworker")){ 222 mix(defaultConfig.hasCache, { 223 "host-browser": 0, 224 "dom": 0, 225 "dojo-dom-ready-api": 0, 226 "dojo-sniff": 0, 227 "dojo-inject-api": 1, 228 "host-webworker": 1 229 }); 230 231 defaultConfig.loaderPatch = { 232 injectUrl: function(url, callback){ 233 // TODO: 234 // This is not async, nor can it be in Webworkers. It could be made better by passing 235 // the entire require array into importScripts at. This way the scripts are loaded in 236 // async mode; even if the callbacks are ran in sync. It is not a major issue as webworkers 237 // tend to be long running where initial startup is not a major factor. 238 239 try{ 240 importScripts(url); 241 callback(); 242 }catch(e){ 243 console.info("failed to load resource (" + url + ")"); 244 console.error(e); 245 } 246 } 247 }; 248 } 249 250 // userConfig has tests override defaultConfig has tests; do this after the environment detection because 251 // the environment detection usually sets some has feature values in the hasCache. 252 for(var p in userConfig.has){ 253 has.add(p, userConfig.has[p], 0, 1); 254 } 255 256 // 257 // define the loader data 258 // 259 260 // the loader will use these like symbols if the loader has the traceApi; otherwise 261 // define magic numbers so that modules can be provided as part of defaultConfig 262 var requested = 1, 263 arrived = 2, 264 nonmodule = 3, 265 executing = 4, 266 executed = 5; 267 268 if( 0 ){ 269 // these make debugging nice; but using strings for symbols is a gross rookie error; don't do it for production code 270 requested = "requested"; 271 arrived = "arrived"; 272 nonmodule = "not-a-module"; 273 executing = "executing"; 274 executed = "executed"; 275 } 276 277 var legacyMode = 0, 278 sync = "sync", 279 xd = "xd", 280 syncExecStack = [], 281 dojoRequirePlugin = 0, 282 checkDojoRequirePlugin = noop, 283 transformToAmd = noop, 284 getXhr; 285 if( 0 ){ 286 req.isXdUrl = noop; 287 288 req.initSyncLoader = function(dojoRequirePlugin_, checkDojoRequirePlugin_, transformToAmd_){ 289 // the first dojo/_base/loader loaded gets to define these variables; they are designed to work 290 // in the presence of zero to many mapped dojo/_base/loaders 291 if(!dojoRequirePlugin){ 292 dojoRequirePlugin = dojoRequirePlugin_; 293 checkDojoRequirePlugin = checkDojoRequirePlugin_; 294 transformToAmd = transformToAmd_; 295 } 296 297 return { 298 sync:sync, 299 requested:requested, 300 arrived:arrived, 301 nonmodule:nonmodule, 302 executing:executing, 303 executed:executed, 304 syncExecStack:syncExecStack, 305 modules:modules, 306 execQ:execQ, 307 getModule:getModule, 308 injectModule:injectModule, 309 setArrived:setArrived, 310 signal:signal, 311 finishExec:finishExec, 312 execModule:execModule, 313 dojoRequirePlugin:dojoRequirePlugin, 314 getLegacyMode:function(){return legacyMode;}, 315 guardCheckComplete:guardCheckComplete 316 }; 317 }; 318 319 if( 1 || has("host-webworker")){ 320 // in legacy sync mode, the loader needs a minimal XHR library 321 322 var locationProtocol = location.protocol, 323 locationHost = location.host; 324 req.isXdUrl = function(url){ 325 if(/^\./.test(url)){ 326 // begins with a dot is always relative to page URL; therefore not xdomain 327 return false; 328 } 329 if(/^\/\//.test(url)){ 330 // for v1.6- backcompat, url starting with // indicates xdomain 331 return true; 332 } 333 // get protocol and host 334 // \/+ takes care of the typical file protocol that looks like file:///drive/path/to/file 335 // locationHost is falsy if file protocol => if locationProtocol matches and is "file:", || will return false 336 var match = url.match(/^([^\/\:]+\:)\/+([^\/]+)/); 337 return match && (match[1] != locationProtocol || (locationHost && match[2] != locationHost)); 338 }; 339 340 341 // note: to get the file:// protocol to work in FF, you must set security.fileuri.strict_origin_policy to false in about:config 342 1 || has.add("dojo-xhr-factory", 1); 343 has.add("dojo-force-activex-xhr", 1 && !doc.addEventListener && window.location.protocol == "file:"); 344 has.add("native-xhr", typeof XMLHttpRequest != "undefined"); 345 if(has("native-xhr") && !has("dojo-force-activex-xhr")){ 346 getXhr = function(){ 347 return new XMLHttpRequest(); 348 }; 349 }else{ 350 // if in the browser an old IE; find an xhr 351 for(var XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], progid, i = 0; i < 3;){ 352 try{ 353 progid = XMLHTTP_PROGIDS[i++]; 354 if(new ActiveXObject(progid)){ 355 // this progid works; therefore, use it from now on 356 break; 357 } 358 }catch(e){ 359 // squelch; we're just trying to find a good ActiveX progid 360 // if they all fail, then progid ends up as the last attempt and that will signal the error 361 // the first time the client actually tries to exec an xhr 362 } 363 } 364 getXhr = function(){ 365 return new ActiveXObject(progid); 366 }; 367 } 368 req.getXhr = getXhr; 369 370 has.add("dojo-gettext-api", 1); 371 req.getText = function(url, async, onLoad){ 372 var xhr = getXhr(); 373 xhr.open('GET', fixupUrl(url), false); 374 xhr.send(null); 375 if(xhr.status == 200 || (!location.host && !xhr.status)){ 376 if(onLoad){ 377 onLoad(xhr.responseText, async); 378 } 379 }else{ 380 throw makeError("xhrFailed", xhr.status); 381 } 382 return xhr.responseText; 383 }; 384 } 385 }else{ 386 req.async = 1; 387 } 388 389 // 390 // loader eval 391 // 392 var eval_ = 393 // use the function constructor so our eval is scoped close to (but not in) in the global space with minimal pollution 394 new Function('return eval(arguments[0]);'); 395 396 req.eval = 397 function(text, hint){ 398 return eval_(text + "\r\n//# sourceURL=" + hint); 399 }; 400 401 // 402 // loader micro events API 403 // 404 var listenerQueues = {}, 405 error = "error", 406 signal = req.signal = function(type, args){ 407 var queue = listenerQueues[type]; 408 // notice we run a copy of the queue; this allows listeners to add/remove 409 // other listeners without affecting this particular signal 410 forEach(queue && queue.slice(0), function(listener){ 411 listener.apply(null, isArray(args) ? args : [args]); 412 }); 413 }, 414 on = req.on = function(type, listener){ 415 // notice a queue is not created until a client actually connects 416 var queue = listenerQueues[type] || (listenerQueues[type] = []); 417 queue.push(listener); 418 return { 419 remove:function(){ 420 for(var i = 0; i<queue.length; i++){ 421 if(queue[i]===listener){ 422 queue.splice(i, 1); 423 return; 424 } 425 } 426 } 427 }; 428 }; 429 430 // configuration machinery; with an optimized/built defaultConfig, all configuration machinery can be discarded 431 // lexical variables hold key loader data structures to help with minification; these may be completely, 432 // one-time initialized by defaultConfig for optimized/built versions 433 var 434 aliases 435 // a vector of pairs of [regexs or string, replacement] => (alias, actual) 436 = [], 437 438 paths 439 // CommonJS paths 440 = {}, 441 442 pathsMapProg 443 // list of (from-path, to-path, regex, length) derived from paths; 444 // a "program" to apply paths; see computeMapProg 445 = [], 446 447 packs 448 // a map from packageId to package configuration object; see fixupPackageInfo 449 = {}, 450 451 map = req.map 452 // AMD map config variable; dojo/_base/kernel needs req.map to figure out the scope map 453 = {}, 454 455 mapProgs 456 // vector of quads as described by computeMapProg; map-key is AMD map key, map-value is AMD map value 457 = [], 458 459 modules 460 // A hash:(mid) --> (module-object) the module namespace 461 // 462 // pid: the package identifier to which the module belongs (e.g., "dojo"); "" indicates the system or default package 463 // mid: the fully-resolved (i.e., mappings have been applied) module identifier without the package identifier (e.g., "dojo/io/script") 464 // url: the URL from which the module was retrieved 465 // pack: the package object of the package to which the module belongs 466 // executed: 0 => not executed; executing => in the process of traversing deps and running factory; executed => factory has been executed 467 // deps: the dependency vector for this module (vector of modules objects) 468 // def: the factory for this module 469 // result: the result of the running the factory for this module 470 // injected: (0 | requested | arrived) the status of the module; nonmodule means the resource did not call define 471 // load: plugin load function; applicable only for plugins 472 // 473 // Modules go through several phases in creation: 474 // 475 // 1. Requested: some other module's definition or a require application contained the requested module in 476 // its dependency vector or executing code explicitly demands a module via req.require. 477 // 478 // 2. Injected: a script element has been appended to the insert-point element demanding the resource implied by the URL 479 // 480 // 3. Loaded: the resource injected in [2] has been evaluated. 481 // 482 // 4. Defined: the resource contained a define statement that advised the loader about the module. Notice that some 483 // resources may just contain a bundle of code and never formally define a module via define 484 // 485 // 5. Evaluated: the module was defined via define and the loader has evaluated the factory and computed a result. 486 = {}, 487 488 cacheBust 489 // query string to append to module URLs to bust browser cache 490 = "", 491 492 cache 493 // hash:(mid | url)-->(function | string) 494 // 495 // A cache of resources. The resources arrive via a config.cache object, which is a hash from either mid --> function or 496 // url --> string. The url key is distinguished from the mid key by always containing the prefix "url:". url keys as provided 497 // by config.cache always have a string value that represents the contents of the resource at the given url. mid keys as provided 498 // by configl.cache always have a function value that causes the same code to execute as if the module was script injected. 499 // 500 // Both kinds of key-value pairs are entered into cache via the function consumePendingCache, which may relocate keys as given 501 // by any mappings *iff* the config.cache was received as part of a module resource request. 502 // 503 // Further, for mid keys, the implied url is computed and the value is entered into that key as well. This allows mapped modules 504 // to retrieve cached items that may have arrived consequent to another namespace. 505 // 506 = {}, 507 508 urlKeyPrefix 509 // the prefix to prepend to a URL key in the cache. 510 = "url:", 511 512 pendingCacheInsert 513 // hash:(mid)-->(function) 514 // 515 // Gives a set of cache modules pending entry into cache. When cached modules are published to the loader, they are 516 // entered into pendingCacheInsert; modules are then pressed into cache upon (1) AMD define or (2) upon receiving another 517 // independent set of cached modules. (1) is the usual case, and this case allows normalizing mids given in the pending 518 // cache for the local configuration, possibly relocating modules. 519 = {}, 520 521 dojoSniffConfig 522 // map of configuration variables 523 // give the data-dojo-config as sniffed from the document (if any) 524 = {}, 525 526 insertPointSibling 527 // the nodes used to locate where scripts are injected into the document 528 = 0; 529 530 if( 1 ){ 531 var consumePendingCacheInsert = function(referenceModule){ 532 var p, item, match, now, m; 533 for(p in pendingCacheInsert){ 534 item = pendingCacheInsert[p]; 535 match = p.match(/^url\:(.+)/); 536 if(match){ 537 cache[urlKeyPrefix + toUrl(match[1], referenceModule)] = item; 538 }else if(p=="*now"){ 539 now = item; 540 }else if(p!="*noref"){ 541 m = getModuleInfo(p, referenceModule, true); 542 cache[m.mid] = cache[urlKeyPrefix + m.url] = item; 543 } 544 } 545 if(now){ 546 now(createRequire(referenceModule)); 547 } 548 pendingCacheInsert = {}; 549 }, 550 551 escapeString = function(s){ 552 return s.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(c){ return "\\" + c; }); 553 }, 554 555 computeMapProg = function(map, dest){ 556 // This routine takes a map as represented by a JavaScript object and initializes dest, a vector of 557 // quads of (map-key, map-value, refex-for-map-key, length-of-map-key), sorted decreasing by length- 558 // of-map-key. The regex looks for the map-key followed by either "/" or end-of-string at the beginning 559 // of a the search source. Notice the map-value is irrelevant to the algorithm 560 dest.splice(0, dest.length); 561 for(var p in map){ 562 dest.push([ 563 p, 564 map[p], 565 new RegExp("^" + escapeString(p) + "(\/|$)"), 566 p.length]); 567 } 568 dest.sort(function(lhs, rhs){ return rhs[3] - lhs[3]; }); 569 return dest; 570 }, 571 572 computeAliases = function(config, dest){ 573 forEach(config, function(pair){ 574 // take a fixed-up copy... 575 dest.push([isString(pair[0]) ? new RegExp("^" + escapeString(pair[0]) + "$") : pair[0], pair[1]]); 576 }); 577 }, 578 579 580 fixupPackageInfo = function(packageInfo){ 581 // calculate the precise (name, location, main, mappings) for a package 582 var name = packageInfo.name; 583 if(!name){ 584 // packageInfo must be a string that gives the name 585 name = packageInfo; 586 packageInfo = {name:name}; 587 } 588 packageInfo = mix({main:"main"}, packageInfo); 589 packageInfo.location = packageInfo.location ? packageInfo.location : name; 590 591 // packageMap is deprecated in favor of AMD map 592 if(packageInfo.packageMap){ 593 map[name] = packageInfo.packageMap; 594 } 595 596 if(!packageInfo.main.indexOf("./")){ 597 packageInfo.main = packageInfo.main.substring(2); 598 } 599 600 // now that we've got a fully-resolved package object, push it into the configuration 601 packs[name] = packageInfo; 602 }, 603 604 delayedModuleConfig 605 // module config cannot be consumed until the loader is completely initialized; therefore, all 606 // module config detected during booting is memorized and applied at the end of loader initialization 607 // TODO: this is a bit of a kludge; all config should be moved to end of loader initialization, but 608 // we'll delay this chore and do it with a final loader 1.x cleanup after the 2.x loader prototyping is complete 609 = [], 610 611 612 config = function(config, booting, referenceModule){ 613 for(var p in config){ 614 if(p=="waitSeconds"){ 615 req.waitms = (config[p] || 0) * 1000; 616 } 617 if(p=="cacheBust"){ 618 cacheBust = config[p] ? (isString(config[p]) ? config[p] : (new Date()).getTime() + "") : ""; 619 } 620 if(p=="baseUrl" || p=="combo"){ 621 req[p] = config[p]; 622 } 623 if( 0 && p=="async"){ 624 // falsy or "sync" => legacy sync loader 625 // "xd" => sync but loading xdomain tree and therefore loading asynchronously (not configurable, set automatically by the loader) 626 // "legacyAsync" => permanently in "xd" by choice 627 // "debugAtAllCosts" => trying to load everything via script injection (not implemented) 628 // otherwise, must be truthy => AMD 629 // legacyMode: sync | legacyAsync | xd | false 630 var mode = config[p]; 631 req.legacyMode = legacyMode = (isString(mode) && /sync|legacyAsync/.test(mode) ? mode : (!mode ? sync : false)); 632 req.async = !legacyMode; 633 } 634 if(config[p]!==hasCache){ 635 // accumulate raw config info for client apps which can use this to pass their own config 636 req.rawConfig[p] = config[p]; 637 p!="has" && has.add("config-"+p, config[p], 0, booting); 638 } 639 } 640 641 // make sure baseUrl exists 642 if(!req.baseUrl){ 643 req.baseUrl = "./"; 644 } 645 // make sure baseUrl ends with a slash 646 if(!/\/$/.test(req.baseUrl)){ 647 req.baseUrl += "/"; 648 } 649 650 // now do the special work for has, packages, packagePaths, paths, aliases, and cache 651 652 for(p in config.has){ 653 has.add(p, config.has[p], 0, booting); 654 } 655 656 // for each package found in any packages config item, augment the packs map owned by the loader 657 forEach(config.packages, fixupPackageInfo); 658 659 // for each packagePath found in any packagePaths config item, augment the packageConfig 660 // packagePaths is deprecated; remove in 2.0 661 for(var baseUrl in config.packagePaths){ 662 forEach(config.packagePaths[baseUrl], function(packageInfo){ 663 var location = baseUrl + "/" + packageInfo; 664 if(isString(packageInfo)){ 665 packageInfo = {name:packageInfo}; 666 } 667 packageInfo.location = location; 668 fixupPackageInfo(packageInfo); 669 }); 670 } 671 672 // notice that computeMapProg treats the dest as a reference; therefore, if/when that variable 673 // is published (see dojo-publish-privates), the published variable will always hold a valid value. 674 675 // this must come after all package processing since package processing may mutate map 676 computeMapProg(mix(map, config.map), mapProgs); 677 forEach(mapProgs, function(item){ 678 item[1] = computeMapProg(item[1], []); 679 if(item[0]=="*"){ 680 mapProgs.star = item; 681 } 682 }); 683 684 // push in any paths and recompute the internal pathmap 685 computeMapProg(mix(paths, config.paths), pathsMapProg); 686 687 // aliases 688 computeAliases(config.aliases, aliases); 689 690 if(booting){ 691 delayedModuleConfig.push({config:config.config}); 692 }else{ 693 for(p in config.config){ 694 var module = getModule(p, referenceModule); 695 module.config = mix(module.config || {}, config.config[p]); 696 } 697 } 698 699 // push in any new cache values 700 if(config.cache){ 701 consumePendingCacheInsert(); 702 pendingCacheInsert = config.cache; 703 if(config.cache["*noref"]){ 704 consumePendingCacheInsert(); 705 } 706 } 707 708 signal("config", [config, req.rawConfig]); 709 }; 710 711 // 712 // execute the various sniffs; userConfig can override and value 713 // 714 715 if(has("dojo-cdn") || 1 ){ 716 // the sniff regex looks for a src attribute ending in dojo.js, optionally preceded with a path. 717 // match[3] returns the path to dojo.js (if any) without the trailing slash. This is used for the 718 // dojo location on CDN deployments and baseUrl when either/both of these are not provided 719 // explicitly in the config data; this is the 1.6- behavior. 720 721 var scripts = doc.getElementsByTagName("script"), 722 i = 0, 723 script, dojoDir, src, match; 724 while(i < scripts.length){ 725 script = scripts[i++]; 726 if((src = script.getAttribute("src")) && (match = src.match(/(((.*)\/)|^)dojo\.js(\W|$)/i))){ 727 // sniff dojoDir and baseUrl 728 dojoDir = match[3] || ""; 729 defaultConfig.baseUrl = defaultConfig.baseUrl || dojoDir; 730 731 // remember an insertPointSibling 732 insertPointSibling = script; 733 } 734 735 // sniff configuration on attribute in script element 736 if((src = (script.getAttribute("data-dojo-config") || script.getAttribute("djConfig")))){ 737 dojoSniffConfig = req.eval("({ " + src + " })", "data-dojo-config"); 738 739 // remember an insertPointSibling 740 insertPointSibling = script; 741 } 742 743 // sniff requirejs attribute 744 if( 0 ){ 745 if((src = script.getAttribute("data-main"))){ 746 dojoSniffConfig.deps = dojoSniffConfig.deps || [src]; 747 } 748 } 749 } 750 } 751 752 if( 0 ){ 753 // pass down doh.testConfig from parent as if it were a data-dojo-config 754 try{ 755 if(window.parent != window && window.parent.require){ 756 var doh = window.parent.require("doh"); 757 doh && mix(dojoSniffConfig, doh.testConfig); 758 } 759 }catch(e){} 760 } 761 762 // configure the loader; let the user override defaults 763 req.rawConfig = {}; 764 config(defaultConfig, 1); 765 766 // do this before setting userConfig/sniffConfig to allow userConfig/sniff overrides 767 if(has("dojo-cdn")){ 768 packs.dojo.location = dojoDir; 769 if(dojoDir){ 770 dojoDir += "/"; 771 } 772 packs.dijit.location = dojoDir + "../dijit/"; 773 packs.dojox.location = dojoDir + "../dojox/"; 774 } 775 776 config(userConfig, 1); 777 config(dojoSniffConfig, 1); 778 779 }else{ 780 // no config API, assume defaultConfig has everything the loader needs...for the entire lifetime of the application 781 paths = defaultConfig.paths; 782 pathsMapProg = defaultConfig.pathsMapProg; 783 packs = defaultConfig.packs; 784 aliases = defaultConfig.aliases; 785 mapProgs = defaultConfig.mapProgs; 786 modules = defaultConfig.modules; 787 cache = defaultConfig.cache; 788 cacheBust = defaultConfig.cacheBust; 789 790 // remember the default config for other processes (e.g., dojo/config) 791 req.rawConfig = defaultConfig; 792 } 793 794 795 if( 0 ){ 796 req.combo = req.combo || {add:noop}; 797 var comboPending = 0, 798 combosPending = [], 799 comboPendingTimer = null; 800 } 801 802 803 // build the loader machinery iaw configuration, including has feature tests 804 var injectDependencies = function(module){ 805 // checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies 806 guardCheckComplete(function(){ 807 forEach(module.deps, injectModule); 808 if( 0 && comboPending && !comboPendingTimer){ 809 comboPendingTimer = setTimeout(function() { 810 comboPending = 0; 811 comboPendingTimer = null; 812 req.combo.done(function(mids, url) { 813 var onLoadCallback= function(){ 814 // defQ is a vector of module definitions 1-to-1, onto mids 815 runDefQ(0, mids); 816 checkComplete(); 817 }; 818 combosPending.push(mids); 819 injectingModule = mids; 820 req.injectUrl(url, onLoadCallback, mids); 821 injectingModule = 0; 822 }, req); 823 }, 0); 824 } 825 }); 826 }, 827 828 contextRequire = function(a1, a2, a3, referenceModule, contextRequire){ 829 var module, syntheticMid; 830 if(isString(a1)){ 831 // signature is (moduleId) 832 module = getModule(a1, referenceModule, true); 833 if(module && module.executed){ 834 return module.result; 835 } 836 throw makeError("undefinedModule", a1); 837 } 838 if(!isArray(a1)){ 839 // a1 is a configuration 840 config(a1, 0, referenceModule); 841 842 // juggle args; (a2, a3) may be (dependencies, callback) 843 a1 = a2; 844 a2 = a3; 845 } 846 if(isArray(a1)){ 847 // signature is (requestList [,callback]) 848 if(!a1.length){ 849 a2 && a2(); 850 }else{ 851 syntheticMid = "require*" + uid(); 852 853 // resolve the request list with respect to the reference module 854 for(var mid, deps = [], i = 0; i < a1.length;){ 855 mid = a1[i++]; 856 deps.push(getModule(mid, referenceModule)); 857 } 858 859 // construct a synthetic module to control execution of the requestList, and, optionally, callback 860 module = mix(makeModuleInfo("", syntheticMid, 0, ""), { 861 injected: arrived, 862 deps: deps, 863 def: a2 || noop, 864 require: referenceModule ? referenceModule.require : req, 865 gc: 1 //garbage collect 866 }); 867 modules[module.mid] = module; 868 869 // checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies 870 injectDependencies(module); 871 872 // try to immediately execute 873 // if already traversing a factory tree, then strict causes circular dependency to abort the execution; maybe 874 // it's possible to execute this require later after the current traversal completes and avoid the circular dependency. 875 // ...but *always* insist on immediate in synch mode 876 var strict = checkCompleteGuard && legacyMode!=sync; 877 guardCheckComplete(function(){ 878 execModule(module, strict); 879 }); 880 if(!module.executed){ 881 // some deps weren't on board or circular dependency detected and strict; therefore, push into the execQ 882 execQ.push(module); 883 } 884 checkComplete(); 885 } 886 } 887 return contextRequire; 888 }, 889 890 createRequire = function(module){ 891 if(!module){ 892 return req; 893 } 894 var result = module.require; 895 if(!result){ 896 result = function(a1, a2, a3){ 897 return contextRequire(a1, a2, a3, module, result); 898 }; 899 module.require = mix(result, req); 900 result.module = module; 901 result.toUrl = function(name){ 902 return toUrl(name, module); 903 }; 904 result.toAbsMid = function(mid){ 905 return toAbsMid(mid, module); 906 }; 907 if( 0 ){ 908 result.undef = function(mid){ 909 req.undef(mid, module); 910 }; 911 } 912 if( 0 ){ 913 result.syncLoadNls = function(mid){ 914 var nlsModuleInfo = getModuleInfo(mid, module), 915 nlsModule = modules[nlsModuleInfo.mid]; 916 if(!nlsModule || !nlsModule.executed){ 917 cached = cache[nlsModuleInfo.mid] || cache[urlKeyPrefix + nlsModuleInfo.url]; 918 if(cached){ 919 evalModuleText(cached); 920 nlsModule = modules[nlsModuleInfo.mid]; 921 } 922 } 923 return nlsModule && nlsModule.executed && nlsModule.result; 924 }; 925 } 926 927 } 928 return result; 929 }, 930 931 execQ = 932 // The list of modules that need to be evaluated. 933 [], 934 935 defQ = 936 // The queue of define arguments sent to loader. 937 [], 938 939 waiting = 940 // The set of modules upon which the loader is waiting for definition to arrive 941 {}, 942 943 setRequested = function(module){ 944 module.injected = requested; 945 waiting[module.mid] = 1; 946 if(module.url){ 947 waiting[module.url] = module.pack || 1; 948 } 949 startTimer(); 950 }, 951 952 setArrived = function(module){ 953 module.injected = arrived; 954 delete waiting[module.mid]; 955 if(module.url){ 956 delete waiting[module.url]; 957 } 958 if(isEmpty(waiting)){ 959 clearTimer(); 960 0 && legacyMode==xd && (legacyMode = sync); 961 } 962 }, 963 964 execComplete = req.idle = 965 // says the loader has completed (or not) its work 966 function(){ 967 return !defQ.length && isEmpty(waiting) && !execQ.length && !checkCompleteGuard; 968 }, 969 970 runMapProg = function(targetMid, map){ 971 // search for targetMid in map; return the map item if found; falsy otherwise 972 if(map){ 973 for(var i = 0; i < map.length; i++){ 974 if(map[i][2].test(targetMid)){ 975 return map[i]; 976 } 977 } 978 } 979 return 0; 980 }, 981 982 compactPath = function(path){ 983 var result = [], 984 segment, lastSegment; 985 path = path.replace(/\\/g, '/').split('/'); 986 while(path.length){ 987 segment = path.shift(); 988 if(segment==".." && result.length && lastSegment!=".."){ 989 result.pop(); 990 lastSegment = result[result.length - 1]; 991 }else if(segment!="."){ 992 result.push(lastSegment= segment); 993 } // else ignore "." 994 } 995 return result.join("/"); 996 }, 997 998 makeModuleInfo = function(pid, mid, pack, url){ 999 if( 0 ){ 1000 var xd= req.isXdUrl(url); 1001 return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0, isXd:xd, isAmd:!!(xd || (packs[pid] && packs[pid].isAmd))}; 1002 }else{ 1003 return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0}; 1004 } 1005 }, 1006 1007 getModuleInfo_ = function(mid, referenceModule, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate){ 1008 // arguments are passed instead of using lexical variables so that this function my be used independent of the loader (e.g., the builder) 1009 // alwaysCreate is useful in this case so that getModuleInfo never returns references to real modules owned by the loader 1010 var pid, pack, midInPackage, mapItem, url, result, isRelative, requestedMid; 1011 requestedMid = mid; 1012 isRelative = /^\./.test(mid); 1013 if(/(^\/)|(\:)|(\.js$)/.test(mid) || (isRelative && !referenceModule)){ 1014 // absolute path or protocol of .js filetype, or relative path but no reference module and therefore relative to page 1015 // whatever it is, it's not a module but just a URL of some sort 1016 // note: pid===0 indicates the routine is returning an unmodified mid 1017 1018 return makeModuleInfo(0, mid, 0, mid); 1019 }else{ 1020 // relative module ids are relative to the referenceModule; get rid of any dots 1021 mid = compactPath(isRelative ? (referenceModule.mid + "/../" + mid) : mid); 1022 if(/^\./.test(mid)){ 1023 throw makeError("irrationalPath", mid); 1024 } 1025 // at this point, mid is an absolute mid 1026 1027 // map the mid 1028 if(referenceModule){ 1029 mapItem = runMapProg(referenceModule.mid, mapProgs); 1030 } 1031 mapItem = mapItem || mapProgs.star; 1032 mapItem = mapItem && runMapProg(mid, mapItem[1]); 1033 1034 if(mapItem){ 1035 mid = mapItem[1] + mid.substring(mapItem[3]); 1036 } 1037 1038 match = mid.match(/^([^\/]+)(\/(.+))?$/); 1039 pid = match ? match[1] : ""; 1040 if((pack = packs[pid])){ 1041 mid = pid + "/" + (midInPackage = (match[3] || pack.main)); 1042 }else{ 1043 pid = ""; 1044 } 1045 1046 // search aliases 1047 var candidateLength = 0, 1048 candidate = 0; 1049 forEach(aliases, function(pair){ 1050 var match = mid.match(pair[0]); 1051 if(match && match.length>candidateLength){ 1052 candidate = isFunction(pair[1]) ? mid.replace(pair[0], pair[1]) : pair[1]; 1053 } 1054 }); 1055 if(candidate){ 1056 return getModuleInfo_(candidate, 0, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate); 1057 } 1058 1059 result = modules[mid]; 1060 if(result){ 1061 return alwaysCreate ? makeModuleInfo(result.pid, result.mid, result.pack, result.url) : modules[mid]; 1062 } 1063 } 1064 // get here iff the sought-after module does not yet exist; therefore, we need to compute the URL given the 1065 // fully resolved (i.e., all relative indicators and package mapping resolved) module id 1066 1067 // note: pid!==0 indicates the routine is returning a url that has .js appended unmodified mid 1068 mapItem = runMapProg(mid, pathsMapProg); 1069 if(mapItem){ 1070 url = mapItem[1] + mid.substring(mapItem[3]); 1071 }else if(pid){ 1072 url = pack.location + "/" + midInPackage; 1073 }else if( 0 ){ 1074 url = "../" + mid; 1075 }else{ 1076 url = mid; 1077 } 1078 // if result is not absolute, add baseUrl 1079 if(!(/(^\/)|(\:)/.test(url))){ 1080 url = baseUrl + url; 1081 } 1082 url += ".js"; 1083 return makeModuleInfo(pid, mid, pack, compactPath(url)); 1084 }, 1085 1086 getModuleInfo = function(mid, referenceModule, fromPendingCache){ 1087 return getModuleInfo_(mid, referenceModule, packs, modules, req.baseUrl, fromPendingCache ? [] : mapProgs, fromPendingCache ? [] : pathsMapProg, fromPendingCache ? [] : aliases); 1088 }, 1089 1090 resolvePluginResourceId = function(plugin, prid, referenceModule){ 1091 return plugin.normalize ? plugin.normalize(prid, function(mid){return toAbsMid(mid, referenceModule);}) : toAbsMid(prid, referenceModule); 1092 }, 1093 1094 dynamicPluginUidGenerator = 0, 1095 1096 getModule = function(mid, referenceModule, immediate){ 1097 // compute and optionally construct (if necessary) the module implied by the mid with respect to referenceModule 1098 var match, plugin, prid, result; 1099 match = mid.match(/^(.+?)\!(.*)$/); 1100 if(match){ 1101 // name was <plugin-module>!<plugin-resource-id> 1102 plugin = getModule(match[1], referenceModule, immediate); 1103 1104 if( 0 && legacyMode == sync && !plugin.executed){ 1105 injectModule(plugin); 1106 if(plugin.injected===arrived && !plugin.executed){ 1107 guardCheckComplete(function(){ 1108 execModule(plugin); 1109 }); 1110 } 1111 if(plugin.executed){ 1112 promoteModuleToPlugin(plugin); 1113 }else{ 1114 // we are in xdomain mode for some reason 1115 execQ.unshift(plugin); 1116 } 1117 } 1118 1119 1120 1121 if(plugin.executed === executed && !plugin.load){ 1122 // executed the module not knowing it was a plugin 1123 promoteModuleToPlugin(plugin); 1124 } 1125 1126 // if the plugin has not been loaded, then can't resolve the prid and must assume this plugin is dynamic until we find out otherwise 1127 if(plugin.load){ 1128 prid = resolvePluginResourceId(plugin, match[2], referenceModule); 1129 mid = (plugin.mid + "!" + (plugin.dynamic ? ++dynamicPluginUidGenerator + "!" : "") + prid); 1130 }else{ 1131 prid = match[2]; 1132 mid = plugin.mid + "!" + (++dynamicPluginUidGenerator) + "!waitingForPlugin"; 1133 } 1134 result = {plugin:plugin, mid:mid, req:createRequire(referenceModule), prid:prid}; 1135 }else{ 1136 result = getModuleInfo(mid, referenceModule); 1137 } 1138 return modules[result.mid] || (!immediate && (modules[result.mid] = result)); 1139 }, 1140 1141 toAbsMid = req.toAbsMid = function(mid, referenceModule){ 1142 return getModuleInfo(mid, referenceModule).mid; 1143 }, 1144 1145 toUrl = req.toUrl = function(name, referenceModule){ 1146 var moduleInfo = getModuleInfo(name+"/x", referenceModule), 1147 url= moduleInfo.url; 1148 return fixupUrl(moduleInfo.pid===0 ? 1149 // if pid===0, then name had a protocol or absolute path; either way, toUrl is the identify function in such cases 1150 name : 1151 // "/x.js" since getModuleInfo automatically appends ".js" and we appended "/x" to make name look like a module id 1152 url.substring(0, url.length-5) 1153 ); 1154 }, 1155 1156 nonModuleProps = { 1157 injected: arrived, 1158 executed: executed, 1159 def: nonmodule, 1160 result: nonmodule 1161 }, 1162 1163 makeCjs = function(mid){ 1164 return modules[mid] = mix({mid:mid}, nonModuleProps); 1165 }, 1166 1167 cjsRequireModule = makeCjs("require"), 1168 cjsExportsModule = makeCjs("exports"), 1169 cjsModuleModule = makeCjs("module"), 1170 1171 runFactory = function(module, args){ 1172 req.trace("loader-run-factory", [module.mid]); 1173 var factory = module.def, 1174 result; 1175 0 && syncExecStack.unshift(module); 1176 if( 0 ){ 1177 try{ 1178 result= isFunction(factory) ? factory.apply(null, args) : factory; 1179 }catch(e){ 1180 signal(error, module.result = makeError("factoryThrew", [module, e])); 1181 } 1182 }else{ 1183 result= isFunction(factory) ? factory.apply(null, args) : factory; 1184 } 1185 module.result = result===undefined && module.cjs ? module.cjs.exports : result; 1186 0 && syncExecStack.shift(module); 1187 }, 1188 1189 abortExec = {}, 1190 1191 defOrder = 0, 1192 1193 promoteModuleToPlugin = function(pluginModule){ 1194 var plugin = pluginModule.result; 1195 pluginModule.dynamic = plugin.dynamic; 1196 pluginModule.normalize = plugin.normalize; 1197 pluginModule.load = plugin.load; 1198 return pluginModule; 1199 }, 1200 1201 resolvePluginLoadQ = function(plugin){ 1202 // plugins is a newly executed module that has a loadQ waiting to run 1203 1204 // step 1: traverse the loadQ and fixup the mid and prid; remember the map from original mid to new mid 1205 // recall the original mid was created before the plugin was on board and therefore it was impossible to 1206 // compute the final mid; accordingly, prid may or may not change, but the mid will definitely change 1207 var map = {}; 1208 forEach(plugin.loadQ, function(pseudoPluginResource){ 1209 // manufacture and insert the real module in modules 1210 var prid = resolvePluginResourceId(plugin, pseudoPluginResource.prid, pseudoPluginResource.req.module), 1211 mid = plugin.dynamic ? pseudoPluginResource.mid.replace(/waitingForPlugin$/, prid) : (plugin.mid + "!" + prid), 1212 pluginResource = mix(mix({}, pseudoPluginResource), {mid:mid, prid:prid, injected:0}); 1213 if(!modules[mid]){ 1214 // create a new (the real) plugin resource and inject it normally now that the plugin is on board 1215 injectPlugin(modules[mid] = pluginResource); 1216 } // else this was a duplicate request for the same (plugin, rid) for a nondynamic plugin 1217 1218 // pluginResource is really just a placeholder with the wrong mid (because we couldn't calculate it until the plugin was on board) 1219 // mark is as arrived and delete it from modules; the real module was requested above 1220 map[pseudoPluginResource.mid] = modules[mid]; 1221 setArrived(pseudoPluginResource); 1222 delete modules[pseudoPluginResource.mid]; 1223 }); 1224 plugin.loadQ = 0; 1225 1226 // step2: replace all references to any placeholder modules with real modules 1227 var substituteModules = function(module){ 1228 for(var replacement, deps = module.deps || [], i = 0; i<deps.length; i++){ 1229 replacement = map[deps[i].mid]; 1230 if(replacement){ 1231 deps[i] = replacement; 1232 } 1233 } 1234 }; 1235 for(var p in modules){ 1236 substituteModules(modules[p]); 1237 } 1238 forEach(execQ, substituteModules); 1239 }, 1240 1241 finishExec = function(module){ 1242 req.trace("loader-finish-exec", [module.mid]); 1243 module.executed = executed; 1244 module.defOrder = defOrder++; 1245 0 && forEach(module.provides, function(cb){ cb(); }); 1246 if(module.loadQ){ 1247 // the module was a plugin 1248 promoteModuleToPlugin(module); 1249 resolvePluginLoadQ(module); 1250 } 1251 // remove all occurrences of this module from the execQ 1252 for(i = 0; i < execQ.length;){ 1253 if(execQ[i] === module){ 1254 execQ.splice(i, 1); 1255 }else{ 1256 i++; 1257 } 1258 } 1259 // delete references to synthetic modules 1260 if (/^require\*/.test(module.mid)) { 1261 delete modules[module.mid]; 1262 } 1263 }, 1264 1265 circleTrace = [], 1266 1267 execModule = function(module, strict){ 1268 // run the dependency vector, then run the factory for module 1269 if(module.executed === executing){ 1270 req.trace("loader-circular-dependency", [circleTrace.concat(module.mid).join("->")]); 1271 return (!module.def || strict) ? abortExec : (module.cjs && module.cjs.exports); 1272 } 1273 // at this point the module is either not executed or fully executed 1274 1275 1276 if(!module.executed){ 1277 if(!module.def){ 1278 return abortExec; 1279 } 1280 var mid = module.mid, 1281 deps = module.deps || [], 1282 arg, argResult, 1283 args = [], 1284 i = 0; 1285 1286 if( 0 ){ 1287 circleTrace.push(mid); 1288 req.trace("loader-exec-module", ["exec", circleTrace.length, mid]); 1289 } 1290 1291 // for circular dependencies, assume the first module encountered was executed OK 1292 // modules that circularly depend on a module that has not run its factory will get 1293 // the pre-made cjs.exports===module.result. They can take a reference to this object and/or 1294 // add properties to it. When the module finally runs its factory, the factory can 1295 // read/write/replace this object. Notice that so long as the object isn't replaced, any 1296 // reference taken earlier while walking the deps list is still valid. 1297 module.executed = executing; 1298 while((arg = deps[i++])){ 1299 argResult = ((arg === cjsRequireModule) ? createRequire(module) : 1300 ((arg === cjsExportsModule) ? module.cjs.exports : 1301 ((arg === cjsModuleModule) ? module.cjs : 1302 execModule(arg, strict)))); 1303 if(argResult === abortExec){ 1304 module.executed = 0; 1305 req.trace("loader-exec-module", ["abort", mid]); 1306 0 && circleTrace.pop(); 1307 return abortExec; 1308 } 1309 args.push(argResult); 1310 } 1311 runFactory(module, args); 1312 finishExec(module); 1313 0 && circleTrace.pop(); 1314 } 1315 // at this point the module is guaranteed fully executed 1316 1317 return module.result; 1318 }, 1319 1320 1321 checkCompleteGuard = 0, 1322 1323 guardCheckComplete = function(proc){ 1324 try{ 1325 checkCompleteGuard++; 1326 proc(); 1327 }finally{ 1328 checkCompleteGuard--; 1329 } 1330 if(execComplete()){ 1331 signal("idle", []); 1332 } 1333 }, 1334 1335 checkComplete = function(){ 1336 // keep going through the execQ as long as at least one factory is executed 1337 // plugins, recursion, cached modules all make for many execution path possibilities 1338 if(checkCompleteGuard){ 1339 return; 1340 } 1341 guardCheckComplete(function(){ 1342 checkDojoRequirePlugin(); 1343 for(var currentDefOrder, module, i = 0; i < execQ.length;){ 1344 currentDefOrder = defOrder; 1345 module = execQ[i]; 1346 execModule(module); 1347 if(currentDefOrder!=defOrder){ 1348 // defOrder was bumped one or more times indicating something was executed (note, this indicates 1349 // the execQ was modified, maybe a lot (for example a later module causes an earlier module to execute) 1350 checkDojoRequirePlugin(); 1351 i = 0; 1352 }else{ 1353 // nothing happened; check the next module in the exec queue 1354 i++; 1355 } 1356 } 1357 }); 1358 }; 1359 1360 1361 if( 0 ){ 1362 req.undef = function(moduleId, referenceModule){ 1363 // In order to reload a module, it must be undefined (this routine) and then re-requested. 1364 // This is useful for testing frameworks (at least). 1365 var module = getModule(moduleId, referenceModule); 1366 setArrived(module); 1367 mix(module, {def:0, executed:0, injected:0, node:0}); 1368 }; 1369 } 1370 1371 if( 1 ){ 1372 if(has("dojo-loader-eval-hint-url")===undefined){ 1373 has.add("dojo-loader-eval-hint-url", 1); 1374 } 1375 1376 var fixupUrl= typeof userConfig.fixupUrl == "function" ? userConfig.fixupUrl : function(url){ 1377 url += ""; // make sure url is a Javascript string (some paths may be a Java string) 1378 return url + (cacheBust ? ((/\?/.test(url) ? "&" : "?") + cacheBust) : ""); 1379 }, 1380 1381 injectPlugin = function( 1382 module 1383 ){ 1384 // injects the plugin module given by module; may have to inject the plugin itself 1385 var plugin = module.plugin; 1386 1387 if(plugin.executed === executed && !plugin.load){ 1388 // executed the module not knowing it was a plugin 1389 promoteModuleToPlugin(plugin); 1390 } 1391 1392 var onLoad = function(def){ 1393 module.result = def; 1394 setArrived(module); 1395 finishExec(module); 1396 checkComplete(); 1397 }; 1398 1399 if(plugin.load){ 1400 plugin.load(module.prid, module.req, onLoad); 1401 }else if(plugin.loadQ){ 1402 plugin.loadQ.push(module); 1403 }else{ 1404 // the unshift instead of push is important: we don't want plugins to execute as 1405 // dependencies of some other module because this may cause circles when the plugin 1406 // loadQ is run; also, generally, we want plugins to run early since they may load 1407 // several other modules and therefore can potentially unblock many modules 1408 plugin.loadQ = [module]; 1409 execQ.unshift(plugin); 1410 injectModule(plugin); 1411 } 1412 }, 1413 1414 // for IE, injecting a module may result in a recursive execution if the module is in the cache 1415 1416 cached = 0, 1417 1418 injectingModule = 0, 1419 1420 injectingCachedModule = 0, 1421 1422 evalModuleText = function(text, module){ 1423 // see def() for the injectingCachedModule bracket; it simply causes a short, safe circuit 1424 if(has("config-stripStrict")){ 1425 text = text.replace(/"use strict"/g, ''); 1426 } 1427 injectingCachedModule = 1; 1428 if( 0 ){ 1429 try{ 1430 if(text===cached){ 1431 cached.call(null); 1432 }else{ 1433 req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid); 1434 } 1435 }catch(e){ 1436 signal(error, makeError("evalModuleThrew", module)); 1437 } 1438 }else{ 1439 if(text===cached){ 1440 cached.call(null); 1441 }else{ 1442 req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid); 1443 } 1444 } 1445 injectingCachedModule = 0; 1446 }, 1447 1448 injectModule = function(module){ 1449 // Inject the module. In the browser environment, this means appending a script element into 1450 // the document; in other environments, it means loading a file. 1451 // 1452 // If in synchronous mode, then get the module synchronously if it's not xdomainLoading. 1453 1454 var mid = module.mid, 1455 url = module.url; 1456 if(module.executed || module.injected || waiting[mid] || (module.url && ((module.pack && waiting[module.url]===module.pack) || waiting[module.url]==1))){ 1457 return; 1458 } 1459 setRequested(module); 1460 1461 if( 0 ){ 1462 var viaCombo = 0; 1463 if(module.plugin && module.plugin.isCombo){ 1464 // a combo plugin; therefore, must be handled by combo service 1465 // the prid should have already been converted to a URL (if required by the plugin) during 1466 // the normalize process; in any event, there is no way for the loader to know how to 1467 // to the conversion; therefore the third argument is zero 1468 req.combo.add(module.plugin.mid, module.prid, 0, req); 1469 viaCombo = 1; 1470 }else if(!module.plugin){ 1471 viaCombo = req.combo.add(0, module.mid, module.url, req); 1472 } 1473 if(viaCombo){ 1474 comboPending= 1; 1475 return; 1476 } 1477 } 1478 1479 if(module.plugin){ 1480 injectPlugin(module); 1481 return; 1482 } // else a normal module (not a plugin) 1483 1484 1485 var onLoadCallback = function(){ 1486 runDefQ(module); 1487 if(module.injected !== arrived){ 1488 // the script that contained the module arrived and has been executed yet 1489 // nothing was added to the defQ (so it wasn't an AMD module) and the module 1490 // wasn't marked as arrived by dojo.provide (so it wasn't a v1.6- module); 1491 // therefore, it must not have been a module; adjust state accordingly 1492 if(has("dojo-enforceDefine")){ 1493 signal(error, makeError("noDefine", module)); 1494 return; 1495 } 1496 setArrived(module); 1497 mix(module, nonModuleProps); 1498 req.trace("loader-define-nonmodule", [module.url]); 1499 } 1500 1501 if( 0 && legacyMode){ 1502 // must call checkComplete even in for sync loader because we may be in xdomainLoading mode; 1503 // but, if xd loading, then don't call checkComplete until out of the current sync traversal 1504 // in order to preserve order of execution of the dojo.required modules 1505 !syncExecStack.length && checkComplete(); 1506 }else{ 1507 checkComplete(); 1508 } 1509 }; 1510 cached = cache[mid] || cache[urlKeyPrefix + module.url]; 1511 if(cached){ 1512 req.trace("loader-inject", ["cache", module.mid, url]); 1513 evalModuleText(cached, module); 1514 onLoadCallback(); 1515 return; 1516 } 1517 if( 0 && legacyMode){ 1518 if(module.isXd){ 1519 // switch to async mode temporarily; if current legacyMode!=sync, then is must be one of {legacyAsync, xd, false} 1520 legacyMode==sync && (legacyMode = xd); 1521 // fall through and load via script injection 1522 }else if(module.isAmd && legacyMode!=sync){ 1523 // fall through and load via script injection 1524 }else{ 1525 // mode may be sync, xd/legacyAsync, or async; module may be AMD or legacy; but module is always located on the same domain 1526 var xhrCallback = function(text){ 1527 if(legacyMode==sync){ 1528 // the top of syncExecStack gives the current synchronously executing module; the loader needs 1529 // to know this if it has to switch to async loading in the middle of evaluating a legacy module 1530 // this happens when a modules dojo.require's a module that must be loaded async because it's xdomain 1531 // (using unshift/shift because there is no back() methods for Javascript arrays) 1532 syncExecStack.unshift(module); 1533 evalModuleText(text, module); 1534 syncExecStack.shift(); 1535 1536 // maybe the module was an AMD module 1537 runDefQ(module); 1538 1539 // legacy modules never get to defineModule() => cjs and injected never set; also evaluation implies executing 1540 if(!module.cjs){ 1541 setArrived(module); 1542 finishExec(module); 1543 } 1544 1545 if(module.finish){ 1546 // while synchronously evaluating this module, dojo.require was applied referencing a module 1547 // that had to be loaded async; therefore, the loader stopped answering all dojo.require 1548 // requests so they could be answered completely in the correct sequence; module.finish gives 1549 // the list of dojo.requires that must be re-applied once all target modules are available; 1550 // make a synthetic module to execute the dojo.require's in the correct order 1551 1552 // compute a guaranteed-unique mid for the synthetic finish module; remember the finish vector; remove it from the reference module 1553 // TODO: can we just leave the module.finish...what's it hurting? 1554 var finishMid = mid + "*finish", 1555 finish = module.finish; 1556 delete module.finish; 1557 1558 def(finishMid, ["dojo", ("dojo/require!" + finish.join(",")).replace(/\./g, "/")], function(dojo){ 1559 forEach(finish, function(mid){ dojo.require(mid); }); 1560 }); 1561 // unshift, not push, which causes the current traversal to be reattempted from the top 1562 execQ.unshift(getModule(finishMid)); 1563 } 1564 onLoadCallback(); 1565 }else{ 1566 text = transformToAmd(module, text); 1567 if(text){ 1568 evalModuleText(text, module); 1569 onLoadCallback(); 1570 }else{ 1571 // if transformToAmd returned falsy, then the module was already AMD and it can be script-injected 1572 // do so to improve debugability(even though it means another download...which probably won't happen with a good browser cache) 1573 injectingModule = module; 1574 req.injectUrl(fixupUrl(url), onLoadCallback, module); 1575 injectingModule = 0; 1576 } 1577 } 1578 }; 1579 1580 req.trace("loader-inject", ["xhr", module.mid, url, legacyMode!=sync]); 1581 if( 0 ){ 1582 try{ 1583 req.getText(url, legacyMode!=sync, xhrCallback); 1584 }catch(e){ 1585 signal(error, makeError("xhrInjectFailed", [module, e])); 1586 } 1587 }else{ 1588 req.getText(url, legacyMode!=sync, xhrCallback); 1589 } 1590 return; 1591 } 1592 } // else async mode or fell through in xdomain loading mode; either way, load by script injection 1593 req.trace("loader-inject", ["script", module.mid, url]); 1594 injectingModule = module; 1595 req.injectUrl(fixupUrl(url), onLoadCallback, module); 1596 injectingModule = 0; 1597 }, 1598 1599 defineModule = function(module, deps, def){ 1600 req.trace("loader-define-module", [module.mid, deps]); 1601 1602 if( 0 && module.plugin && module.plugin.isCombo){ 1603 // the module is a plugin resource loaded by the combo service 1604 // note: check for module.plugin should be enough since normal plugin resources should 1605 // not follow this path; module.plugin.isCombo is future-proofing belt and suspenders 1606 module.result = isFunction(def) ? def() : def; 1607 setArrived(module); 1608 finishExec(module); 1609 return module; 1610 } 1611 1612 var mid = module.mid; 1613 if(module.injected === arrived){ 1614 signal(error, makeError("multipleDefine", module)); 1615 return module; 1616 } 1617 mix(module, { 1618 deps: deps, 1619 def: def, 1620 cjs: { 1621 id: module.mid, 1622 uri: module.url, 1623 exports: (module.result = {}), 1624 setExports: function(exports){ 1625 module.cjs.exports = exports; 1626 }, 1627 config:function(){ 1628 return module.config; 1629 } 1630 } 1631 }); 1632 1633 // resolve deps with respect to this module 1634 for(var i = 0; deps[i]; i++){ 1635 deps[i] = getModule(deps[i], module); 1636 } 1637 1638 if( 0 && legacyMode && !waiting[mid]){ 1639 // the module showed up without being asked for; it was probably in a <script> element 1640 injectDependencies(module); 1641 execQ.push(module); 1642 checkComplete(); 1643 } 1644 setArrived(module); 1645 1646 if(!isFunction(def) && !deps.length){ 1647 module.result = def; 1648 finishExec(module); 1649 } 1650 1651 return module; 1652 }, 1653 1654 runDefQ = function(referenceModule, mids){ 1655 // defQ is an array of [id, dependencies, factory] 1656 // mids (if any) is a vector of mids given by a combo service 1657 var definedModules = [], 1658 module, args; 1659 while(defQ.length){ 1660 args = defQ.shift(); 1661 mids && (args[0]= mids.shift()); 1662 // explicit define indicates possible multiple modules in a single file; delay injecting dependencies until defQ fully 1663 // processed since modules earlier in the queue depend on already-arrived modules that are later in the queue 1664 // TODO: what if no args[0] and no referenceModule 1665 module = (args[0] && getModule(args[0])) || referenceModule; 1666 definedModules.push([module, args[1], args[2]]); 1667 } 1668 consumePendingCacheInsert(referenceModule); 1669 forEach(definedModules, function(args){ 1670 injectDependencies(defineModule.apply(null, args)); 1671 }); 1672 }; 1673 } 1674 1675 var timerId = 0, 1676 clearTimer = noop, 1677 startTimer = noop; 1678 if( 0 ){ 1679 // Timer machinery that monitors how long the loader is waiting and signals an error when the timer runs out. 1680 clearTimer = function(){ 1681 timerId && clearTimeout(timerId); 1682 timerId = 0; 1683 }; 1684 1685 startTimer = function(){ 1686 clearTimer(); 1687 if(req.waitms){ 1688 timerId = global.setTimeout(function(){ 1689 clearTimer(); 1690 signal(error, makeError("timeout", waiting)); 1691 }, req.waitms); 1692 } 1693 }; 1694 } 1695 1696 if ( 1 ) { 1697 // Test for IE's different way of signaling when scripts finish loading. Note that according to 1698 // http://bugs.dojotoolkit.org/ticket/15096#comment:14, IE9 also needs to follow the 1699 // IE specific code path even though it has an addEventListener() method. 1700 // Unknown if special path needed on IE10+, which also has a document.attachEvent() method. 1701 // Should evaluate to false for Opera and Windows 8 apps, even though they document.attachEvent() 1702 // is defined in both those environments. 1703 has.add("ie-event-behavior", doc.attachEvent && typeof Windows === "undefined" && 1704 (typeof opera === "undefined" || opera.toString() != "[object Opera]")); 1705 } 1706 1707 if( 1 && ( 1 || 1 )){ 1708 var domOn = function(node, eventName, ieEventName, handler){ 1709 // Add an event listener to a DOM node using the API appropriate for the current browser; 1710 // return a function that will disconnect the listener. 1711 if(!has("ie-event-behavior")){ 1712 node.addEventListener(eventName, handler, false); 1713 return function(){ 1714 node.removeEventListener(eventName, handler, false); 1715 }; 1716 }else{ 1717 node.attachEvent(ieEventName, handler); 1718 return function(){ 1719 node.detachEvent(ieEventName, handler); 1720 }; 1721 } 1722 }, 1723 windowOnLoadListener = domOn(window, "load", "onload", function(){ 1724 req.pageLoaded = 1; 1725 doc.readyState!="complete" && (doc.readyState = "complete"); 1726 windowOnLoadListener(); 1727 }); 1728 1729 if( 1 ){ 1730 // if the loader is on the page, there must be at least one script element 1731 // getting its parent and then doing insertBefore solves the "Operation Aborted" 1732 // error in IE from appending to a node that isn't properly closed; see 1733 // dojo/tests/_base/loader/requirejs/simple-badbase.html for an example 1734 // don't use scripts with type dojo/... since these may be removed; see #15809 1735 // prefer to use the insertPoint computed during the config sniff in case a script is removed; see #16958 1736 var scripts = doc.getElementsByTagName("script"), 1737 i = 0, 1738 script; 1739 while(!insertPointSibling){ 1740 if(!/^dojo/.test((script = scripts[i++]) && script.type)){ 1741 insertPointSibling= script; 1742 } 1743 } 1744 1745 req.injectUrl = function(url, callback, owner){ 1746 // insert a script element to the insert-point element with src=url; 1747 // apply callback upon detecting the script has loaded. 1748 1749 var node = owner.node = doc.createElement("script"), 1750 onLoad = function(e){ 1751 e = e || window.event; 1752 var node = e.target || e.srcElement; 1753 if(e.type === "load" || /complete|loaded/.test(node.readyState)){ 1754 loadDisconnector(); 1755 errorDisconnector(); 1756 callback && callback(); 1757 } 1758 }, 1759 loadDisconnector = domOn(node, "load", "onreadystatechange", onLoad), 1760 errorDisconnector = domOn(node, "error", "onerror", function(e){ 1761 loadDisconnector(); 1762 errorDisconnector(); 1763 signal(error, makeError("scriptError", [url, e])); 1764 }); 1765 1766 node.type = "text/javascript"; 1767 node.charset = "utf-8"; 1768 node.src = url; 1769 insertPointSibling.parentNode.insertBefore(node, insertPointSibling); 1770 return node; 1771 }; 1772 } 1773 } 1774 1775 if( 0 ){ 1776 req.log = function(){ 1777 try{ 1778 for(var i = 0; i < arguments.length; i++){ 1779 console.log(arguments[i]); 1780 } 1781 }catch(e){} 1782 }; 1783 }else{ 1784 req.log = noop; 1785 } 1786 1787 if( 0 ){ 1788 var trace = req.trace = function( 1789 group, // the trace group to which this application belongs 1790 args // the contents of the trace 1791 ){ 1792 /// 1793 // Tracing interface by group. 1794 // 1795 // Sends the contents of args to the console iff (req.trace.on && req.trace[group]) 1796 1797 if(trace.on && trace.group[group]){ 1798 signal("trace", [group, args]); 1799 for(var arg, dump = [], text= "trace:" + group + (args.length ? (":" + args[0]) : ""), i= 1; i<args.length;){ 1800 arg = args[i++]; 1801 if(isString(arg)){ 1802 text += ", " + arg; 1803 }else{ 1804 dump.push(arg); 1805 } 1806 } 1807 req.log(text); 1808 dump.length && dump.push("."); 1809 req.log.apply(req, dump); 1810 } 1811 }; 1812 mix(trace, { 1813 on:1, 1814 group:{}, 1815 set:function(group, value){ 1816 if(isString(group)){ 1817 trace.group[group]= value; 1818 }else{ 1819 mix(trace.group, group); 1820 } 1821 } 1822 }); 1823 trace.set(mix(mix(mix({}, defaultConfig.trace), userConfig.trace), dojoSniffConfig.trace)); 1824 on("config", function(config){ 1825 config.trace && trace.set(config.trace); 1826 }); 1827 }else{ 1828 req.trace = noop; 1829 } 1830 1831 var def = function( 1832 mid, //(commonjs.moduleId, optional) 1833 dependencies, //(array of commonjs.moduleId, optional) list of modules to be loaded before running factory 1834 factory //(any) 1835 ){ 1836 /// 1837 // Advises the loader of a module factory. //Implements http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition. 1838 /// 1839 //note 1840 // CommonJS factory scan courtesy of http://requirejs.org 1841 1842 var arity = arguments.length, 1843 defaultDeps = ["require", "exports", "module"], 1844 // the predominate signature... 1845 args = [0, mid, dependencies]; 1846 if(arity==1){ 1847 args = [0, (isFunction(mid) ? defaultDeps : []), mid]; 1848 }else if(arity==2 && isString(mid)){ 1849 args = [mid, (isFunction(dependencies) ? defaultDeps : []), dependencies]; 1850 }else if(arity==3){ 1851 args = [mid, dependencies, factory]; 1852 } 1853 1854 if( 0 && args[1]===defaultDeps){ 1855 args[2].toString() 1856 .replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg, "") 1857 .replace(/require\(["']([\w\!\-_\.\/]+)["']\)/g, function(match, dep){ 1858 args[1].push(dep); 1859 }); 1860 } 1861 1862 req.trace("loader-define", args.slice(0, 2)); 1863 var targetModule = args[0] && getModule(args[0]), 1864 module; 1865 if(targetModule && !waiting[targetModule.mid]){ 1866 // given a mid that hasn't been requested; therefore, defined through means other than injecting 1867 // consequent to a require() or define() application; examples include defining modules on-the-fly 1868 // due to some code path or including a module in a script element. In any case, 1869 // there is no callback waiting to finish processing and nothing to trigger the defQ and the 1870 // dependencies are never requested; therefore, do it here. 1871 injectDependencies(defineModule(targetModule, args[1], args[2])); 1872 }else if(!has("ie-event-behavior") || ! 1 || injectingCachedModule){ 1873 // not IE path: anonymous module and therefore must have been injected; therefore, onLoad will fire immediately 1874 // after script finishes being evaluated and the defQ can be run from that callback to detect the module id 1875 defQ.push(args); 1876 }else{ 1877 // IE path: possibly anonymous module and therefore injected; therefore, cannot depend on 1-to-1, 1878 // in-order exec of onLoad with script eval (since it's IE) and must manually detect here 1879 targetModule = targetModule || injectingModule; 1880 if(!targetModule){ 1881 for(mid in waiting){ 1882 module = modules[mid]; 1883 if(module && module.node && module.node.readyState === 'interactive'){ 1884 targetModule = module; 1885 break; 1886 } 1887 } 1888 if( 0 && !targetModule){ 1889 for(var i = 0; i<combosPending.length; i++){ 1890 targetModule = combosPending[i]; 1891 if(targetModule.node && targetModule.node.readyState === 'interactive'){ 1892 break; 1893 } 1894 targetModule= 0; 1895 } 1896 } 1897 } 1898 if( 0 && isArray(targetModule)){ 1899 injectDependencies(defineModule(getModule(targetModule.shift()), args[1], args[2])); 1900 if(!targetModule.length){ 1901 combosPending.splice(i, 1); 1902 } 1903 }else if(targetModule){ 1904 consumePendingCacheInsert(targetModule);
1905 injectDependencies(defineModule(targetModule, args[1], args[2])); 1906 }else{ 1907 signal(error, makeError("ieDefineFailed", args[0])); 1908 } 1909 checkComplete(); 1910 } 1911 }; 1912 def.amd = { 1913 vendor:"dojotoolkit.org" 1914 }; 1915 1916 if( 0 ){ 1917 req.def = def; 1918 } 1919 1920 // allow config to override default implementation of named functions; this is useful for 1921 // non-browser environments, e.g., overriding injectUrl, getText, log, etc. in node.js, Rhino, etc. 1922 // also useful for testing and monkey patching loader 1923 mix(mix(req, defaultConfig.loaderPatch), userConfig.loaderPatch); 1924 1925 // now that req is fully initialized and won't change, we can hook it up to the error signal 1926 on(error, function(arg){ 1927 try{ 1928 console.error(arg); 1929 if(arg instanceof Error){ 1930 for(var p in arg){ 1931 console.log(p + ":", arg[p]); 1932 } 1933 console.log("."); 1934 } 1935 }catch(e){} 1936 }); 1937 1938 // always publish these 1939 mix(req, { 1940 uid:uid, 1941 cache:cache, 1942 packs:packs 1943 }); 1944 1945 1946 if( 0 ){ 1947 mix(req, { 1948 // these may be interesting to look at when debugging 1949 paths:paths, 1950 aliases:aliases, 1951 modules:modules, 1952 legacyMode:legacyMode, 1953 execQ:execQ, 1954 defQ:defQ, 1955 waiting:waiting, 1956 1957 // these are used for testing 1958 // TODO: move testing infrastructure to a different has feature 1959 packs:packs, 1960 mapProgs:mapProgs, 1961 pathsMapProg:pathsMapProg, 1962 listenerQueues:listenerQueues, 1963 1964 // these are used by the builder (at least) 1965 computeMapProg:computeMapProg, 1966 computeAliases:computeAliases, 1967 runMapProg:runMapProg, 1968 compactPath:compactPath, 1969 getModuleInfo:getModuleInfo_ 1970 }); 1971 } 1972 1973 // the loader can be defined exactly once; look for global define which is the symbol AMD loaders are 1974 // *required* to define (as opposed to require, which is optional) 1975 if(global.define){ 1976 if( 0 ){ 1977 signal(error, makeError("defineAlreadyDefined", 0)); 1978 } 1979 return; 1980 }else{ 1981 global.define = def; 1982 global.require = req; 1983 if( 0 ){ 1984 require = req; 1985 } 1986 } 1987 1988 if( 0 && req.combo && req.combo.plugins){ 1989 var plugins = req.combo.plugins, 1990 pluginName; 1991 for(pluginName in plugins){ 1992 mix(mix(getModule(pluginName), plugins[pluginName]), {isCombo:1, executed:"executed", load:1}); 1993 } 1994 } 1995 1996 if( 1 ){ 1997 forEach(delayedModuleConfig, function(c){ config(c); }); 1998 var bootDeps = dojoSniffConfig.deps || userConfig.deps || defaultConfig.deps, 1999 bootCallback = dojoSniffConfig.callback || userConfig.callback || defaultConfig.callback; 2000 req.boot = (bootDeps || bootCallback) ? [bootDeps || [], bootCallback] : 0; 2001 } 2002 if(! 1 ){ 2003 !req.async && req(["dojo"]); 2004 req.boot && req.apply(null, req.boot); 2005 } 2006}) 2007(this.dojoConfig || this.djConfig || this.require || {}, { 2008 async:1, 2009 hasCache:{ 2010 'config-selectorEngine':"lite", 2011 'config-tlmSiblingOfDojo':1, 2012 'dojo-built':1, 2013 'dojo-loader':1, 2014 dom:1, 2015 'host-browser':1 2016 }, 2017 packages:[ 2018 { 2019 location:".", 2020 name:"dojo" 2021 }, 2022 { 2023 location:"../dijit", 2024 name:"dijit" 2025 }, 2026 { 2027 location:"../dojox", 2028 name:"dojox" 2029 }, 2030 { 2031 location:"../dpage", 2032 name:"dpage" 2033 }, 2034 { 2035 location:"../footable", 2036 name:"footable" 2037 }, 2038 { 2039 location:"../jquery", 2040 main:"jquery", 2041 name:"jquery" 2042 }, 2043 { 2044 location:"../jquery-ui", 2045 name:"jquery-ui" 2046 }, 2047 { 2048 location:"../jQueryPrivate", 2049 main:"jQueryPrivate", 2050 name:"jQueryPrivate" 2051 }, 2052 { 2053 location:"../xstyle", 2054 name:"xstyle" 2055 }, 2056 { 2057 location:"../put-selector", 2058 main:"put", 2059 name:"put-selector" 2060 } 2061 ] 2062});require({cache:{ 2063'dojo/main':function(){ 2064define([ 2065 "./_base/kernel", // kernel.isAsync 2066 "./has", 2067 "require", 2068 "./sniff", 2069 "./_base/lang", 2070 "./_base/array", 2071 "./_base/config", 2072 "./ready", 2073 "./_base/declare", 2074 "./_base/connect", 2075 "./_base/Deferred", 2076 "./_base/json", 2077 "./_base/Color", 2078 "require", 2079 "./_base/browser", 2080 "require" 2081], function(kernel, has, require, sniff, lang, array, config, ready){ 2082 // module: 2083 // dojo/main 2084 // summary: 2085 // This is the package main module for the dojo package; it loads dojo base appropriate for the execution environment. 2086
2087 // the preferred way to load the dojo firebug console is by setting 0 true in dojoConfig 2088 // the isDebug config switch is for backcompat and will work fine in sync loading mode; it works in 2089 // async mode too, but there's no guarantee when the module is loaded; therefore, if you need a firebug 2090 // console guaranteed at a particular spot in an app, either set config.has["dojo-firebug"] true before 2091 // loading dojo.js or explicitly include dojo/_firebug/firebug in a dependency list. 2092 if(config.isDebug){ 2093 require(["./_firebug/firebug"]); 2094 } 2095 2096 // dojoConfig.require is deprecated; use the loader configuration property deps 2097 0 && has.add("dojo-config-require", 1); 2098 if( 0 ){ 2099 var deps= config.require; 2100 if(deps){ 2101 // config.require may be dot notation 2102 deps= array.map(lang.isArray(deps) ? deps : [deps], function(item){ return item.replace(/\./g, "/"); }); 2103 if(kernel.isAsync){ 2104 require(deps); 2105 }else{ 2106 // this is a bit janky; in 1.6- dojo is defined before these requires are applied; but in 1.7+ 2107 // dojo isn't defined until returning from this module; this is only a problem in sync mode 2108 // since we're in sync mode, we know we've got our loader with its priority ready queue 2109 ready(1, function(){require(deps);}); 2110 } 2111 } 2112 } 2113 2114 return kernel; 2115}); 2116 2117}, 2118'dojo/_base/kernel':function(){ 2119define(["../has", "./config", "require", "module"], function(has, config, require, module){ 2120 // module: 2121 // dojo/_base/kernel 2122 2123 // This module is the foundational module of the dojo boot sequence; it defines the dojo object. 2124 2125 var 2126 // loop variables for this module 2127 i, p, 2128 2129 // create dojo, dijit, and dojox 2130 // FIXME: in 2.0 remove dijit, dojox being created by dojo 2131 global = (function () { return this; })(), 2132 dijit = {}, 2133 dojox = {}, 2134 dojo = { 2135 // summary: 2136 // This module is the foundational module of the dojo boot sequence; it defines the dojo object. 2137 2138 // notice dojo takes ownership of the value of the config module 2139 config:config, 2140 global:global, 2141 dijit:dijit, 2142 dojox:dojox 2143 }; 2144 2145 2146 // Configure the scope map. For a 100% AMD application, the scope map is not needed other than to provide 2147 // a _scopeName property for the dojo, dijit, and dojox root object so those packages can create 2148 // unique names in the global space. 2149 // 2150 // Built, legacy modules use the scope map to allow those modules to be expressed as if dojo, dijit, and dojox, 2151 // where global when in fact they are either global under different names or not global at all. In v1.6-, the 2152 // config variable "scopeMap" was used to map names as used within a module to global names. This has been 2153 // subsumed by the AMD map configuration variable which can relocate packages to different names. For backcompat, 2154 // only the "*" mapping is supported. See http://livedocs.dojotoolkit.org/developer/design/loader#legacy-cross-domain-mode for details. 2155 // 2156 // The following computations contort the packageMap for this dojo instance into a scopeMap. 2157 var scopeMap = 2158 // a map from a name used in a legacy module to the (global variable name, object addressed by that name) 2159 // always map dojo, dijit, and dojox 2160 { 2161 dojo:["dojo", dojo], 2162 dijit:["dijit", dijit], 2163 dojox:["dojox", dojox] 2164 }, 2165 2166 packageMap = 2167 // the package map for this dojo instance; note, a foreign loader or no pacakgeMap results in the above default config 2168 (require.map && require.map[module.id.match(/[^\/]+/)[0]]), 2169 2170 item; 2171 2172 2173 // process all mapped top-level names for this instance of dojo 2174 for(p in packageMap){ 2175 if(scopeMap[p]){ 2176 // mapped dojo, dijit, or dojox 2177 scopeMap[p][0] = packageMap[p]; 2178 }else{ 2179 // some other top-level name 2180 scopeMap[p] = [packageMap[p], {}]; 2181 } 2182 } 2183 2184 // publish those names to _scopeName and, optionally, the global namespace 2185 for(p in scopeMap){ 2186 item = scopeMap[p]; 2187 item[1]._scopeName = item[0]; 2188 if(!config.noGlobals){ 2189 global[item[0]] = item[1]; 2190 } 2191 } 2192 dojo.scopeMap = scopeMap; 2193 2194 /*===== dojo.__docParserConfigureScopeMap(scopeMap); =====*/ 2195 2196 // FIXME: dojo.baseUrl and dojo.config.baseUrl should be deprecated 2197 dojo.baseUrl = dojo.config.baseUrl = require.baseUrl; 2198 dojo.isAsync = ! 1 || require.async; 2199 dojo.locale = config.locale; 2200 2201 var rev = "$Rev: f4fef70 $".match(/[0-9a-f]{7,}/); 2202 dojo.version = { 2203 // summary: 2204 // Version number of the Dojo Toolkit 2205 // description: 2206 // Hash about the version, including 2207 // 2208 // - major: Integer: Major version. If total version is "1.2.0beta1", will be 1 2209 // - minor: Integer: Minor version. If total version is "1.2.0beta1", will be 2 2210 // - patch: Integer: Patch version. If total version is "1.2.0beta1", will be 0 2211 // - flag: String: Descriptor flag. If total version is "1.2.0beta1", will be "beta1" 2212 // - revision: Number: The Git rev from which dojo was pulled 2213 2214 major: 1, minor: 10, patch: 4, flag: "",
2215 revision: rev ? rev[0] : NaN, 2216 toString: function(){ 2217 var v = dojo.version; 2218 return v.major + "." + v.minor + "." + v.patch + v.flag + " (" + v.revision + ")"; // String 2219 } 2220 }; 2221 2222 // If 1 is truthy, then as a dojo module is defined it should push it's definitions 2223 // into the dojo object, and conversely. In 2.0, it will likely be unusual to augment another object 2224 // as a result of defining a module. This has feature gives a way to force 2.0 behavior as the code 2225 // is migrated. Absent specific advice otherwise, set extend-dojo to truthy. 2226 1 || has.add("extend-dojo", 1); 2227 2228 2229 (Function("d", "d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(dojo); 2230 /*===== 2231 dojo.eval = function(scriptText){ 2232 // summary: 2233 // A legacy method created for use exclusively by internal Dojo methods. Do not use this method 2234 // directly unless you understand its possibly-different implications on the platforms your are targeting. 2235 // description: 2236 // Makes an attempt to evaluate scriptText in the global scope. The function works correctly for browsers 2237 // that support indirect eval. 2238 // 2239 // As usual, IE does not. On IE, the only way to implement global eval is to 2240 // use execScript. Unfortunately, execScript does not return a value and breaks some current usages of dojo.eval. 2241 // This implementation uses the technique of executing eval in the scope of a function that is a single scope 2242 // frame below the global scope; thereby coming close to the global scope. Note carefully that 2243 // 2244 // dojo.eval("var pi = 3.14;"); 2245 // 2246 // will define global pi in non-IE environments, but define pi only in a temporary local scope for IE. If you want 2247 // to define a global variable using dojo.eval, write something like 2248 // 2249 // dojo.eval("window.pi = 3.14;") 2250 // scriptText: 2251 // The text to evaluation. 2252 // returns: 2253 // The result of the evaluation. Often `undefined` 2254 }; 2255 =====*/ 2256 2257 2258 if( 0 ){ 2259 dojo.exit = function(exitcode){ 2260 quit(exitcode); 2261 }; 2262 }else{ 2263 dojo.exit = function(){ 2264 }; 2265 } 2266 2267 1 || has.add("dojo-guarantee-console", 2268 // ensure that console.log, console.warn, etc. are defined 2269 1 2270 ); 2271 if( 1 ){ 2272 typeof console != "undefined" || (console = {}); 2273 // Be careful to leave 'log' always at the end 2274 var cn = [ 2275 "assert", "count", "debug", "dir", "dirxml", "error", "group", 2276 "groupEnd", "info", "profile", "profileEnd", "time", "timeEnd", 2277 "trace", "warn", "log" 2278 ]; 2279 var tn; 2280 i = 0; 2281 while((tn = cn[i++])){ 2282 if(!console[tn]){ 2283 (function(){ 2284 var tcn = tn + ""; 2285 console[tcn] = ('log' in console) ? function(){ 2286 var a = Array.prototype.slice.call(arguments); 2287 a.unshift(tcn + ":"); 2288 console["log"](a.join(" ")); 2289 } : function(){}; 2290 console[tcn]._fake = true; 2291 })(); 2292 } 2293 } 2294 } 2295 2296 0 && has.add("dojo-debug-messages", 2297 // include dojo.deprecated/dojo.experimental implementations 2298 !!config.isDebug 2299 ); 2300 dojo.deprecated = dojo.experimental = function(){}; 2301 if( 0 ){ 2302 dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){ 2303 // summary: 2304 // Log a debug message to indicate that a behavior has been 2305 // deprecated. 2306 // behaviour: String 2307 // The API or behavior being deprecated. Usually in the form 2308 // of "myApp.someFunction()". 2309 // extra: String? 2310 // Text to append to the message. Often provides advice on a 2311 // new function or facility to achieve the same goal during 2312 // the deprecation period. 2313 // removal: String? 2314 // Text to indicate when in the future the behavior will be 2315 // removed. Usually a version number. 2316 // example: 2317 // | dojo.deprecated("myApp.getTemp()", "use myApp.getLocaleTemp() instead", "1.0"); 2318 2319 var message = "DEPRECATED: " + behaviour; 2320 if(extra){ message += " " + extra; } 2321 if(removal){ message += " -- will be removed in version: " + removal; } 2322 console.warn(message); 2323 }; 2324 2325 dojo.experimental = function(/* String */ moduleName, /* String? */ extra){ 2326 // summary: 2327 // Marks code as experimental. 2328 // description: 2329 // This can be used to mark a function, file, or module as 2330 // experimental. Experimental code is not ready to be used, and the 2331 // APIs are subject to change without notice. Experimental code may be 2332 // completed deleted without going through the normal deprecation 2333 // process. 2334 // moduleName: String 2335 // The name of a module, or the name of a module file or a specific 2336 // function 2337 // extra: String? 2338 // some additional message for the user 2339 // example: 2340 // | dojo.experimental("dojo.data.Result"); 2341 // example: 2342 // | dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA"); 2343 2344 var message = "EXPERIMENTAL: " + moduleName + " -- APIs subject to change without notice."; 2345 if(extra){ message += " " + extra; } 2346 console.warn(message); 2347 }; 2348 } 2349 2350 0 && has.add("dojo-modulePaths", 2351 // consume dojo.modulePaths processing 2352 1 2353 ); 2354 if( 0 ){ 2355 // notice that modulePaths won't be applied to any require's before the dojo/_base/kernel factory is run; 2356 // this is the v1.6- behavior. 2357 if(config.modulePaths){ 2358 dojo.deprecated("dojo.modulePaths", "use paths configuration"); 2359 var paths = {}; 2360 for(p in config.modulePaths){ 2361 paths[p.replace(/\./g, "/")] = config.modulePaths[p]; 2362 } 2363 require({paths:paths}); 2364 } 2365 } 2366 2367 0 && has.add("dojo-moduleUrl", 2368 // include dojo.moduleUrl 2369 1 2370 ); 2371 if( 0 ){ 2372 dojo.moduleUrl = function(/*String*/module, /*String?*/url){ 2373 // summary: 2374 // Returns a URL relative to a module. 2375 // example: 2376 // | var pngPath = dojo.moduleUrl("acme","images/small.png"); 2377 // | console.dir(pngPath); // list the object properties 2378 // | // create an image and set it's source to pngPath's value: 2379 // | var img = document.createElement("img"); 2380 // | img.src = pngPath; 2381 // | // add our image to the document 2382 // | dojo.body().appendChild(img); 2383 // example: 2384 // you may de-reference as far as you like down the package 2385 // hierarchy. This is sometimes handy to avoid lengthy relative 2386 // urls or for building portable sub-packages. In this example, 2387 // the `acme.widget` and `acme.util` directories may be located 2388 // under different roots (see `dojo.registerModulePath`) but the 2389 // the modules which reference them can be unaware of their 2390 // relative locations on the filesystem: 2391 // | // somewhere in a configuration block 2392 // | dojo.registerModulePath("acme.widget", "../../acme/widget"); 2393 // | dojo.registerModulePath("acme.util", "../../util"); 2394 // | 2395 // | // ... 2396 // | 2397 // | // code in a module using acme resources 2398 // | var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html"); 2399 // | var dataPath = dojo.moduleUrl("acme.util","resources/data.json"); 2400 2401 dojo.deprecated("dojo.moduleUrl()", "use require.toUrl", "2.0"); 2402 2403 // require.toUrl requires a filetype; therefore, just append the suffix "/*.*" to guarantee a filetype, then 2404 // remove the suffix from the result. This way clients can request a url w/out a filetype. This should be 2405 // rare, but it maintains backcompat for the v1.x line (note: dojo.moduleUrl will be removed in v2.0).
2406 // Notice * is an illegal filename so it won't conflict with any real path map that may exist the paths config. 2407 var result = null; 2408 if(module){ 2409 result = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : "") + "/*.*").replace(/\/\*\.\*/, "") + (url ? "" : "/"); 2410 } 2411 return result; 2412 }; 2413 } 2414 2415 dojo._hasResource = {}; // for backward compatibility with layers built with 1.6 tooling 2416 2417 return dojo; 2418}); 2419 2420}, 2421'dojo/has':function(){ 2422define(["require", "module"], function(require, module){ 2423 // module: 2424 // dojo/has 2425 // summary: 2426 // Defines the has.js API and several feature tests used by dojo. 2427 // description: 2428 // This module defines the has API as described by the project has.js with the following additional features: 2429 // 2430 // - the has test cache is exposed at has.cache. 2431 // - the method has.add includes a forth parameter that controls whether or not existing tests are replaced 2432 // - the loader's has cache may be optionally copied into this module's has cahce. 2433 // 2434 // This module adopted from https://github.com/phiggins42/has.js; thanks has.js team! 2435 2436 // try to pull the has implementation from the loader; both the dojo loader and bdLoad provide one 2437 // if using a foreign loader, then the has cache may be initialized via the config object for this module 2438 // WARNING: if a foreign loader defines require.has to be something other than the has.js API, then this implementation fail 2439 var has = require.has || function(){}; 2440 if(! 1 ){ 2441 var 2442 isBrowser = 2443 // the most fundamental decision: are we in the browser? 2444 typeof window != "undefined" && 2445 typeof location != "undefined" && 2446 typeof document != "undefined" && 2447 window.location == location && window.document == document, 2448 2449 // has API variables 2450 global = (function () { return this; })(), 2451 doc = isBrowser && document, 2452 element = doc && doc.createElement("DiV"), 2453 cache = (module.config && module.config()) || {}; 2454 2455 has = function(name){ 2456 // summary: 2457 // Return the current value of the named feature. 2458 // 2459 // name: String|Integer 2460 // The name (if a string) or identifier (if an integer) of the feature to test. 2461 // 2462 // description: 2463 // Returns the value of the feature named by name. The feature must have been 2464 // previously added to the cache by has.add. 2465 2466 return typeof cache[name] == "function" ? (cache[name] = cache[name](global, doc, element)) : cache[name]; // Boolean 2467 }; 2468 2469 has.cache = cache; 2470 2471 has.add = function(name, test, now, force){ 2472 // summary: 2473 // Register a new feature test for some named feature. 2474 // name: String|Integer 2475 // The name (if a string) or identifier (if an integer) of the feature to test. 2476 // test: Function 2477 // A test function to register. If a function, queued for testing until actually 2478 // needed. The test function should return a boolean indicating 2479 // the presence of a feature or bug. 2480 // now: Boolean? 2481 // Optional. Omit if `test` is not a function. Provides a way to immediately 2482 // run the test and cache the result. 2483 // force: Boolean? 2484 // Optional. If the test already exists and force is truthy, then the existing 2485 // test will be replaced; otherwise, add does not replace an existing test (that 2486 // is, by default, the first test advice wins). 2487 // example: 2488 // A redundant test, testFn with immediate execution: 2489 // | has.add("javascript", function(){ return true; }, true); 2490 // 2491 // example: 2492 // Again with the redundantness. You can do this in your tests, but we should 2493 // not be doing this in any internal has.js tests 2494 // | has.add("javascript", true); 2495 // 2496 // example: 2497 // Three things are passed to the testFunction. `global`, `document`, and a generic element 2498 // from which to work your test should the need arise. 2499 // | has.add("bug-byid", function(g, d, el){ 2500 // | // g == global, typically window, yadda yadda 2501 // | // d == document object 2502 // | // el == the generic element. a `has` element. 2503 // | return false; // fake test, byid-when-form-has-name-matching-an-id is slightly longer 2504 // | }); 2505 2506 (typeof cache[name]=="undefined" || force) && (cache[name]= test); 2507 return now && has(name); 2508 }; 2509 2510 // since we're operating under a loader that doesn't provide a has API, we must explicitly initialize 2511 // has as it would have otherwise been initialized by the dojo loader; use has.add to the builder 2512 // can optimize these away iff desired 2513 1 || has.add("host-browser", isBrowser); 2514 0 && has.add("host-node", (typeof process == "object" && process.versions && process.versions.node && process.versions.v8)); 2515 0 && has.add("host-rhino", (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object"))); 2516 1 || has.add("dom", isBrowser); 2517 1 || has.add("dojo-dom-ready-api", 1); 2518 1 || has.add("dojo-sniff", 1); 2519 } 2520 2521 if( 1 ){ 2522 // Common application level tests 2523 has.add("dom-addeventlistener", !!document.addEventListener); 2524 2525 // Do the device and browser have touch capability? 2526 has.add("touch", "ontouchstart" in document 2527 || ("onpointerdown" in document && navigator.maxTouchPoints > 0) 2528 || window.navigator.msMaxTouchPoints); 2529 2530 // Touch events support 2531 has.add("touch-events", "ontouchstart" in document); 2532 2533 // Pointer Events support 2534 has.add("pointer-events", "onpointerdown" in document); 2535 has.add("MSPointer", "msMaxTouchPoints" in navigator); //IE10 (+IE11 preview) 2536 2537 // I don't know if any of these tests are really correct, just a rough guess
vendor: 4,863 bytes, lines 2538-2664
2538 has.add("device-width", screen.availWidth || innerWidth); 2539 2540 // Tests for DOMNode.attributes[] behavior: 2541 // - dom-attributes-explicit - attributes[] only lists explicitly user specified attributes 2542 // - dom-attributes-specified-flag (IE8) - need to check attr.specified flag to skip attributes user didn't specify 2543 // - Otherwise, in IE6-7. attributes[] will list hundreds of values, so need to do outerHTML to get attrs instead. 2544 var form = document.createElement("form"); 2545 has.add("dom-attributes-explicit", form.attributes.length == 0); // W3C 2546 has.add("dom-attributes-specified-flag", form.attributes.length > 0 && form.attributes.length < 40); // IE8 2547 } 2548 2549 has.clearElement = function(element){ 2550 // summary: 2551 // Deletes the contents of the element passed to test functions. 2552 element.innerHTML= ""; 2553 return element; 2554 }; 2555 2556 has.normalize = function(id, toAbsMid){ 2557 // summary: 2558 // Resolves id into a module id based on possibly-nested tenary expression that branches on has feature test value(s). 2559 // 2560 // toAbsMid: Function 2561 // Resolves a relative module id into an absolute module id 2562 var 2563 tokens = id.match(/[\?:]|[^:\?]*/g), i = 0, 2564 get = function(skip){ 2565 var term = tokens[i++]; 2566 if(term == ":"){ 2567 // empty string module name, resolves to 0 2568 return 0; 2569 }else{ 2570 // postfixed with a ? means it is a feature to branch on, the term is the name of the feature 2571 if(tokens[i++] == "?"){ 2572 if(!skip && has(term)){ 2573 // matched the feature, get the first value from the options 2574 return get(); 2575 }else{ 2576 // did not match, get the second value, passing over the first 2577 get(true); 2578 return get(skip); 2579 } 2580 } 2581 // a module 2582 return term || 0; 2583 } 2584 }; 2585 id = get(); 2586 return id && toAbsMid(id); 2587 }; 2588 2589 has.load = function(id, parentRequire, loaded){ 2590 // summary: 2591 // Conditional loading of AMD modules based on a has feature test value. 2592 // id: String 2593 // Gives the resolved module id to load. 2594 // parentRequire: Function 2595 // The loader require function with respect to the module that contained the plugin resource in it's 2596 // dependency list. 2597 // loaded: Function 2598 // Callback to loader that consumes result of plugin demand. 2599 2600 if(id){ 2601 parentRequire([id], loaded); 2602 }else{ 2603 loaded(); 2604 } 2605 }; 2606 2607 return has; 2608}); 2609 2610}, 2611'dojo/_base/config':function(){ 2612define(["../has", "require"], function(has, require){ 2613 // module: 2614 // dojo/_base/config 2615 2616/*===== 2617return { 2618 // summary: 2619 // This module defines the user configuration during bootstrap. 2620 // description: 2621 // By defining user configuration as a module value, an entire configuration can be specified in a build, 2622 // thereby eliminating the need for sniffing and or explicitly setting in the global variable dojoConfig. 2623 // Also, when multiple instances of dojo exist in a single application, each will necessarily be located 2624 // at an unique absolute module identifier as given by the package configuration. Implementing configuration 2625 // as a module allows for specifying unique, per-instance configurations. 2626 // example: 2627 // Create a second instance of dojo with a different, instance-unique configuration (assume the loader and 2628 // dojo.js are already loaded). 2629 // | // specify a configuration that creates a new instance of dojo at the absolute module identifier "myDojo" 2630 // | require({ 2631 // | packages:[{ 2632 // | name:"myDojo", 2633 // | location:".", //assume baseUrl points to dojo.js 2634 // | }] 2635 // | }); 2636 // | 2637 // | // specify a configuration for the myDojo instance 2638 // | define("myDojo/config", { 2639 // | // normal configuration variables go here, e.g., 2640 // | locale:"fr-ca" 2641 // | }); 2642 // | 2643 // | // load and use the new instance of dojo 2644 // | require(["myDojo"], function(dojo){ 2645 // | // dojo is the new instance of dojo 2646 // | // use as required 2647 // | }); 2648 2649 // isDebug: Boolean 2650 // Defaults to `false`. If set to `true`, ensures that Dojo provides 2651 // extended debugging feedback via Firebug. If Firebug is not available 2652 // on your platform, setting `isDebug` to `true` will force Dojo to 2653 // pull in (and display) the version of Firebug Lite which is 2654 // integrated into the Dojo distribution, thereby always providing a 2655 // debugging/logging console when `isDebug` is enabled. Note that 2656 // Firebug's `console.*` methods are ALWAYS defined by Dojo. If 2657 // `isDebug` is false and you are on a platform without Firebug, these 2658 // methods will be defined as no-ops. 2659 isDebug: false, 2660 2661 // locale: String 2662 // The locale to assume for loading localized resources in this page, 2663 // specified according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt). 2664 // Must be specified entirely in lowercase, e.g. `en-us` and `zh-cn`.
2665 // See the documentation for `dojo.i18n` and `dojo.requireLocalization` 2666 // for details on loading localized resources. If no locale is specified, 2667 // Dojo assumes the locale of the user agent, according to `navigator.userLanguage` 2668 // or `navigator.language` properties. 2669 locale: undefined, 2670 2671 // extraLocale: Array 2672 // No default value. Specifies additional locales whose 2673 // resources should also be loaded alongside the default locale when 2674 // calls to `dojo.requireLocalization()` are processed. 2675 extraLocale: undefined, 2676 2677 // baseUrl: String 2678 // The directory in which `dojo.js` is located. Under normal 2679 // conditions, Dojo auto-detects the correct location from which it 2680 // was loaded. You may need to manually configure `baseUrl` in cases 2681 // where you have renamed `dojo.js` or in which `<base>` tags confuse 2682 // some browsers (e.g. IE 6). The variable `dojo.baseUrl` is assigned 2683 // either the value of `djConfig.baseUrl` if one is provided or the 2684 // auto-detected root if not. Other modules are located relative to 2685 // this path. The path should end in a slash. 2686 baseUrl: undefined, 2687 2688 // modulePaths: [deprecated] Object 2689 // A map of module names to paths relative to `dojo.baseUrl`. The 2690 // key/value pairs correspond directly to the arguments which 2691 // `dojo.registerModulePath` accepts. Specifying 2692 // `djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent 2693 // of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple 2694 // modules may be configured via `djConfig.modulePaths`. 2695 modulePaths: {}, 2696 2697 // addOnLoad: Function|Array 2698 // Adds a callback via dojo/ready. Useful when Dojo is added after 2699 // the page loads and djConfig.afterOnLoad is true. Supports the same 2700 // arguments as dojo/ready. When using a function reference, use 2701 // `djConfig.addOnLoad = function(){};`. For object with function name use 2702 // `djConfig.addOnLoad = [myObject, "functionName"];` and for object with 2703 // function reference use 2704 // `djConfig.addOnLoad = [myObject, function(){}];` 2705 addOnLoad: null, 2706 2707 // parseOnLoad: Boolean 2708 // Run the parser after the page is loaded 2709 parseOnLoad: false, 2710 2711 // require: String[] 2712 // An array of module names to be loaded immediately after dojo.js has been included 2713 // in a page. 2714 require: [], 2715 2716 // defaultDuration: Number 2717 // Default duration, in milliseconds, for wipe and fade animations within dijits. 2718 // Assigned to dijit.defaultDuration. 2719 defaultDuration: 200, 2720 2721 // dojoBlankHtmlUrl: String 2722 // Used by some modules to configure an empty iframe. Used by dojo/io/iframe and 2723 // dojo/back, and dijit/popup support in IE where an iframe is needed to make sure native 2724 // controls do not bleed through the popups. Normally this configuration variable 2725 // does not need to be set, except when using cross-domain/CDN Dojo builds. 2726 // Save dojo/resources/blank.html to your domain and set `djConfig.dojoBlankHtmlUrl` 2727 // to the path on your domain your copy of blank.html. 2728 dojoBlankHtmlUrl: undefined, 2729 2730 // ioPublish: Boolean? 2731 // Set this to true to enable publishing of topics for the different phases of 2732 // IO operations. Publishing is done via dojo/topic.publish(). See dojo/main.__IoPublish for a list 2733 // of topics that are published. 2734 ioPublish: false, 2735 2736 // useCustomLogger: Anything? 2737 // If set to a value that evaluates to true such as a string or array and 2738 // isDebug is true and Firebug is not available or running, then it bypasses 2739 // the creation of Firebug Lite allowing you to define your own console object. 2740 useCustomLogger: undefined, 2741 2742 // transparentColor: Array 2743 // Array containing the r, g, b components used as transparent color in dojo.Color; 2744 // if undefined, [255,255,255] (white) will be used. 2745 transparentColor: undefined, 2746 2747 // deps: Function|Array 2748 // Defines dependencies to be used before the loader has been loaded. 2749 // When provided, they cause the loader to execute require(deps, callback) 2750 // once it has finished loading. Should be used with callback. 2751 deps: undefined, 2752 2753 // callback: Function|Array
2754 // Defines a callback to be used when dependencies are defined before 2755 // the loader has been loaded. When provided, they cause the loader to 2756 // execute require(deps, callback) once it has finished loading. 2757 // Should be used with deps. 2758 callback: undefined, 2759 2760 // deferredInstrumentation: Boolean 2761 // Whether deferred instrumentation should be loaded or included 2762 // in builds. 2763 deferredInstrumentation: true, 2764 2765 // useDeferredInstrumentation: Boolean|String 2766 // Whether the deferred instrumentation should be used. 2767 // 2768 // * `"report-rejections"`: report each rejection as it occurs. 2769 // * `true` or `1` or `"report-unhandled-rejections"`: wait 1 second 2770 // in an attempt to detect unhandled rejections. 2771 useDeferredInstrumentation: "report-unhandled-rejections" 2772}; 2773=====*/ 2774 2775 var result = {}; 2776 if( 1 ){ 2777 // must be the dojo loader; take a shallow copy of require.rawConfig 2778 var src = require.rawConfig, p; 2779 for(p in src){ 2780 result[p] = src[p]; 2781 } 2782 }else{ 2783 var adviseHas = function(featureSet, prefix, booting){ 2784 for(p in featureSet){ 2785 p!="has" && has.add(prefix + p, featureSet[p], 0, booting); 2786 } 2787 }; 2788 var global = (function () { return this; })(); 2789 result = 1 ? 2790 // must be a built version of the dojo loader; all config stuffed in require.rawConfig 2791 require.rawConfig : 2792 // a foreign loader 2793 global.dojoConfig || global.djConfig || {}; 2794 adviseHas(result, "config", 1); 2795 adviseHas(result.has, "", 1); 2796 } 2797 2798 if(!result.locale && typeof navigator != "undefined"){ 2799 // Default locale for browsers. 2800 var language = (navigator.language || navigator.userLanguage); 2801 if(language){ 2802 result.locale = language.toLowerCase(); 2803 } 2804 } 2805 2806 return result; 2807}); 2808 2809 2810}, 2811'dojo/sniff':function(){ 2812define(["./has"], function(has){ 2813 // module: 2814 // dojo/sniff 2815 2816 /*===== 2817 return function(){ 2818 // summary: 2819 // This module sets has() flags based on the current browser. 2820 // It returns the has() function. 2821 }; 2822 =====*/ 2823 2824 if( 1 ){ 2825 var n = navigator, 2826 dua = n.userAgent, 2827 dav = n.appVersion, 2828 tv = parseFloat(dav); 2829 2830 has.add("air", dua.indexOf("AdobeAIR") >= 0); 2831 has.add("msapp", parseFloat(dua.split("MSAppHost/")[1]) || undefined); 2832 has.add("khtml", dav.indexOf("Konqueror") >= 0 ? tv : undefined); 2833 has.add("webkit", parseFloat(dua.split("WebKit/")[1]) || undefined); 2834 has.add("chrome", parseFloat(dua.split("Chrome/")[1]) || undefined); 2835 has.add("safari", dav.indexOf("Safari")>=0 && !has("chrome") ? parseFloat(dav.split("Version/")[1]) : undefined); 2836 has.add("mac", dav.indexOf("Macintosh") >= 0); 2837 has.add("quirks", document.compatMode == "BackCompat"); 2838 if(dua.match(/(iPhone|iPod|iPad)/)){ 2839 var p = RegExp.$1.replace(/P/, "p"); 2840 var v = dua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1"; 2841 var os = parseFloat(v.replace(/_/, ".").replace(/_/g, "")); 2842 has.add(p, os); // "iphone", "ipad" or "ipod" 2843 has.add("ios", os); 2844 } 2845 has.add("android", parseFloat(dua.split("Android ")[1]) || undefined); 2846 has.add("bb", (dua.indexOf("BlackBerry") >= 0 || dua.indexOf("BB10") >= 0) && parseFloat(dua.split("Version/")[1]) || undefined); 2847 has.add("trident", parseFloat(dav.split("Trident/")[1]) || undefined); 2848 2849 has.add("svg", typeof SVGAngle !== "undefined"); 2850 2851 if(!has("webkit")){ 2852 // Opera 2853 if(dua.indexOf("Opera") >= 0){ 2854 // see http://dev.opera.com/articles/view/opera-ua-string-changes and http://www.useragentstring.com/pages/Opera/ 2855 // 9.8 has both styles; <9.8, 9.9 only old style 2856 has.add("opera", tv >= 9.8 ? parseFloat(dua.split("Version/")[1]) || tv : tv); 2857 } 2858 2859 // Mozilla and firefox 2860 if(dua.indexOf("Gecko") >= 0 && !has("khtml") && !has("webkit") && !has("trident")){ 2861 has.add("mozilla", tv); 2862 } 2863 if(has("mozilla")){ 2864 //We really need to get away from this. Consider a sane isGecko approach for the future. 2865 has.add("ff", parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined); 2866 } 2867 2868 // IE 2869 if(document.all && !has("opera")){ 2870 var isIE = parseFloat(dav.split("MSIE ")[1]) || undefined; 2871 2872 //In cases where the page has an HTTP header or META tag with 2873 //X-UA-Compatible, then it is in emulation mode. 2874 //Make sure isIE reflects the desired version. 2875 //document.documentMode of 5 means quirks mode.
2876 //Only switch the value if documentMode's major version 2877 //is different from isIE's major version. 2878 var mode = document.documentMode; 2879 if(mode && mode != 5 && Math.floor(isIE) != mode){ 2880 isIE = mode; 2881 } 2882 2883 has.add("ie", isIE); 2884 } 2885 2886 // Wii 2887 has.add("wii", typeof opera != "undefined" && opera.wiiremote); 2888 } 2889 } 2890 2891 return has; 2892}); 2893 2894}, 2895'dojo/_base/lang':function(){ 2896define(["./kernel", "../has", "../sniff"], function(dojo, has){ 2897 // module: 2898 // dojo/_base/lang 2899 2900 has.add("bug-for-in-skips-shadowed", function(){ 2901 // if true, the for-in iterator skips object properties that exist in Object's prototype (IE 6 - ?) 2902 for(var i in {toString: 1}){ 2903 return 0; 2904 } 2905 return 1; 2906 }); 2907 2908 // Helper methods 2909 var _extraNames = 2910 has("bug-for-in-skips-shadowed") ? 2911 "hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split(".") : [], 2912 2913 _extraLen = _extraNames.length, 2914 2915 getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){ 2916 if(!context){ 2917 if(parts[0] && dojo.scopeMap[parts[0]]) { 2918 // Voodoo code from the old days where "dojo" or "dijit" maps to some special object 2919 // rather than just window.dojo 2920 context = dojo.scopeMap[parts.shift()][1]; 2921 }else{ 2922 context = dojo.global; 2923 } 2924 } 2925 2926 try{ 2927 for(var i = 0; i < parts.length; i++){ 2928 var p = parts[i]; 2929 if(!(p in context)){ 2930 if(create){ 2931 context[p] = {}; 2932 }else{ 2933 return; // return undefined 2934 } 2935 } 2936 context = context[p]; 2937 } 2938 return context; // mixed 2939 }catch(e){ 2940 // "p in context" throws an exception when context is a number, boolean, etc. rather than an object, 2941 // so in that corner case just return undefined (by having no return statement) 2942 } 2943 }, 2944 2945 opts = Object.prototype.toString, 2946 2947 efficient = function(obj, offset, startWith){ 2948 return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0)); 2949 }, 2950 2951 _pattern = /\{([^\}]+)\}/g; 2952 2953 // Module export 2954 var lang = { 2955 // summary: 2956 // This module defines Javascript language extensions. 2957 2958 // _extraNames: String[] 2959 // Lists property names that must be explicitly processed during for-in iteration 2960 // in environments that have has("bug-for-in-skips-shadowed") true. 2961 _extraNames:_extraNames, 2962 2963 _mixin: function(dest, source, copyFunc){ 2964 // summary: 2965 // Copies/adds all properties of source to dest; returns dest. 2966 // dest: Object 2967 // The object to which to copy/add all properties contained in source. 2968 // source: Object 2969 // The object from which to draw all properties to copy into dest. 2970 // copyFunc: Function? 2971 // The process used to copy/add a property in source; defaults to the Javascript assignment operator. 2972 // returns: 2973 // dest, as modified 2974 // description: 2975 // All properties, including functions (sometimes termed "methods"), excluding any non-standard extensions 2976 // found in Object.prototype, are copied/added to dest. Copying/adding each particular property is 2977 // delegated to copyFunc (if any); copyFunc defaults to the Javascript assignment operator if not provided. 2978 // Notice that by default, _mixin executes a so-called "shallow copy" and aggregate types are copied/added by reference. 2979 var name, s, i, empty = {}; 2980 for(name in source){ 2981 // the (!(name in empty) || empty[name] !== s) condition avoids copying properties in "source" 2982 // inherited from Object.prototype. For example, if dest has a custom toString() method, 2983 // don't overwrite it with the toString() method that source inherited from Object.prototype 2984 s = source[name]; 2985 if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){ 2986 dest[name] = copyFunc ? copyFunc(s) : s; 2987 } 2988 } 2989 2990 if(has("bug-for-in-skips-shadowed")){ 2991 if(source){ 2992 for(i = 0; i < _extraLen; ++i){ 2993 name = _extraNames[i]; 2994 s = source[name]; 2995 if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){ 2996 dest[name] = copyFunc ? copyFunc(s) : s; 2997 } 2998 } 2999 } 3000 } 3001 3002 return dest; // Object 3003 }, 3004 3005 mixin: function(dest, sources){ 3006 // summary: 3007 // Copies/adds all properties of one or more sources to dest; returns dest. 3008 // dest: Object 3009 // The object to which to copy/add all properties contained in source. If dest is falsy, then 3010 // a new object is manufactured before copying/adding properties begins. 3011 // sources: Object... 3012 // One of more objects from which to draw all properties to copy into dest. sources are processed 3013 // left-to-right and if more than one of these objects contain the same property name, the right-most 3014 // value "wins". 3015 // returns: Object 3016 // dest, as modified 3017 // description: 3018 // All properties, including functions (sometimes termed "methods"), excluding any non-standard extensions 3019 // found in Object.prototype, are copied/added from sources to dest. sources are processed left to right. 3020 // The Javascript assignment operator is used to copy/add each property; therefore, by default, mixin 3021 // executes a so-called "shallow copy" and aggregate types are copied/added by reference. 3022 // example: 3023 // make a shallow copy of an object 3024 // | var copy = lang.mixin({}, source); 3025 // example: 3026 // many class constructors often take an object which specifies 3027 // values to be configured on the object. In this case, it is 3028 // often simplest to call `lang.mixin` on the `this` object: 3029 // | declare("acme.Base", null, { 3030 // | constructor: function(properties){ 3031 // | // property configuration: 3032 // | lang.mixin(this, properties); 3033 // | 3034 // | console.log(this.quip); 3035 // | // ... 3036 // | }, 3037 // | quip: "I wasn't born yesterday, you know - I've seen movies.", 3038 // | // ... 3039 // | }); 3040 // | 3041 // | // create an instance of the class and configure it 3042 // | var b = new acme.Base({quip: "That's what it does!" }); 3043 // example: 3044 // copy in properties from multiple objects 3045 // | var flattened = lang.mixin( 3046 // | { 3047 // | name: "Frylock", 3048 // | braces: true 3049 // | }, 3050 // | { 3051 // | name: "Carl Brutanananadilewski" 3052 // | } 3053 // | ); 3054 // | 3055 // | // will print "Carl Brutanananadilewski" 3056 // | console.log(flattened.name); 3057 // | // will print "true" 3058 // | console.log(flattened.braces); 3059 3060 if(!dest){ dest = {}; } 3061 for(var i = 1, l = arguments.length; i < l; i++){ 3062 lang._mixin(dest, arguments[i]); 3063 } 3064 return dest; // Object 3065 }, 3066 3067 setObject: function(name, value, context){ 3068 // summary: 3069 // Set a property from a dot-separated string, such as "A.B.C" 3070 // description: 3071 // Useful for longer api chains where you have to test each object in 3072 // the chain, or when you have an object reference in string format. 3073 // Objects are created as needed along `path`. Returns the passed 3074 // value if setting is successful or `undefined` if not. 3075 // name: String 3076 // Path to a property, in the form "A.B.C". 3077 // value: anything 3078 // value or object to place at location given by name 3079 // context: Object? 3080 // Optional. Object to use as root of path. Defaults to 3081 // `dojo.global`. 3082 // example: 3083 // set the value of `foo.bar.baz`, regardless of whether 3084 // intermediate objects already exist: 3085 // | lang.setObject("foo.bar.baz", value); 3086 // example: 3087 // without `lang.setObject`, we often see code like this: 3088 // | // ensure that intermediate objects are available 3089 // | if(!obj["parent"]){ obj.parent = {}; } 3090 // | if(!obj.parent["child"]){ obj.parent.child = {}; } 3091 // | // now we can safely set the property 3092 // | obj.parent.child.prop = "some value"; 3093 // whereas with `lang.setObject`, we can shorten that to: 3094 // | lang.setObject("parent.child.prop", "some value", obj); 3095 3096 var parts = name.split("."), p = parts.pop(), obj = getProp(parts, true, context); 3097 return obj && p ? (obj[p] = value) : undefined; // Object 3098 }, 3099 3100 getObject: function(name, create, context){ 3101 // summary: 3102 // Get a property from a dot-separated string, such as "A.B.C" 3103 // description: 3104 // Useful for longer api chains where you have to test each object in 3105 // the chain, or when you have an object reference in string format. 3106 // name: String 3107 // Path to an property, in the form "A.B.C". 3108 // create: Boolean? 3109 // Optional. Defaults to `false`. If `true`, Objects will be 3110 // created at any point along the 'path' that is undefined. 3111 // context: Object? 3112 // Optional. Object to use as root of path. Defaults to 3113 // 'dojo.global'. Null may be passed. 3114 return getProp(name ? name.split(".") : [], create, context); // Object 3115 }, 3116 3117 exists: function(name, obj){ 3118 // summary: 3119 // determine if an object supports a given method 3120 // description: 3121 // useful for longer api chains where you have to test each object in 3122 // the chain. Useful for object and method detection. 3123 // name: String 3124 // Path to an object, in the form "A.B.C". 3125 // obj: Object? 3126 // Object to use as root of path. Defaults to 3127 // 'dojo.global'. Null may be passed. 3128 // example: 3129 // | // define an object 3130 // | var foo = { 3131 // | bar: { } 3132 // | }; 3133 // | 3134 // | // search the global scope 3135 // | lang.exists("foo.bar"); // true 3136 // | lang.exists("foo.bar.baz"); // false 3137 // | 3138 // | // search from a particular scope 3139 // | lang.exists("bar", foo); // true 3140 // | lang.exists("bar.baz", foo); // false 3141 return lang.getObject(name, false, obj) !== undefined; // Boolean 3142 }, 3143 3144 // Crockford (ish) functions 3145 3146 isString: function(it){ 3147 // summary: 3148 // Return true if it is a String 3149 // it: anything 3150 // Item to test. 3151 return (typeof it == "string" || it instanceof String); // Boolean 3152 }, 3153 3154 isArray: function(it){ 3155 // summary: 3156 // Return true if it is an Array. 3157 // Does not work on Arrays created in other windows. 3158 // it: anything 3159 // Item to test. 3160 return it && (it instanceof Array || typeof it == "array"); // Boolean 3161 }, 3162 3163 isFunction: function(it){ 3164 // summary: 3165 // Return true if it is a Function 3166 // it: anything 3167 // Item to test. 3168 return opts.call(it) === "[object Function]"; 3169 }, 3170 3171 isObject: function(it){ 3172 // summary: 3173 // Returns true if it is a JavaScript object (or an Array, a Function 3174 // or null) 3175 // it: anything 3176 // Item to test. 3177 return it !== undefined && 3178 (it === null || typeof it == "object" || lang.isArray(it) || lang.isFunction(it)); // Boolean 3179 }, 3180 3181 isArrayLike: function(it){ 3182 // summary: 3183 // similar to isArray() but more permissive 3184 // it: anything 3185 // Item to test. 3186 // returns: 3187 // If it walks like a duck and quacks like a duck, return `true` 3188 // description: 3189 // Doesn't strongly test for "arrayness". Instead, settles for "isn't 3190 // a string or number and has a length property". Arguments objects 3191 // and DOM collections will return true when passed to 3192 // isArrayLike(), but will return false when passed to 3193 // isArray(). 3194 return it && it !== undefined && // Boolean 3195 // keep out built-in constructors (Number, String, ...) which have length 3196 // properties 3197 !lang.isString(it) && !lang.isFunction(it) && 3198 !(it.tagName && it.tagName.toLowerCase() == 'form') && 3199 (lang.isArray(it) || isFinite(it.length)); 3200 }, 3201 3202 isAlien: function(it){ 3203 // summary: 3204 // Returns true if it is a built-in function or some other kind of 3205 // oddball that *should* report as a function but doesn't 3206 return it && !lang.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean 3207 }, 3208 3209 extend: function(ctor, props){ 3210 // summary: 3211 // Adds all properties and methods of props to constructor's 3212 // prototype, making them available to all instances created with 3213 // constructor. 3214 // ctor: Object 3215 // Target constructor to extend. 3216 // props: Object 3217 // One or more objects to mix into ctor.prototype 3218 for(var i=1, l=arguments.length; i<l; i++){ 3219 lang._mixin(ctor.prototype, arguments[i]); 3220 } 3221 return ctor; // Object 3222 }, 3223 3224 _hitchArgs: function(scope, method){ 3225 var pre = lang._toArray(arguments, 2); 3226 var named = lang.isString(method); 3227 return function(){ 3228 // arrayify arguments 3229 var args = lang._toArray(arguments); 3230 // locate our method 3231 var f = named ? (scope||dojo.global)[method] : method; 3232 // invoke with collected args 3233 return f && f.apply(scope || this, pre.concat(args)); // mixed 3234 }; // Function 3235 }, 3236 3237 hitch: function(scope, method){ 3238 // summary: 3239 // Returns a function that will only ever execute in the given scope. 3240 // This allows for easy use of object member functions 3241 // in callbacks and other places in which the "this" keyword may 3242 // otherwise not reference the expected scope. 3243 // Any number of default positional arguments may be passed as parameters 3244 // beyond "method". 3245 // Each of these values will be used to "placehold" (similar to curry) 3246 // for the hitched function. 3247 // scope: Object 3248 // The scope to use when method executes. If method is a string,
3249 // scope is also the object containing method. 3250 // method: Function|String... 3251 // A function to be hitched to scope, or the name of the method in 3252 // scope to be hitched. 3253 // example: 3254 // | lang.hitch(foo, "bar")(); 3255 // runs foo.bar() in the scope of foo 3256 // example: 3257 // | lang.hitch(foo, myFunction); 3258 // returns a function that runs myFunction in the scope of foo 3259 // example: 3260 // Expansion on the default positional arguments passed along from 3261 // hitch. Passed args are mixed first, additional args after. 3262 // | var foo = { bar: function(a, b, c){ console.log(a, b, c); } }; 3263 // | var fn = lang.hitch(foo, "bar", 1, 2); 3264 // | fn(3); // logs "1, 2, 3" 3265 // example: 3266 // | var foo = { bar: 2 }; 3267 // | lang.hitch(foo, function(){ this.bar = 10; })(); 3268 // execute an anonymous function in scope of foo 3269 if(arguments.length > 2){ 3270 return lang._hitchArgs.apply(dojo, arguments); // Function 3271 } 3272 if(!method){ 3273 method = scope; 3274 scope = null; 3275 } 3276 if(lang.isString(method)){ 3277 scope = scope || dojo.global; 3278 if(!scope[method]){ throw(['lang.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); } 3279 return function(){ return scope[method].apply(scope, arguments || []); }; // Function 3280 } 3281 return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function 3282 }, 3283 3284 delegate: (function(){ 3285 // boodman/crockford delegation w/ cornford optimization 3286 function TMP(){} 3287 return function(obj, props){ 3288 TMP.prototype = obj; 3289 var tmp = new TMP(); 3290 TMP.prototype = null; 3291 if(props){ 3292 lang._mixin(tmp, props); 3293 } 3294 return tmp; // Object 3295 }; 3296 })(), 3297 /*===== 3298 delegate: function(obj, props){ 3299 // summary: 3300 // Returns a new object which "looks" to obj for properties which it 3301 // does not have a value for. Optionally takes a bag of properties to 3302 // seed the returned object with initially. 3303 // description: 3304 // This is a small implementation of the Boodman/Crockford delegation 3305 // pattern in JavaScript. An intermediate object constructor mediates 3306 // the prototype chain for the returned object, using it to delegate 3307 // down to obj for property lookup when object-local lookup fails. 3308 // This can be thought of similarly to ES4's "wrap", save that it does 3309 // not act on types but rather on pure objects. 3310 // obj: Object 3311 // The object to delegate to for properties not found directly on the 3312 // return object or in props. 3313 // props: Object... 3314 // an object containing properties to assign to the returned object 3315 // returns: 3316 // an Object of anonymous type 3317 // example: 3318 // | var foo = { bar: "baz" }; 3319 // | var thinger = lang.delegate(foo, { thud: "xyzzy"}); 3320 // | thinger.bar == "baz"; // delegated to foo 3321 // | foo.thud == undefined; // by definition 3322 // | thinger.thud == "xyzzy"; // mixed in from props 3323 // | foo.bar = "thonk"; 3324 // | thinger.bar == "thonk"; // still delegated to foo's bar 3325 }, 3326 =====*/ 3327 3328 _toArray: has("ie") ? 3329 (function(){ 3330 function slow(obj, offset, startWith){ 3331 var arr = startWith||[]; 3332 for(var x = offset || 0; x < obj.length; x++){ 3333 arr.push(obj[x]); 3334 } 3335 return arr; 3336 } 3337 return function(obj){ 3338 return ((obj.item) ? slow : efficient).apply(this, arguments); 3339 }; 3340 })() : efficient, 3341 /*===== 3342 _toArray: function(obj, offset, startWith){ 3343 // summary: 3344 // Converts an array-like object (i.e. arguments, DOMCollection) to an 3345 // array. Returns a new Array with the elements of obj. 3346 // obj: Object 3347 // the object to "arrayify". We expect the object to have, at a 3348 // minimum, a length property which corresponds to integer-indexed 3349 // properties. 3350 // offset: Number? 3351 // the location in obj to start iterating from. Defaults to 0. 3352 // Optional. 3353 // startWith: Array? 3354 // An array to pack with the properties of obj. If provided, 3355 // properties in obj are appended at the end of startWith and 3356 // startWith is the returned array. 3357 }, 3358 =====*/ 3359 3360 partial: function(/*Function|String*/ method /*, ...*/){ 3361 // summary: 3362 // similar to hitch() except that the scope object is left to be 3363 // whatever the execution context eventually becomes. 3364 // description: 3365 // Calling lang.partial is the functional equivalent of calling: 3366 // | lang.hitch(null, funcName, ...); 3367 // method: 3368 // The function to "wrap" 3369 var arr = [ null ]; 3370 return lang.hitch.apply(dojo, arr.concat(lang._toArray(arguments))); // Function 3371 }, 3372 3373 clone: function(/*anything*/ src){ 3374 // summary: 3375 // Clones objects (including DOM nodes) and all children. 3376 // Warning: do not clone cyclic structures. 3377 // src: 3378 // The object to clone 3379 if(!src || typeof src != "object" || lang.isFunction(src)){ 3380 // null, undefined, any non-object, or function 3381 return src; // anything 3382 } 3383 if(src.nodeType && "cloneNode" in src){ 3384 // DOM Node 3385 return src.cloneNode(true); // Node 3386 } 3387 if(src instanceof Date){ 3388 // Date 3389 return new Date(src.getTime()); // Date 3390 } 3391 if(src instanceof RegExp){ 3392 // RegExp 3393 return new RegExp(src); // RegExp 3394 } 3395 var r, i, l; 3396 if(lang.isArray(src)){ 3397 // array 3398 r = []; 3399 for(i = 0, l = src.length; i < l; ++i){ 3400 if(i in src){ 3401 r.push(lang.clone(src[i])); 3402 } 3403 } 3404 // we don't clone functions for performance reasons 3405 // }else if(d.isFunction(src)){ 3406 // // function 3407 // r = function(){ return src.apply(this, arguments); }; 3408 }else{ 3409 // generic objects 3410 r = src.constructor ? new src.constructor() : {}; 3411 } 3412 return lang._mixin(r, src, lang.clone); 3413 }, 3414 3415 3416 trim: String.prototype.trim ? 3417 function(str){ return str.trim(); } : 3418 function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); }, 3419 /*===== 3420 trim: function(str){ 3421 // summary:
3422 // Trims whitespace from both sides of the string 3423 // str: String 3424 // String to be trimmed 3425 // returns: String 3426 // Returns the trimmed string 3427 // description: 3428 // This version of trim() was selected for inclusion into the base due 3429 // to its compact size and relatively good performance 3430 // (see [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript) 3431 // Uses String.prototype.trim instead, if available. 3432 // The fastest but longest version of this function is located at 3433 // lang.string.trim() 3434 }, 3435 =====*/ 3436 3437 replace: function(tmpl, map, pattern){ 3438 // summary: 3439 // Performs parameterized substitutions on a string. Throws an 3440 // exception if any parameter is unmatched. 3441 // tmpl: String 3442 // String to be used as a template. 3443 // map: Object|Function 3444 // If an object, it is used as a dictionary to look up substitutions. 3445 // If a function, it is called for every substitution with following parameters: 3446 // a whole match, a name, an offset, and the whole template 3447 // string (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace 3448 // for more details). 3449 // pattern: RegEx? 3450 // Optional regular expression objects that overrides the default pattern. 3451 // Must be global and match one item. The default is: /\{([^\}]+)\}/g, 3452 // which matches patterns like that: "{xxx}", where "xxx" is any sequence 3453 // of characters, which doesn't include "}". 3454 // returns: String 3455 // Returns the substituted string. 3456 // example: 3457 // | // uses a dictionary for substitutions: 3458 // | lang.replace("Hello, {name.first} {name.last} AKA {nick}!", 3459 // | { 3460 // | nick: "Bob", 3461 // | name: { 3462 // | first: "Robert", 3463 // | middle: "X", 3464 // | last: "Cringely" 3465 // | } 3466 // | }); 3467 // | // returns: Hello, Robert Cringely AKA Bob! 3468 // example: 3469 // | // uses an array for substitutions: 3470 // | lang.replace("Hello, {0} {2}!", 3471 // | ["Robert", "X", "Cringely"]); 3472 // | // returns: Hello, Robert Cringely! 3473 // example: 3474 // | // uses a function for substitutions: 3475 // | function sum(a){ 3476 // | var t = 0; 3477 // | arrayforEach(a, function(x){ t += x; }); 3478 // | return t; 3479 // | } 3480 // | lang.replace( 3481 // | "{count} payments averaging {avg} USD per payment.", 3482 // | lang.hitch( 3483 // | { payments: [11, 16, 12] }, 3484 // | function(_, key){ 3485 // | switch(key){ 3486 // | case "count": return this.payments.length; 3487 // | case "min": return Math.min.apply(Math, this.payments); 3488 // | case "max": return Math.max.apply(Math, this.payments); 3489 // | case "sum": return sum(this.payments); 3490 // | case "avg": return sum(this.payments) / this.payments.length; 3491 // | } 3492 // | } 3493 // | ) 3494 // | ); 3495 // | // prints: 3 payments averaging 13 USD per payment. 3496 // example: 3497 // | // uses an alternative PHP-like pattern for substitutions: 3498 // | lang.replace("Hello, ${0} ${2}!", 3499 // | ["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g); 3500 // | // returns: Hello, Robert Cringely! 3501 3502 return tmpl.replace(pattern || _pattern, lang.isFunction(map) ? 3503 map : function(_, k){ return lang.getObject(k, false, map); }); 3504 } 3505 }; 3506 3507 1 && lang.mixin(dojo, lang); 3508 3509 return lang; 3510}); 3511 3512 3513}, 3514'dojo/_base/array':function(){ 3515define(["./kernel", "../has", "./lang"], function(dojo, has, lang){ 3516 // module: 3517 // dojo/_base/array 3518 3519 // our old simple function builder stuff 3520 var cache = {}, u; 3521 3522 function buildFn(fn){ 3523 return cache[fn] = new Function("item", "index", "array", fn); // Function 3524 } 3525 // magic snippet: if(typeof fn == "string") fn = cache[fn] || buildFn(fn); 3526 3527 // every & some 3528 3529 function everyOrSome(some){ 3530 var every = !some; 3531 return function(a, fn, o){ 3532 var i = 0, l = a && a.length || 0, result; 3533 if(l && typeof a == "string") a = a.split(""); 3534 if(typeof fn == "string") fn = cache[fn] || buildFn(fn); 3535 if(o){ 3536 for(; i < l; ++i){ 3537 result = !fn.call(o, a[i], i, a); 3538 if(some ^ result){ 3539 return !result; 3540 } 3541 } 3542 }else{ 3543 for(; i < l; ++i){ 3544 result = !fn(a[i], i, a); 3545 if(some ^ result){ 3546 return !result; 3547 } 3548 } 3549 } 3550 return every; // Boolean 3551 }; 3552 } 3553 3554 // indexOf, lastIndexOf 3555 3556 function index(up){ 3557 var delta = 1, lOver = 0, uOver = 0; 3558 if(!up){ 3559 delta = lOver = uOver = -1; 3560 } 3561 return function(a, x, from, last){ 3562 if(last && delta > 0){ 3563 // TODO: why do we use a non-standard signature? why do we need "last"? 3564 return array.lastIndexOf(a, x, from); 3565 } 3566 var l = a && a.length || 0, end = up ? l + uOver : lOver, i; 3567 if(from === u){ 3568 i = up ? lOver : l + uOver; 3569 }else{ 3570 if(from < 0){ 3571 i = l + from; 3572 if(i < 0){ 3573 i = lOver; 3574 } 3575 }else{ 3576 i = from >
3576= l ? l + uOver : from; 3577 } 3578 } 3579 if(l && typeof a == "string") a = a.split(""); 3580 for(; i != end; i += delta){ 3581 if(a[i] == x){ 3582 return i; // Number 3583 } 3584 } 3585 return -1; // Number 3586 }; 3587 } 3588 3589 var array = { 3590 // summary: 3591 // The Javascript v1.6 array extensions. 3592 3593 every: everyOrSome(false), 3594 /*===== 3595 every: function(arr, callback, thisObject){ 3596 // summary: 3597 // Determines whether or not every item in arr satisfies the 3598 // condition implemented by callback. 3599 // arr: Array|String 3600 // the array to iterate on. If a string, operates on individual characters. 3601 // callback: Function|String 3602 // a function is invoked with three arguments: item, index, 3603 // and array and returns true if the condition is met. 3604 // thisObject: Object? 3605 // may be used to scope the call to callback 3606 // returns: Boolean 3607 // description: 3608 // This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when 3609 // run over sparse arrays, this implementation passes the "holes" in the sparse array to 3610 // the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array. 3611 // For more details, see: 3612 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every 3613 // example: 3614 // | // returns false 3615 // | array.every([1, 2, 3, 4], function(item){ return item>1; }); 3616 // example: 3617 // | // returns true 3618 // | array.every([1, 2, 3, 4], function(item){ return item>0; }); 3619 }, 3620 =====*/ 3621 3622 some: everyOrSome(true), 3623 /*===== 3624 some: function(arr, callback, thisObject){ 3625 // summary: 3626 // Determines whether or not any item in arr satisfies the 3627 // condition implemented by callback. 3628 // arr: Array|String 3629 // the array to iterate over. If a string, operates on individual characters. 3630 // callback: Function|String 3631 // a function is invoked with three arguments: item, index, 3632 // and array and returns true if the condition is met. 3633 // thisObject: Object? 3634 // may be used to scope the call to callback 3635 // returns: Boolean 3636 // description: 3637 // This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when 3638 // run over sparse arrays, this implementation passes the "holes" in the sparse array to 3639 // the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array. 3640 // For more details, see: 3641 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some 3642 // example: 3643 // | // is true 3644 // | array.some([1, 2, 3, 4], function(item){ return item>1; }); 3645 // example: 3646 // | // is false 3647 // | array.some([1, 2, 3, 4], function(item){ return item<1; }); 3648 }, 3649 =====*/ 3650 3651 indexOf: index(true), 3652 /*===== 3653 indexOf: function(arr, value, fromIndex, findLast){ 3654 // summary: 3655 // locates the first index of the provided value in the 3656 // passed array. If the value is not found, -1 is returned. 3657 // description: 3658 // This method corresponds to the JavaScript 1.6 Array.indexOf method, with two differences: 3659 // 3660 // 1. when run over sparse arrays, the Dojo function invokes the callback for every index 3661 // whereas JavaScript 1.6's indexOf skips the holes in the sparse array. 3662 // 2. uses equality (==) rather than strict equality (===) 3663 // 3664 // For details on this method, see: 3665 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf 3666 // arr: Array 3667 // value: Object 3668 // fromIndex: Integer? 3669 // findLast: Boolean? 3670 // Makes indexOf() work like lastIndexOf(). Used internally; not meant for external usage. 3671 // returns: Number 3672 }, 3673 =====*/ 3674 3675 lastIndexOf: index(false), 3676 /*===== 3677 lastIndexOf: function(arr, value, fromIndex){ 3678 // summary: 3679 // locates the last index of the provided value in the passed 3680 // array. If the value is not found, -1 is returned. 3681 // description: 3682 // This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with two differences: 3683 // 3684 // 1. when run over sparse arrays, the Dojo function invokes the callback for every index 3685 // whereas JavaScript 1.6's lasIndexOf skips the holes in the sparse array. 3686 // 2. uses equality (==) rather than strict equality (===) 3687 // 3688 // For details on this method, see: 3689 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf 3690 // arr: Array, 3691 // value: Object, 3692 // fromIndex: Integer? 3693 // returns: Number 3694 }, 3695 =====*/ 3696 3697 forEach: function(arr, callback, thisObject){ 3698 // summary: 3699 // for every item in arr, callback is invoked. Return values are ignored. 3700 // If you want to break out of the loop, consider using array.every() or array.some(). 3701 // forEach does not allow breaking out of the loop over the items in arr. 3702 // arr: 3703 // the array to iterate over. If a string, operates on individual characters. 3704 // callback:
3705 // a function is invoked with three arguments: item, index, and array 3706 // thisObject: 3707 // may be used to scope the call to callback 3708 // description: 3709 // This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when 3710 // run over sparse arrays, this implementation passes the "holes" in the sparse array to 3711 // the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array. 3712 // For more details, see: 3713 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach 3714 // example: 3715 // | // log out all members of the array: 3716 // | array.forEach( 3717 // | [ "thinger", "blah", "howdy", 10 ], 3718 // | function(item){ 3719 // | console.log(item); 3720 // | } 3721 // | ); 3722 // example: 3723 // | // log out the members and their indexes 3724 // | array.forEach( 3725 // | [ "thinger", "blah", "howdy", 10 ], 3726 // | function(item, idx, arr){ 3727 // | console.log(item, "at index:", idx); 3728 // | } 3729 // | ); 3730 // example: 3731 // | // use a scoped object member as the callback 3732 // | 3733 // | var obj = { 3734 // | prefix: "logged via obj.callback:", 3735 // | callback: function(item){ 3736 // | console.log(this.prefix, item); 3737 // | } 3738 // | }; 3739 // | 3740 // | // specifying the scope function executes the callback in that scope 3741 // | array.forEach( 3742 // | [ "thinger", "blah", "howdy", 10 ], 3743 // | obj.callback, 3744 // | obj 3745 // | ); 3746 // | 3747 // | // alternately, we can accomplish the same thing with lang.hitch() 3748 // | array.forEach( 3749 // | [ "thinger", "blah", "howdy", 10 ], 3750 // | lang.hitch(obj, "callback") 3751 // | ); 3752 // arr: Array|String 3753 // callback: Function|String 3754 // thisObject: Object? 3755 3756 var i = 0, l = arr && arr.length || 0; 3757 if(l && typeof arr == "string") arr = arr.split(""); 3758 if(typeof callback == "string") callback = cache[callback] || buildFn(callback); 3759 if(thisObject){ 3760 for(; i < l; ++i){ 3761 callback.call(thisObject, arr[i], i, arr); 3762 } 3763 }else{ 3764 for(; i < l; ++i){ 3765 callback(arr[i], i, arr); 3766 } 3767 } 3768 }, 3769 3770 map: function(arr, callback, thisObject, Ctr){ 3771 // summary: 3772 // applies callback to each element of arr and returns 3773 // an Array with the results 3774 // arr: Array|String 3775 // the array to iterate on. If a string, operates on 3776 // individual characters. 3777 // callback: Function|String 3778 // a function is invoked with three arguments, (item, index, 3779 // array), and returns a value 3780 // thisObject: Object? 3781 // may be used to scope the call to callback 3782 // returns: Array 3783 // description: 3784 // This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when 3785 // run over sparse arrays, this implementation passes the "holes" in the sparse array to 3786 // the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array. 3787 // For more details, see: 3788 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map 3789 // example: 3790 // | // returns [2, 3, 4, 5] 3791 // | array.map([1, 2, 3, 4], function(item){ return item+1 }); 3792 3793 // TODO: why do we have a non-standard signature here? do we need "Ctr"? 3794 var i = 0, l = arr && arr.length || 0, out = new (Ctr || Array)(l); 3795 if(l && typeof arr == "string") arr = arr.split(""); 3796 if(typeof callback == "string") callback = cache[callback] || buildFn(callback); 3797 if(thisObject){ 3798 for(; i < l; ++i){ 3799 out[i] = callback.call(thisObject, arr[i], i, arr); 3800 } 3801 }else{ 3802 for(; i < l; ++i){ 3803 out[i] = callback(arr[i], i, arr); 3804 } 3805 } 3806 return out; // Array 3807 }, 3808 3809 filter: function(arr, callback, thisObject){ 3810 // summary: 3811 // Returns a new Array with those items from arr that match the 3812 // condition implemented by callback. 3813 // arr: Array 3814 // the array to iterate over. 3815 // callback: Function|String 3816 // a function that is invoked with three arguments (item, 3817 // index, array). The return of this function is expected to 3818 // be a boolean which determines whether the passed-in item 3819 // will be included in the returned array. 3820 // thisObject: Object? 3821 // may be used to scope the call to callback 3822 // returns: Array 3823 // description: 3824 // This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when 3825 // run over sparse arrays, this implementation passes the "holes" in the sparse array to 3826 // the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array. 3827 // For more details, see: 3828 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter 3829 // example: 3830 // | // returns [2, 3, 4] 3831 // | array.filter([1, 2, 3, 4], function(item){ return item>1; }); 3832 3833 // TODO: do we need "Ctr" here like in map()?
3834 var i = 0, l = arr && arr.length || 0, out = [], value; 3835 if(l && typeof arr == "string") arr = arr.split(""); 3836 if(typeof callback == "string") callback = cache[callback] || buildFn(callback); 3837 if(thisObject){ 3838 for(; i < l; ++i){ 3839 value = arr[i]; 3840 if(callback.call(thisObject, value, i, arr)){ 3841 out.push(value); 3842 } 3843 } 3844 }else{ 3845 for(; i < l; ++i){ 3846 value = arr[i]; 3847 if(callback(value, i, arr)){ 3848 out.push(value); 3849 } 3850 } 3851 } 3852 return out; // Array 3853 }, 3854 3855 clearCache: function(){ 3856 cache = {}; 3857 } 3858 }; 3859 3860 3861 1 && lang.mixin(dojo, array); 3862 3863 return array; 3864}); 3865 3866}, 3867'dojo/ready':function(){ 3868define(["./_base/kernel", "./has", "require", "./domReady", "./_base/lang"], function(dojo, has, require, domReady, lang){ 3869 // module: 3870 // dojo/ready 3871 // note: 3872 // This module should be unnecessary in dojo 2.0 3873 3874 var 3875 // truthy if DOMContentLoaded or better (e.g., window.onload fired) has been achieved 3876 isDomReady = 0, 3877 3878 // The queue of functions waiting to execute as soon as dojo.ready conditions satisfied 3879 loadQ = [], 3880 3881 // prevent recursion in onLoad 3882 onLoadRecursiveGuard = 0, 3883 3884 handleDomReady = function(){ 3885 isDomReady = 1; 3886 dojo._postLoad = dojo.config.afterOnLoad = true; 3887 onEvent(); 3888 }, 3889 3890 onEvent = function(){ 3891 // Called when some state changes: 3892 // - dom ready 3893 // - dojo/domReady has finished processing everything in its queue 3894 // - task added to loadQ 3895 // - require() has finished loading all currently requested modules 3896 // 3897 // Run the functions queued with dojo.ready if appropriate. 3898 3899 3900 //guard against recursions into this function 3901 if(onLoadRecursiveGuard){ 3902 return; 3903 } 3904 onLoadRecursiveGuard = 1; 3905 3906 // Run tasks in queue if require() is finished loading modules, the dom is ready, and there are no 3907 // pending tasks registered via domReady(). 3908 // The last step is necessary so that a user defined dojo.ready() callback is delayed until after the 3909 // domReady() calls inside of dojo. Failure can be seen on dijit/tests/robot/Dialog_ally.html on IE8 3910 // because the dijit/focus.js domReady() callback doesn't execute until after the test starts running. 3911 while(isDomReady && (!domReady || domReady._Q.length == 0) && (require.idle ? require.idle() : true) && loadQ.length){ 3912 var f = loadQ.shift(); 3913 try{ 3914 f(); 3915 }catch(e){ 3916 // force the dojo.js on("error") handler do display the message 3917 e.info = e.message; 3918 if(require.signal){ 3919 require.signal("error", e); 3920 }else{ 3921 throw e; 3922 } 3923 } 3924 } 3925 3926 onLoadRecursiveGuard = 0; 3927 }; 3928 3929 // Check if we should run the next queue operation whenever require() finishes loading modules or domReady 3930 // finishes processing it's queue. 3931 require.on && require.on("idle", onEvent); 3932 if(domReady){ 3933 domReady._onQEmpty = onEvent; 3934 } 3935 3936 var ready = dojo.ready = dojo.addOnLoad = function(priority, context, callback){ 3937 // summary: 3938 // Add a function to execute on DOM content loaded and all requested modules have arrived and been evaluated. 3939 // In most cases, the `domReady` plug-in should suffice and this method should not be needed. 3940 // 3941 // When called in a non-browser environment, just checks that all requested modules have arrived and been 3942 // evaluated. 3943 // priority: Integer? 3944 // The order in which to exec this callback relative to other callbacks, defaults to 1000 3945 // context: Object?|Function 3946 // The context in which to run execute callback, or a callback if not using context 3947 // callback: Function? 3948 // The function to execute. 3949 // 3950 // example: 3951 // Simple DOM and Modules ready syntax 3952 // | require(["dojo/ready"], function(ready){ 3953 // | ready(function(){ alert("Dom ready!"); }); 3954 // | }); 3955 // 3956 // example: 3957 // Using a priority 3958 // | require(["dojo/ready"], function(ready){ 3959 // | ready(2, function(){ alert("low priority ready!"); }) 3960 // | }); 3961 // 3962 // example: 3963 // Using context 3964 // | require(["dojo/ready"], function(ready){ 3965 // | ready(foo, function(){ 3966 // | // in here, this == foo 3967 // | }); 3968 // | }); 3969 // 3970 // example: 3971 // Using dojo/hitch style args: 3972 // | require(["dojo/ready"], function(ready){ 3973 // | var foo = { dojoReady: function(){ console.warn(this, "dojo dom and modules ready."); } }; 3974 // | ready(foo, "dojoReady"); 3975 // | }); 3976 3977 var hitchArgs = lang._toArray(arguments); 3978 if(typeof priority != "number"){ 3979 callback = context; 3980 context = priority; 3981 priority = 1000; 3982 }else{ 3983 hitchArgs.shift(); 3984 } 3985 callback = callback ? 3986 lang.hitch.apply(dojo, hitchArgs) : 3987 function(){ 3988 context(); 3989 }; 3990 callback.priority = priority; 3991 for(var i = 0; i < loadQ.length && priority >= loadQ[i].priority; i++){} 3992 loadQ.splice(i, 0, callback); 3993 onEvent(); 3994 }; 3995 3996 1 || has.add("dojo-config-addOnLoad", 1); 3997 if( 1 ){ 3998 var dca = dojo.config.addOnLoad; 3999 if(dca){ 4000 ready[(lang.isArray(dca) ? "apply" : "call")](dojo, dca); 4001 } 4002 } 4003 4004 if( 0 && dojo.config.parseOnLoad && !dojo.isAsync){ 4005 ready(99, function(){ 4006 if(!dojo.parser){ 4007 dojo.deprecated("Add explicit require(['dojo/parser']);", "", "2.0"); 4008 require(["dojo/parser"]); 4009 } 4010 }); 4011 } 4012 4013 if(domReady){ 4014 domReady(handleDomReady); 4015 }else{ 4016 handleDomReady(); 4017 } 4018 4019 return ready; 4020}); 4021 4022}, 4023'dojo/domReady':function(){ 4024define(['./has'], function(has){ 4025 var global = (function () { return this; })(), 4026 doc = document, 4027 readyStates = { 'loaded': 1, 'complete': 1 }, 4028 fixReadyState = typeof doc.readyState != "string", 4029 ready = !!readyStates[doc.readyState], 4030 readyQ = [], 4031 recursiveGuard; 4032 4033 function domReady(callback){ 4034 // summary: 4035 // Plugin to delay require()/define() callback from firing until the DOM has finished loading. 4036 readyQ.push(callback); 4037 if(ready){ processQ(); } 4038 } 4039 domReady.load = function(id, req, load){ 4040 domReady(load); 4041 }; 4042 4043 // Export queue so that ready() can check if it's empty or not. 4044 domReady._Q = readyQ; 4045 domReady._onQEmpty = function(){ 4046 // summary: 4047 // Private method overridden by dojo/ready, to notify when everything in the 4048 // domReady queue has been processed. Do not use directly. 4049 // Will be removed in 2.0, along with domReady._Q. 4050 }; 4051 4052 // For FF <= 3.5 4053 if(fixReadyState){ doc.readyState = "loading"; } 4054 4055 function processQ(){ 4056 // Calls all functions in the queue in order, unless processQ() is already running, in which case just return 4057 4058 if(recursiveGuard){ return; } 4059 recursiveGuard = true; 4060 4061 while(readyQ.length){ 4062 try{ 4063 (readyQ.shift())(doc); 4064 }catch(err){ 4065 console.error(err, "in domReady callback", err.stack); 4066 } 4067 } 4068 4069 recursiveGuard = false; 4070 4071 // Notification for dojo/ready. Remove for 2.0. 4072 // Note that this could add more tasks to the ready queue. 4073 domReady._onQEmpty(); 4074 } 4075 4076 if(!ready){ 4077 var tests = [], 4078 detectReady = function(evt){ 4079 evt = evt || global.event; 4080 if(ready || (evt.type == "readystatechange" && !readyStates[doc.readyState])){ return; } 4081 4082 // For FF <= 3.5 4083 if(fixReadyState){ doc.readyState = "complete"; } 4084 4085 ready = 1; 4086 processQ(); 4087 }, 4088 on = function(node, event){ 4089 node.addEventListener(event, detectReady, false); 4090 readyQ.push(function(){ node.removeEventListener(event, detectReady, false); }); 4091 }; 4092 4093 if(!has("dom-addeventlistener")){ 4094 on = function(node, event){ 4095 event = "on" + event; 4096 node.attachEvent(event, detectReady); 4097 readyQ.push(function(){ node.detachEvent(event, detectReady); }); 4098 }; 4099 4100 var div = doc.createElement("div"); 4101 try{ 4102 if(div.doScroll && global.frameElement === null){ 4103 // the doScroll test is only useful if we're in the top-most frame 4104 tests.push(function(){ 4105 // Derived with permission from Diego Perini's IEContentLoaded 4106 // http://javascript.nwbox.com/IEContentLoaded/ 4107 try{ 4108 div.doScroll("left"); 4109 return 1; 4110 }catch(e){} 4111 });
4112 } 4113 }catch(e){} 4114 } 4115 4116 on(doc, "DOMContentLoaded"); 4117 on(global, "load"); 4118 4119 if("onreadystatechange" in doc){ 4120 on(doc, "readystatechange"); 4121 }else if(!fixReadyState){ 4122 // if the ready state property exists and there's 4123 // no readystatechange event, poll for the state 4124 // to change 4125 tests.push(function(){ 4126 return readyStates[doc.readyState]; 4127 }); 4128 } 4129 4130 if(tests.length){ 4131 var poller = function(){ 4132 if(ready){ return; } 4133 var i = tests.length; 4134 while(i--){ 4135 if(tests[i]()){ 4136 detectReady("poller"); 4137 return; 4138 } 4139 } 4140 setTimeout(poller, 30); 4141 }; 4142 poller(); 4143 } 4144 } 4145 4146 return domReady; 4147}); 4148 4149}, 4150'dojo/_base/declare':function(){ 4151define(["./kernel", "../has", "./lang"], function(dojo, has, lang){ 4152 // module: 4153 // dojo/_base/declare 4154 4155 var mix = lang.mixin, op = Object.prototype, opts = op.toString, 4156 xtor = new Function, counter = 0, cname = "constructor"; 4157 4158 function err(msg, cls){ throw new Error("declare" + (cls ? " " + cls : "") + ": " + msg); } 4159 4160 // C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/) 4161 function c3mro(bases, className){ 4162 var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1, 4163 l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs; 4164 4165 // build a list of bases naming them if needed 4166 for(; i < l; ++i){ 4167 base = bases[i]; 4168 if(!base){ 4169 err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?", className); 4170 }else if(opts.call(base) != "[object Function]"){ 4171 err("mixin #" + i + " is not a callable constructor.", className); 4172 } 4173 lin = base._meta ? base._meta.bases : [base]; 4174 top = 0; 4175 // add bases to the name map 4176 for(j = lin.length - 1; j >= 0; --j){ 4177 proto = lin[j].prototype; 4178 if(!proto.hasOwnProperty("declaredClass")){ 4179 proto.declaredClass = "uniqName_" + (counter++); 4180 } 4181 name = proto.declaredClass; 4182 if(!nameMap.hasOwnProperty(name)){ 4183 nameMap[name] = {count: 0, refs: [], cls: lin[j]}; 4184 ++clsCount; 4185 } 4186 rec = nameMap[name]; 4187 if(top && top !== rec){ 4188 rec.refs.push(top); 4189 ++top.count; 4190 } 4191 top = rec; 4192 } 4193 ++top.count; 4194 roots[0].refs.push(top); 4195 } 4196 4197 // remove classes without external references recursively 4198 while(roots.length){ 4199 top = roots.pop(); 4200 result.push(top.cls); 4201 --clsCount; 4202 // optimization: follow a single-linked chain 4203 while(refs = top.refs, refs.length == 1){ 4204 top = refs[0]; 4205 if(!top || --top.count){ 4206 // branch or end of chain => do not end to roots 4207 top = 0; 4208 break; 4209 } 4210 result.push(top.cls); 4211 --clsCount; 4212 } 4213 if(top){ 4214 // branch 4215 for(i = 0, l = refs.length; i < l; ++i){ 4216 top = refs[i]; 4217 if(!--top.count){ 4218 roots.push(top); 4219 } 4220 } 4221 } 4222 } 4223 if(clsCount){ 4224 err("can't build consistent linearization", className); 4225 } 4226 4227 // calculate the superclass offset 4228 base = bases[0]; 4229 result[0] = base ? 4230 base._meta && base === result[result.length - base._meta.bases.length] ? 4231 base._meta.bases.length : 1 : 0; 4232 4233 return result; 4234 } 4235 4236 function inherited(args, a, f){ 4237 var name, chains, bases, caller, meta, base, proto, opf, pos, 4238 cache = this._inherited = this._inherited || {}; 4239 4240 // crack arguments 4241 if(typeof args == "string"){ 4242 name = args; 4243 args = a; 4244 a = f; 4245 } 4246 f = 0; 4247 4248 caller = args.callee; 4249 name = name || caller.nom; 4250 if(!name){ 4251 err("can't deduce a name to call inherited()", this.declaredClass); 4252 } 4253 4254 meta = this.constructor._meta; 4255 bases = meta.bases; 4256 4257 pos = cache.p; 4258 if(name != cname){ 4259 // method 4260 if(cache.c !== caller){ 4261 // cache bust 4262 pos = 0; 4263 base = bases[0]; 4264 meta = base._meta; 4265 if(meta.hidden[name] !== caller){ 4266 // error detection 4267 chains = meta.chains; 4268 if(chains && typeof chains[name] == "string"){ 4269 err("calling chained method with inherited: " + name, this.declaredClass); 4270 } 4271 // find caller 4272 do{ 4273 meta = base._meta; 4274 proto = base.prototype; 4275 if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){ 4276 break; 4277 } 4278 }while(base = bases[++pos]); // intentional assignment 4279 pos = base ? pos : -1; 4280 } 4281 } 4282 // find next 4283 base = bases[++pos]; 4284 if(base){ 4285 proto = base.prototype; 4286 if(base._meta && proto.hasOwnProperty(name)){ 4287 f = proto[name]; 4288 }else{ 4289 opf = op[name]; 4290 do{ 4291 proto = base.prototype; 4292 f = proto[name]; 4293 if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){ 4294 break; 4295 } 4296 }while(base = bases[++pos]); // intentional assignment 4297 } 4298 } 4299 f = base && f || op[name]; 4300 }else{ 4301 // constructor 4302 if(cache.c !== caller){ 4303 // cache bust 4304 pos = 0;
4305 meta = bases[0]._meta; 4306 if(meta && meta.ctor !== caller){ 4307 // error detection 4308 chains = meta.chains; 4309 if(!chains || chains.constructor !== "manual"){ 4310 err("calling chained constructor with inherited", this.declaredClass); 4311 } 4312 // find caller 4313 while(base = bases[++pos]){ // intentional assignment 4314 meta = base._meta; 4315 if(meta && meta.ctor === caller){ 4316 break; 4317 } 4318 } 4319 pos = base ? pos : -1; 4320 } 4321 } 4322 // find next 4323 while(base = bases[++pos]){ // intentional assignment 4324 meta = base._meta; 4325 f = meta ? meta.ctor : base; 4326 if(f){ 4327 break; 4328 } 4329 } 4330 f = base && f; 4331 } 4332 4333 // cache the found super method 4334 cache.c = f; 4335 cache.p = pos; 4336 4337 // now we have the result 4338 if(f){ 4339 return a === true ? f : f.apply(this, a || args); 4340 } 4341 // intentionally no return if a super method was not found 4342 } 4343 4344 function getInherited(name, args){ 4345 if(typeof name == "string"){ 4346 return this.__inherited(name, args, true); 4347 } 4348 return this.__inherited(name, true); 4349 } 4350 4351 function inherited__debug(args, a1, a2){ 4352 var f = this.getInherited(args, a1); 4353 if(f){ return f.apply(this, a2 || a1 || args); } 4354 // intentionally no return if a super method was not found 4355 } 4356 4357 var inheritedImpl = dojo.config.isDebug ? inherited__debug : inherited; 4358 4359 // emulation of "instanceof" 4360 function isInstanceOf(cls){ 4361 var bases = this.constructor._meta.bases; 4362 for(var i = 0, l = bases.length; i < l; ++i){ 4363 if(bases[i] === cls){ 4364 return true; 4365 } 4366 } 4367 return this instanceof cls; 4368 } 4369 4370 function mixOwn(target, source){ 4371 // add props adding metadata for incoming functions skipping a constructor 4372 for(var name in source){ 4373 if(name != cname && source.hasOwnProperty(name)){ 4374 target[name] = source[name]; 4375 } 4376 } 4377 if(has("bug-for-in-skips-shadowed")){ 4378 for(var extraNames= lang._extraNames, i= extraNames.length; i;){ 4379 name = extraNames[--i]; 4380 if(name != cname && source.hasOwnProperty(name)){ 4381 target[name] = source[name]; 4382 } 4383 } 4384 } 4385 } 4386 4387 // implementation of safe mixin function 4388 function safeMixin(target, source){ 4389 // summary: 4390 // Mix in properties skipping a constructor and decorating functions 4391 // like it is done by declare(). 4392 // target: Object 4393 // Target object to accept new properties. 4394 // source: Object 4395 // Source object for new properties. 4396 // description: 4397 // This function is used to mix in properties like lang.mixin does, 4398 // but it skips a constructor property and decorates functions like 4399 // declare() does. 4400 // 4401 // It is meant to be used with classes and objects produced with 4402 // declare. Functions mixed in with dojo.safeMixin can use 4403 // this.inherited() like normal methods. 4404 // 4405 // This function is used to implement extend() method of a constructor 4406 // produced with declare(). 4407 // 4408 // example: 4409 // | var A = declare(null, { 4410 // | m1: function(){ 4411 // | console.log("A.m1"); 4412 // | }, 4413 // | m2: function(){ 4414 // | console.log("A.m2"); 4415 // | } 4416 // | }); 4417 // | var B = declare(A, { 4418 // | m1: function(){ 4419 // | this.inherited(arguments); 4420 // | console.log("B.m1"); 4421 // | } 4422 // | }); 4423 // | B.extend({ 4424 // | m2: function(){ 4425 // | this.inherited(arguments); 4426 // | console.log("B.m2"); 4427 // | } 4428 // | }); 4429 // | var x = new B(); 4430 // | dojo.safeMixin(x, { 4431 // | m1: function(){ 4432 // | this.inherited(arguments); 4433 // | console.log("X.m1"); 4434 // | }, 4435 // | m2: function(){ 4436 // | this.inherited(arguments); 4437 // | console.log("X.m2"); 4438 // | } 4439 // | }); 4440 // | x.m2(); 4441 // | // prints: 4442 // | // A.m1 4443 // | // B.m1 4444 // | // X.m1 4445 4446 var name, t; 4447 // add props adding metadata for incoming functions skipping a constructor 4448 for(name in source){ 4449 t = source[name]; 4450 if((t !== op[name] || !(name in op)) && name != cname){ 4451 if(opts.call(t) == "[object Function]"){ 4452 // non-trivial function method => attach its name 4453 t.nom = name; 4454 } 4455 target[name] = t; 4456 } 4457 } 4458 if(has("bug-for-in-skips-shadowed")){ 4459 for(var extraNames= lang._extraNames, i= extraNames.length; i;){ 4460 name = extraNames[--i]; 4461 t = source[name]; 4462 if((t !== op[name] || !(name in op)) && name != cname){ 4463 if(opts.call(t) == "[object Function]"){ 4464 // non-trivial function method => attach its name 4465 t.nom = name; 4466 } 4467 target[name] = t; 4468 } 4469 } 4470 } 4471 return target; 4472 } 4473 4474 function extend(source){ 4475 declare.safeMixin(this.prototype, source); 4476 return this; 4477 } 4478 4479 function createSubclass(mixins, props){ 4480 // crack parameters 4481 if(!(mixins instanceof Array || typeof mixins == 'function')){ 4482 props = mixins; 4483 mixins = undefined; 4484 } 4485 4486 props = props || {}; 4487 mixins = mixins || []; 4488 4489 return declare([this].concat(mixins), props); 4490 } 4491 4492 // chained constructor compatible with the legacy declare() 4493 function chainedConstructor(bases, ctorSpecial){ 4494 return function(){ 4495 var a = arguments, args = a, a0 = a[0], f, i, m,
4496 l = bases.length, preArgs; 4497 4498 if(!(this instanceof a.callee)){ 4499 // not called via new, so force it 4500 return applyNew(a); 4501 } 4502 4503 //this._inherited = {}; 4504 // perform the shaman's rituals of the original declare() 4505 // 1) call two types of the preamble 4506 if(ctorSpecial && (a0 && a0.preamble || this.preamble)){ 4507 // full blown ritual 4508 preArgs = new Array(bases.length); 4509 // prepare parameters 4510 preArgs[0] = a; 4511 for(i = 0;;){ 4512 // process the preamble of the 1st argument 4513 a0 = a[0]; 4514 if(a0){ 4515 f = a0.preamble; 4516 if(f){ 4517 a = f.apply(this, a) || a; 4518 } 4519 } 4520 // process the preamble of this class 4521 f = bases[i].prototype; 4522 f = f.hasOwnProperty("preamble") && f.preamble; 4523 if(f){ 4524 a = f.apply(this, a) || a; 4525 } 4526 // one peculiarity of the preamble: 4527 // it is called if it is not needed, 4528 // e.g., there is no constructor to call 4529 // let's watch for the last constructor 4530 // (see ticket #9795) 4531 if(++i == l){ 4532 break; 4533 } 4534 preArgs[i] = a; 4535 } 4536 } 4537 // 2) call all non-trivial constructors using prepared arguments 4538 for(i = l - 1; i >= 0; --i){ 4539 f = bases[i]; 4540 m = f._meta; 4541 f = m ? m.ctor : f; 4542 if(f){
4543 f.apply(this, preArgs ? preArgs[i] : a); 4544 } 4545 } 4546 // 3) continue the original ritual: call the postscript 4547 f = this.postscript; 4548 if(f){ 4549 f.apply(this, args); 4550 } 4551 }; 4552 } 4553 4554 4555 // chained constructor compatible with the legacy declare() 4556 function singleConstructor(ctor, ctorSpecial){ 4557 return function(){ 4558 var a = arguments, t = a, a0 = a[0], f; 4559 4560 if(!(this instanceof a.callee)){ 4561 // not called via new, so force it 4562 return applyNew(a); 4563 } 4564 4565 //this._inherited = {}; 4566 // perform the shaman's rituals of the original declare() 4567 // 1) call two types of the preamble 4568 if(ctorSpecial){ 4569 // full blown ritual 4570 if(a0){ 4571 // process the preamble of the 1st argument 4572 f = a0.preamble; 4573 if(f){ 4574 t = f.apply(this, t) || t; 4575 } 4576 } 4577 f = this.preamble; 4578 if(f){ 4579 // process the preamble of this class 4580 f.apply(this, t); 4581 // one peculiarity of the preamble: 4582 // it is called even if it is not needed, 4583 // e.g., there is no constructor to call 4584 // let's watch for the last constructor 4585 // (see ticket #9795) 4586 } 4587 } 4588 // 2) call a constructor 4589 if(ctor){ 4590 ctor.apply(this, a); 4591 } 4592 // 3) continue the original ritual: call the postscript 4593 f = this.postscript; 4594 if(f){ 4595 f.apply(this, a); 4596 } 4597 }; 4598 } 4599 4600 // plain vanilla constructor (can use inherited() to call its base constructor) 4601 function simpleConstructor(bases){ 4602 return function(){ 4603 var a = arguments, i = 0, f, m; 4604 4605 if(!(this instanceof a.callee)){ 4606 // not called via new, so force it 4607 return applyNew(a); 4608 } 4609 4610 //this._inherited = {}; 4611 // perform the shaman's rituals of the original declare() 4612 // 1) do not call the preamble 4613 // 2) call the top constructor (it can use this.inherited()) 4614 for(; f = bases[i]; ++i){ // intentional assignment 4615 m = f._meta; 4616 f = m ? m.ctor : f; 4617 if(f){ 4618 f.apply(this, a); 4619 break; 4620 } 4621 } 4622 // 3) call the postscript 4623 f = this.postscript; 4624 if(f){ 4625 f.apply(this, a); 4626 } 4627 }; 4628 } 4629 4630 function chain(name, bases, reversed){ 4631 return function(){ 4632 var b, m, f, i = 0, step = 1; 4633 if(reversed){ 4634 i = bases.length - 1; 4635 step = -1; 4636 } 4637 for(; b = bases[i]; i += step){ // intentional assignment 4638 m = b._meta; 4639 f = (m ? m.hidden : b.prototype)[name]; 4640 if(f){ 4641 f.apply(this, arguments); 4642 } 4643 } 4644 }; 4645 } 4646 4647 // forceNew(ctor) 4648 // return a new object that inherits from ctor.prototype but 4649 // without actually running ctor on the object. 4650 function forceNew(ctor){ 4651 // create object with correct prototype using a do-nothing 4652 // constructor 4653 xtor.prototype = ctor.prototype; 4654 var t = new xtor; 4655 xtor.prototype = null; // clean up 4656 return t; 4657 } 4658 4659 // applyNew(args) 4660 // just like 'new ctor()' except that the constructor and its arguments come 4661 // from args, which must be an array or an arguments object 4662 function applyNew(args){ 4663 // create an object with ctor's prototype but without 4664 // calling ctor on it. 4665 var ctor = args.callee, t = forceNew(ctor); 4666 // execute the real constructor on the new object 4667 ctor.apply(t, args); 4668 return t; 4669 } 4670 4671 function declare(className, superclass, props){ 4672 // summary: 4673 // Create a feature-rich constructor from compact notation. 4674 // className: String? 4675 // The optional name of the constructor (loosely, a "class") 4676 // stored in the "declaredClass" property in the created prototype. 4677 // It will be used as a global name for a created constructor. 4678 // superclass: Function|Function[] 4679 // May be null, a Function, or an Array of Functions. This argument 4680 // specifies a list of bases (the left-most one is the most deepest 4681 // base). 4682 // props: Object 4683 // An object whose properties are copied to the created prototype. 4684 // Add an instance-initialization function by making it a property 4685 // named "constructor". 4686 // returns: dojo/_base/declare.__DeclareCreatedObject 4687 // New constructor function. 4688 // description: 4689 // Create a constructor using a compact notation for inheritance and 4690 // prototype extension. 4691 // 4692 // Mixin ancestors provide a type of multiple inheritance. 4693 // Prototypes of mixin ancestors are copied to the new class: 4694 // changes to mixin prototypes will not affect classes to which 4695 // they have been mixed in. 4696 // 4697 // Ancestors can be compound classes created by this version of 4698 // declare(). In complex cases all base classes are going to be 4699 // linearized according to C3 MRO algorithm 4700 // (see http://www.python.org/download/releases/2.3/mro/ for more 4701 // details). 4702 // 4703 // "className" is cached in "declaredClass" property of the new class, 4704 // if it was supplied. The immediate super class will be cached in 4705 // "superclass" property of the new class. 4706 // 4707 // Methods in "props" will be copied and modified: "nom" property 4708 // (the declared name of the method) will be added to all copied 4709 // functions to help identify them for the internal machinery. Be 4710 // very careful, while reusing methods: if you use the same 4711 // function under different names, it can produce errors in some 4712 // cases. 4713 // 4714 // It is possible to use constructors created "manually" (without 4715 // declare()) as bases. They will be called as usual during the 4716 // creation of an instance, their methods will be chained, and even 4717 // called by "this.inherited()". 4718 // 4719 // Special property "-chains-" governs how to chain methods. It is
4720 // a dictionary, which uses method names as keys, and hint strings 4721 // as values. If a hint string is "after", this method will be 4722 // called after methods of its base classes. If a hint string is 4723 // "before", this method will be called before methods of its base 4724 // classes. 4725 // 4726 // If "constructor" is not mentioned in "-chains-" property, it will 4727 // be chained using the legacy mode: using "after" chaining, 4728 // calling preamble() method before each constructor, if available, 4729 // and calling postscript() after all constructors were executed. 4730 // If the hint is "after", it is chained as a regular method, but 4731 // postscript() will be called after the chain of constructors. 4732 // "constructor" cannot be chained "before", but it allows 4733 // a special hint string: "manual", which means that constructors 4734 // are not going to be chained in any way, and programmer will call 4735 // them manually using this.inherited(). In the latter case 4736 // postscript() will be called after the construction. 4737 // 4738 // All chaining hints are "inherited" from base classes and 4739 // potentially can be overridden. Be very careful when overriding 4740 // hints! Make sure that all chained methods can work in a proposed 4741 // manner of chaining. 4742 // 4743 // Once a method was chained, it is impossible to unchain it. The 4744 // only exception is "constructor". You don't need to define a 4745 // method in order to supply a chaining hint. 4746 // 4747 // If a method is chained, it cannot use this.inherited() because 4748 // all other methods in the hierarchy will be called automatically. 4749 // 4750 // Usually constructors and initializers of any kind are chained 4751 // using "after" and destructors of any kind are chained as 4752 // "before". Note that chaining assumes that chained methods do not 4753 // return any value: any returned value will be discarded. 4754 // 4755 // example: 4756 // | declare("my.classes.bar", my.classes.foo, { 4757 // | // properties to be added to the class prototype 4758 // | someValue: 2, 4759 // | // initialization function 4760 // | constructor: function(){ 4761 // | this.myComplicatedObject = new ReallyComplicatedObject(); 4762 // | }, 4763 // | // other functions 4764 // | someMethod: function(){ 4765 // | doStuff(); 4766 // | } 4767 // | }); 4768 // 4769 // example: 4770 // | var MyBase = declare(null, { 4771 // | // constructor, properties, and methods go here 4772 // | // ... 4773 // | }); 4774 // | var MyClass1 = declare(MyBase, { 4775 // | // constructor, properties, and methods go here 4776 // | // ... 4777 // | }); 4778 // | var MyClass2 = declare(MyBase, { 4779 // | // constructor, properties, and methods go here 4780 // | // ... 4781 // | }); 4782 // | var MyDiamond = declare([MyClass1, MyClass2], { 4783 // | // constructor, properties, and methods go here 4784 // | // ... 4785 // | }); 4786 // 4787 // example: 4788 // | var F = function(){ console.log("raw constructor"); }; 4789 // | F.prototype.method = function(){ 4790 // | console.log("raw method"); 4791 // | }; 4792 // | var A = declare(F, { 4793 // | constructor: function(){ 4794 // | console.log("A.constructor"); 4795 // | }, 4796 // | method: function(){ 4797 // | console.log("before calling F.method..."); 4798 // | this.inherited(arguments); 4799 // | console.log("...back in A"); 4800 // | } 4801 // | }); 4802 // | new A().method(); 4803 // | // will print: 4804 // | // raw constructor 4805 // | // A.constructor 4806 // | // before calling F.method... 4807 // | // raw method 4808 // | // ...back in A 4809 // 4810 // example: 4811 // | var A = declare(null, { 4812 // | "-chains-": { 4813 // | destroy: "before" 4814 // | } 4815 // | }); 4816 // | var B = declare(A, { 4817 // | constructor: function(){ 4818 // | console.log("B.constructor"); 4819 // | }, 4820 // | destroy: function(){ 4821 // | console.log("B.destroy"); 4822 // | } 4823 // | }); 4824 // | var C = declare(B, { 4825 // | constructor: function(){ 4826 // | console.log("C.constructor"); 4827 // | }, 4828 // | destroy: function(){ 4829 // | console.log("C.destroy"); 4830 // | } 4831 // | }); 4832 // | new C().destroy(); 4833 // | // prints: 4834 // | // B.constructor 4835 // | // C.constructor 4836 // | // C.destroy 4837 // | // B.destroy 4838 // 4839 // example: 4840 // | var A = declare(null, { 4841 // | "-chains-": { 4842 // | constructor: "manual" 4843 // | } 4844 // | }); 4845 // | var B = declare(A, { 4846 // | constructor: function(){ 4847 // | // ... 4848 // | // call the base constructor with new parameters 4849 // | this.inherited(arguments, [1, 2, 3]); 4850 // | // ... 4851 // | } 4852 // | }); 4853 // 4854 // example: 4855 // | var A = declare(null, { 4856 // | "-chains-": { 4857 // | m1: "before" 4858 // | }, 4859 // | m1: function(){ 4860 // | console.log("A.m1"); 4861 // | }, 4862 // | m2: function(){ 4863 // | console.log("A.m2"); 4864 // | } 4865 // | }); 4866 // | var B = declare(A, { 4867 // | "-chains-": { 4868 // | m2: "after" 4869 // | }, 4870 // | m1: function(){ 4871 // | console.log("B.m1"); 4872 // | }, 4873 // | m2: function(){ 4874 // | console.log("B.m2"); 4875 // | } 4876 // | }); 4877 // | var x = new B(); 4878 // | x.m1(); 4879 // | // prints: 4880 // | // B.m1 4881 // | // A.m1 4882 // | x.m2(); 4883 // | // prints: 4884 // | // A.m2 4885 // | // B.m2 4886 4887 // crack parameters 4888 if(typeof className != "string"){ 4889 props = superclass; 4890 superclass = className; 4891 className = ""; 4892 } 4893 props = props || {}; 4894 4895 var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass; 4896 4897 // build a prototype 4898 if(opts.call(superclass) == "[object Array]"){ 4899 // C3 MRO 4900 bases = c3mro(superclass, className); 4901 t = bases[0];
4902 mixins = bases.length - t; 4903 superclass = bases[mixins]; 4904 }else{ 4905 bases = [0]; 4906 if(superclass){ 4907 if(opts.call(superclass) == "[object Function]"){ 4908 t = superclass._meta; 4909 bases = bases.concat(t ? t.bases : superclass); 4910 }else{ 4911 err("base class is not a callable constructor.", className); 4912 } 4913 }else if(superclass !== null){ 4914 err("unknown base class. Did you use dojo.require to pull it in?", className); 4915 } 4916 } 4917 if(superclass){ 4918 for(i = mixins - 1;; --i){ 4919 proto = forceNew(superclass); 4920 if(!i){ 4921 // stop if nothing to add (the last base) 4922 break; 4923 } 4924 // mix in properties 4925 t = bases[i]; 4926 (t._meta ? mixOwn : mix)(proto, t.prototype); 4927 // chain in new constructor 4928 ctor = new Function; 4929 ctor.superclass = superclass; 4930 ctor.prototype = proto; 4931 superclass = proto.constructor = ctor; 4932 } 4933 }else{ 4934 proto = {}; 4935 } 4936 // add all properties 4937 declare.safeMixin(proto, props); 4938 // add constructor 4939 t = props.constructor; 4940 if(t !== op.constructor){ 4941 t.nom = cname; 4942 proto.constructor = t; 4943 } 4944 4945 // collect chains and flags 4946 for(i = mixins - 1; i; --i){ // intentional assignment 4947 t = bases[i]._meta; 4948 if(t && t.chains){ 4949 chains = mix(chains || {}, t.chains); 4950 } 4951 } 4952 if(proto["-chains-"]){ 4953 chains = mix(chains || {}, proto["-chains-"]); 4954 } 4955 4956 // build ctor 4957 t = !chains || !chains.hasOwnProperty(cname); 4958 bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) : 4959 (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t)); 4960 4961 // add meta information to the constructor 4962 ctor._meta = {bases: bases, hidden: props, chains: chains, 4963 parents: parents, ctor: props.constructor}; 4964 ctor.superclass = superclass && superclass.prototype; 4965 ctor.extend = extend; 4966 ctor.createSubclass = createSubclass; 4967 ctor.prototype = proto; 4968 proto.constructor = ctor; 4969 4970 // add "standard" methods to the prototype 4971 proto.getInherited = getInherited; 4972 proto.isInstanceOf = isInstanceOf; 4973 proto.inherited = inheritedImpl; 4974 proto.__inherited = inherited; 4975 4976 // add name if specified 4977 if(className){ 4978 proto.declaredClass = className; 4979 lang.setObject(className, ctor); 4980 } 4981 4982 // build chains and add them to the prototype 4983 if(chains){ 4984 for(name in chains){ 4985 if(proto[name] && typeof chains[name] == "string" && name != cname){ 4986 t = proto[name] = chain(name, bases, chains[name] === "after"); 4987 t.nom = name; 4988 } 4989 } 4990 } 4991 // chained methods do not return values 4992 // no need to chain "invisible" functions 4993 4994 return ctor; // Function 4995 } 4996 4997 /*===== 4998 declare.__DeclareCreatedObject = { 4999 // summary: 5000 // dojo/_base/declare() returns a constructor `C`. `new C()` returns an Object with the following 5001 // methods, in addition to the methods and properties specified via the arguments passed to declare(). 5002 5003 inherited: function(name, args, newArgs){ 5004 // summary: 5005 // Calls a super method. 5006 // name: String? 5007 // The optional method name. Should be the same as the caller's 5008 // name. Usually "name" is specified in complex dynamic cases, when 5009 // the calling method was dynamically added, undecorated by 5010 // declare(), and it cannot be determined. 5011 // args: Arguments 5012 // The caller supply this argument, which should be the original 5013 // "arguments". 5014 // newArgs: Object? 5015 // If "true", the found function will be returned without 5016 // executing it. 5017 // If Array, it will be used to call a super method. Otherwise 5018 // "args" will be used. 5019 // returns: 5020 // Whatever is returned by a super method, or a super method itself, 5021 // if "true" was specified as newArgs. 5022 // description: 5023 // This method is used inside method of classes produced with 5024 // declare() to call a super method (next in the chain). It is 5025 // used for manually controlled chaining. Consider using the regular 5026 // chaining, because it is faster. Use "this.inherited()" only in 5027 // complex cases. 5028 // 5029 // This method cannot me called from automatically chained 5030 // constructors including the case of a special (legacy) 5031 // constructor chaining. It cannot be called from chained methods. 5032 // 5033 // If "this.inherited()" cannot find the next-in-chain method, it 5034 // does nothing and returns "undefined". The last method in chain 5035 // can be a default method implemented in Object, which will be 5036 // called last. 5037 // 5038 // If "name" is specified, it is assumed that the method that 5039 // received "args" is the parent method for this call. It is looked 5040 // up in the chain list and if it is found the next-in-chain method 5041 // is called. If it is not found, the first-in-chain method is 5042 // called. 5043 // 5044 // If "name" is not specified, it will be derived from the calling 5045 // method (using a methoid property "nom"). 5046 // 5047 // example: 5048 // | var B = declare(A, { 5049 // | method1: function(a, b, c){ 5050 // | this.inherited(arguments); 5051 // | }, 5052 // | method2: function(a, b){ 5053 // | return this.inherited(arguments, [a + b]); 5054 // | } 5055 // | }); 5056 // | // next method is not in the chain list because it is added 5057 // | // manually after the class was created. 5058 // | B.prototype.method3 = function(){ 5059 // | console.log("This is a dynamically-added method."); 5060 // | this.inherited("method3", arguments); 5061 // | }; 5062 // example: 5063 // | var B = declare(A, { 5064 // | method: function(a, b){ 5065 // | var super = this.inherited(arguments, true); 5066 // | // ... 5067 // | if(!super){ 5068 // | console.log("there is no super method"); 5069 // | return 0; 5070 // | } 5071 // | return super.apply(this, arguments); 5072 // | } 5073 // | }); 5074 return {}; // Object 5075 }, 5076 5077 getInherited: function(name, args){ 5078 // summary: 5079 // Returns a super method. 5080 // name: String?
5081 // The optional method name. Should be the same as the caller's 5082 // name. Usually "name" is specified in complex dynamic cases, when 5083 // the calling method was dynamically added, undecorated by 5084 // declare(), and it cannot be determined. 5085 // args: Arguments 5086 // The caller supply this argument, which should be the original 5087 // "arguments". 5088 // returns: 5089 // Returns a super method (Function) or "undefined". 5090 // description: 5091 // This method is a convenience method for "this.inherited()". 5092 // It uses the same algorithm but instead of executing a super 5093 // method, it returns it, or "undefined" if not found. 5094 // 5095 // example: 5096 // | var B = declare(A, { 5097 // | method: function(a, b){ 5098 // | var super = this.getInherited(arguments); 5099 // | // ... 5100 // | if(!super){ 5101 // | console.log("there is no super method"); 5102 // | return 0; 5103 // | } 5104 // | return super.apply(this, arguments); 5105 // | } 5106 // | }); 5107 return {}; // Object 5108 }, 5109 5110 isInstanceOf: function(cls){ 5111 // summary: 5112 // Checks the inheritance chain to see if it is inherited from this 5113 // class. 5114 // cls: Function 5115 // Class constructor. 5116 // returns: 5117 // "true", if this object is inherited from this class, "false" 5118 // otherwise. 5119 // description: 5120 // This method is used with instances of classes produced with 5121 // declare() to determine of they support a certain interface or 5122 // not. It models "instanceof" operator. 5123 // 5124 // example: 5125 // | var A = declare(null, { 5126 // | // constructor, properties, and methods go here 5127 // | // ... 5128 // | }); 5129 // | var B = declare(null, { 5130 // | // constructor, properties, and methods go here 5131 // | // ... 5132 // | }); 5133 // | var C = declare([A, B], { 5134 // | // constructor, properties, and methods go here 5135 // | // ... 5136 // | }); 5137 // | var D = declare(A, { 5138 // | // constructor, properties, and methods go here 5139 // | // ... 5140 // | }); 5141 // | 5142 // | var a = new A(), b = new B(), c = new C(), d = new D(); 5143 // | 5144 // | console.log(a.isInstanceOf(A)); // true 5145 // | console.log(b.isInstanceOf(A)); // false 5146 // | console.log(c.isInstanceOf(A)); // true 5147 // | console.log(d.isInstanceOf(A)); // true 5148 // | 5149 // | console.log(a.isInstanceOf(B)); // false 5150 // | console.log(b.isInstanceOf(B)); // true 5151 // | console.log(c.isInstanceOf(B)); // true 5152 // | console.log(d.isInstanceOf(B)); // false 5153 // | 5154 // | console.log(a.isInstanceOf(C)); // false 5155 // | console.log(b.isInstanceOf(C)); // false 5156 // | console.log(c.isInstanceOf(C)); // true 5157 // | console.log(d.isInstanceOf(C)); // false 5158 // | 5159 // | console.log(a.isInstanceOf(D)); // false 5160 // | console.log(b.isInstanceOf(D)); // false 5161 // | console.log(c.isInstanceOf(D)); // false 5162 // | console.log(d.isInstanceOf(D)); // true 5163 return {}; // Object 5164 }, 5165 5166 extend: function(source){ 5167 // summary: 5168 // Adds all properties and methods of source to constructor's 5169 // prototype, making them available to all instances created with 5170 // constructor. This method is specific to constructors created with 5171 // declare(). 5172 // source: Object 5173 // Source object which properties are going to be copied to the 5174 // constructor's prototype. 5175 // description: 5176 // Adds source properties to the constructor's prototype. It can 5177 // override existing properties. 5178 // 5179 // This method is similar to dojo.extend function, but it is specific 5180 // to constructors produced by declare(). It is implemented 5181 // using dojo.safeMixin, and it skips a constructor property, 5182 // and properly decorates copied functions. 5183 // 5184 // example: 5185 // | var A = declare(null, { 5186 // | m1: function(){}, 5187 // | s1: "Popokatepetl" 5188 // | }); 5189 // | A.extend({ 5190 // | m1: function(){}, 5191 // | m2: function(){}, 5192 // | f1: true, 5193 // | d1: 42 5194 // | }); 5195 }, 5196 5197 createSubclass: function(mixins, props){ 5198 // summary: 5199 // Create a subclass of the declared class from a list of base classes. 5200 // mixins: Function[] 5201 // Specifies a list of bases (the left-most one is the most deepest 5202 // base). 5203 // props: Object? 5204 // An optional object whose properties are copied to the created prototype. 5205 // returns: dojo/_base/declare.__DeclareCreatedObject 5206 // New constructor function. 5207 // description: 5208 // Create a constructor using a compact notation for inheritance and 5209 // prototype extension. 5210 // 5211 // Mixin ancestors provide a type of multiple inheritance. 5212 // Prototypes of mixin ancestors are copied to the new class: 5213 // changes to mixin prototypes will not affect classes to which 5214 // they have been mixed in. 5215 // 5216 // example: 5217 // | var A = declare(null, { 5218 // | m1: function(){}, 5219 // | s1: "bar" 5220 // | }); 5221 // | var B = declare(null, { 5222 // | m2: function(){}, 5223 // | s2: "foo" 5224 // | }); 5225 // | var C = declare(null, { 5226 // | });
5227 // | var D1 = A.createSubclass([B, C], { 5228 // | m1: function(){}, 5229 // | d1: 42 5230 // | }); 5231 // | var d1 = new D1(); 5232 // | 5233 // | // this is equivalent to: 5234 // | var D2 = declare([A, B, C], { 5235 // | m1: function(){}, 5236 // | d1: 42 5237 // | }); 5238 // | var d2 = new D2(); 5239 } 5240 }; 5241 =====*/ 5242 5243 // For back-compat, remove for 2.0 5244 dojo.safeMixin = declare.safeMixin = safeMixin; 5245 dojo.declare = declare; 5246 5247 return declare; 5248}); 5249 5250}, 5251'dojo/_base/connect':function(){ 5252define(["./kernel", "../on", "../topic", "../aspect", "./event", "../mouse", "./sniff", "./lang", "../keys"], function(dojo, on, hub, aspect, eventModule, mouse, has, lang){ 5253// module: 5254// dojo/_base/connect 5255 5256has.add("events-keypress-typed", function(){ // keypresses should only occur a printable character is hit 5257 var testKeyEvent = {charCode: 0}; 5258 try{ 5259 testKeyEvent = document.createEvent("KeyboardEvent"); 5260 (testKeyEvent.initKeyboardEvent || testKeyEvent.initKeyEvent).call(testKeyEvent, "keypress", true, true, null, false, false, false, false, 9, 3); 5261 }catch(e){} 5262 return testKeyEvent.charCode == 0 && !has("opera"); 5263}); 5264 5265function connect_(obj, event, context, method, dontFix){ 5266 method = lang.hitch(context, method); 5267 if(!obj || !(obj.addEventListener || obj.attachEvent)){ 5268 // it is a not a DOM node and we are using the dojo.connect style of treating a 5269 // method like an event, must go right to aspect 5270 return aspect.after(obj || dojo.global, event, method, true); 5271 } 5272 if(typeof event == "string" && event.substring(0, 2) == "on"){ 5273 event = event.substring(2); 5274 } 5275 if(!obj){ 5276 obj = dojo.global; 5277 } 5278 if(!dontFix){ 5279 switch(event){ 5280 // dojo.connect has special handling for these event types 5281 case "keypress": 5282 event = keypress; 5283 break; 5284 case "mouseenter": 5285 event = mouse.enter; 5286 break; 5287 case "mouseleave": 5288 event = mouse.leave; 5289 break; 5290 } 5291 } 5292 return on(obj, event, method, dontFix); 5293} 5294 5295var _punctMap = { 5296 106:42, 5297 111:47, 5298 186:59, 5299 187:43, 5300 188:44, 5301 189:45, 5302 190:46, 5303 191:47, 5304 192:96, 5305 219:91, 5306 220:92, 5307 221:93, 5308 222:39, 5309 229:113 5310}; 5311var evtCopyKey = has("mac") ? "metaKey" : "ctrlKey"; 5312 5313 5314var _synthesizeEvent = function(evt, props){ 5315 var faux = lang.mixin({}, evt, props); 5316 setKeyChar(faux); 5317 // FIXME: would prefer to use lang.hitch: lang.hitch(evt, evt.preventDefault); 5318 // but it throws an error when preventDefault is invoked on Safari 5319 // does Event.preventDefault not support "apply" on Safari? 5320 faux.preventDefault = function(){ evt.preventDefault(); }; 5321 faux.stopPropagation = function(){ evt.stopPropagation(); }; 5322 return faux; 5323};
5324function setKeyChar(evt){ 5325 evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : ''; 5326 evt.charOrCode = evt.keyChar || evt.keyCode; 5327} 5328var keypress; 5329if(has("events-keypress-typed")){ 5330 // this emulates Firefox's keypress behavior where every keydown can correspond to a keypress 5331 var _trySetKeyCode = function(e, code){ 5332 try{ 5333 // squelch errors when keyCode is read-only 5334 // (e.g. if keyCode is ctrl or shift) 5335 return (e.keyCode = code); 5336 }catch(e){ 5337 return 0; 5338 } 5339 }; 5340 keypress = function(object, listener){ 5341 var keydownSignal = on(object, "keydown", function(evt){ 5342 // munge key/charCode 5343 var k=evt.keyCode; 5344 // These are Windows Virtual Key Codes 5345 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp 5346 var unprintable = (k!=13) && k!=32 && (k!=27||!has("ie")) && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222) && k!=229; 5347 // synthesize keypress for most unprintables and CTRL-keys 5348 if(unprintable||evt.ctrlKey){ 5349 var c = unprintable ? 0 : k; 5350 if(evt.ctrlKey){ 5351 if(k==3 || k==13){ 5352 return listener.call(evt.currentTarget, evt); // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively 5353 }else if(c>95 && c<106){ 5354 c -= 48; // map CTRL-[numpad 0-9] to ASCII 5355 }else if((!evt.shiftKey)&&(c>=65&&c<=90)){ 5356 c += 32; // map CTRL-[A-Z] to lowercase 5357 }else{ 5358 c = _punctMap[c] || c; // map other problematic CTRL combinations to ASCII 5359 } 5360 } 5361 // simulate a keypress event 5362 var faux = _synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c}); 5363 listener.call(evt.currentTarget, faux); 5364 if(has("ie")){ 5365 _trySetKeyCode(evt, faux.keyCode); 5366 } 5367 } 5368 }); 5369 var keypressSignal = on(object, "keypress", function(evt){ 5370 var c = evt.charCode; 5371 c = c>=32 ? c : 0; 5372 evt = _synthesizeEvent(evt, {charCode: c, faux: true}); 5373 return listener.call(this, evt); 5374 }); 5375 return { 5376 remove: function(){ 5377 keydownSignal.remove(); 5378 keypressSignal.remove(); 5379 } 5380 }; 5381 }; 5382}else{ 5383 if(has("opera")){ 5384 keypress = function(object, listener){ 5385 return on(object, "keypress", function(evt){ 5386 var c = evt.which; 5387 if(c==3){ 5388 c=99; // Mozilla maps CTRL-BREAK to CTRL-c 5389 } 5390 // can't trap some keys at all, like INSERT and DELETE 5391 // there is no differentiating info between DELETE and ".", or INSERT and "-" 5392 c = c<32 && !evt.shiftKey ? 0 : c; 5393 if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){ 5394 // lowercase CTRL-[A-Z] keys 5395 c += 32; 5396 } 5397 return listener.call(this, _synthesizeEvent(evt, { charCode: c })); 5398 }); 5399 }; 5400 }else{ 5401 keypress = function(object, listener){ 5402 return on(object, "keypress", function(evt){ 5403 setKeyChar(evt); 5404 return listener.call(this, evt); 5405 }); 5406 }; 5407 } 5408} 5409 5410var connect = { 5411 // summary: 5412 // This module defines the dojo.connect API. 5413 // This modules also provides keyboard event handling helpers. 5414 // This module exports an extension event for emulating Firefox's keypress handling. 5415 // However, this extension event exists primarily for backwards compatibility and 5416 // is not recommended. WebKit and IE uses an alternate keypress handling (only 5417 // firing for printable characters, to distinguish from keydown events), and most 5418 // consider the WebKit/IE behavior more desirable. 5419 5420 _keypress:keypress, 5421 5422 connect:function(obj, event, context, method, dontFix){ 5423 // summary: 5424 // `dojo.connect` is a deprecated event handling and delegation method in 5425 // Dojo. It allows one function to "listen in" on the execution of 5426 // any other, triggering the second whenever the first is called. Many 5427 // listeners may be attached to a function, and source functions may 5428 // be either regular function calls or DOM events. 5429 // 5430 // description: 5431 // Connects listeners to actions, so that after event fires, a 5432 // listener is called with the same arguments passed to the original 5433 // function. 5434 // 5435 // Since `dojo.connect` allows the source of events to be either a 5436 // "regular" JavaScript function or a DOM event, it provides a uniform 5437 // interface for listening to all the types of events that an 5438 // application is likely to deal with though a single, unified 5439 // interface. DOM programmers may want to think of it as 5440 // "addEventListener for everything and anything". 5441 // 5442 // When setting up a connection, the `event` parameter must be a 5443 // string that is the name of the method/event to be listened for. If 5444 // `obj` is null, `kernel.global` is assumed, meaning that connections 5445 // to global methods are supported but also that you may inadvertently 5446 // connect to a global by passing an incorrect object name or invalid 5447 // reference. 5448 // 5449 // `dojo.connect` generally is forgiving. If you pass the name of a 5450 // function or method that does not yet exist on `obj`, connect will 5451 // not fail, but will instead set up a stub method. Similarly, null
5452 // arguments may simply be omitted such that fewer than 4 arguments 5453 // may be required to set up a connection See the examples for details. 5454 // 5455 // The return value is a handle that is needed to 5456 // remove this connection with `dojo.disconnect`. 5457 // 5458 // obj: Object? 5459 // The source object for the event function. 5460 // Defaults to `kernel.global` if null. 5461 // If obj is a DOM node, the connection is delegated 5462 // to the DOM event manager (unless dontFix is true). 5463 // 5464 // event: String 5465 // String name of the event function in obj. 5466 // I.e. identifies a property `obj[event]`. 5467 // 5468 // context: Object|null 5469 // The object that method will receive as "this". 5470 // 5471 // If context is null and method is a function, then method 5472 // inherits the context of event. 5473 // 5474 // If method is a string then context must be the source 5475 // object object for method (context[method]). If context is null, 5476 // kernel.global is used. 5477 // 5478 // method: String|Function 5479 // A function reference, or name of a function in context. 5480 // The function identified by method fires after event does. 5481 // method receives the same arguments as the event. 5482 // See context argument comments for information on method's scope. 5483 // 5484 // dontFix: Boolean? 5485 // If obj is a DOM node, set dontFix to true to prevent delegation 5486 // of this connection to the DOM event manager. 5487 // 5488 // example: 5489 // When obj.onchange(), do ui.update(): 5490 // | dojo.connect(obj, "onchange", ui, "update"); 5491 // | dojo.connect(obj, "onchange", ui, ui.update); // same 5492 // 5493 // example: 5494 // Using return value for disconnect: 5495 // | var link = dojo.connect(obj, "onchange", ui, "update"); 5496 // | ... 5497 // | dojo.disconnect(link); 5498 // 5499 // example: 5500 // When onglobalevent executes, watcher.handler is invoked: 5501 // | dojo.connect(null, "onglobalevent", watcher, "handler"); 5502 // 5503 // example: 5504 // When ob.onCustomEvent executes, customEventHandler is invoked: 5505 // | dojo.connect(ob, "onCustomEvent", null, "customEventHandler"); 5506 // | dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same 5507 // 5508 // example: 5509 // When ob.onCustomEvent executes, customEventHandler is invoked 5510 // with the same scope (this): 5511 // | dojo.connect(ob, "onCustomEvent", null, customEventHandler); 5512 // | dojo.connect(ob, "onCustomEvent", customEventHandler); // same 5513 // 5514 // example: 5515 // When globalEvent executes, globalHandler is invoked 5516 // with the same scope (this): 5517 // | dojo.connect(null, "globalEvent", null, globalHandler); 5518 // | dojo.connect("globalEvent", globalHandler); // same 5519 5520 // normalize arguments 5521 var a=arguments, args=[], i=0; 5522 // if a[0] is a String, obj was omitted 5523 args.push(typeof a[0] == "string" ? null : a[i++], a[i++]); 5524 // if the arg-after-next is a String or Function, context was NOT omitted 5525 var a1 = a[i+1]; 5526 args.push(typeof a1 == "string" || typeof a1 == "function" ? a[i++] : null, a[i++]); 5527 // absorb any additional arguments 5528 for(var l=a.length; i<l; i++){ args.push(a[i]); } 5529 return connect_.apply(this, args); 5530 }, 5531 5532 disconnect:function(handle){ 5533 // summary: 5534 // Remove a link created by dojo.connect. 5535 // description: 5536 // Removes the connection between event and the method referenced by handle. 5537 // handle: Handle 5538 // the return value of the dojo.connect call that created the connection. 5539 5540 if(handle){ 5541 handle.remove(); 5542 } 5543 }, 5544 5545 subscribe:function(topic, context, method){ 5546 // summary: 5547 // Attach a listener to a named topic. The listener function is invoked whenever the 5548 // named topic is published (see: dojo.publish). 5549 // Returns a handle which is needed to unsubscribe this listener. 5550 // topic: String 5551 // The topic to which to subscribe. 5552 // context: Object? 5553 // Scope in which method will be invoked, or null for default scope. 5554 // method: String|Function 5555 // The name of a function in context, or a function reference. This is the function that 5556 // is invoked when topic is published. 5557 // example: 5558 // | dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); }); 5559 // | dojo.publish("alerts", [ "read this", "hello world" ]); 5560 return hub.subscribe(topic, lang.hitch(context, method)); 5561 }, 5562 5563 publish:function(topic, args){ 5564 // summary: 5565 // Invoke all listener method subscribed to topic. 5566 // topic: String 5567 // The name of the topic to publish. 5568 // args: Array? 5569 // An array of arguments. The arguments will be applied 5570 // to each topic subscriber (as first class parameters, via apply). 5571 // example: 5572 // | dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); }; 5573 // | dojo.publish("alerts", [ "read this", "hello world" ]); 5574 return hub.publish.apply(hub, [topic].concat(args)); 5575 }, 5576 5577 connectPublisher:function(topic, obj, event){ 5578 // summary: 5579 // Ensure that every time obj.event() is called, a message is published 5580 // on the topic. Returns a handle which can be passed to 5581 // dojo.disconnect() to disable subsequent automatic publication on 5582 // the topic. 5583 // topic: String 5584 // The name of the topic to publish. 5585 // obj: Object? 5586 // The source object for the event function. Defaults to kernel.global 5587 // if null. 5588 // event: String 5589 // The name of the event function in obj. 5590 // I.e. identifies a property obj[event]. 5591 // example: 5592 // | dojo.connectPublisher("/ajax/start", dojo, "xhrGet"); 5593 var pf = function(){ connect.publish(topic, arguments); }; 5594 return event ? connect.connect(obj, event, pf) : connect.connect(obj, pf); //Handle 5595 }, 5596 5597 isCopyKey: function(e){
5598 // summary: 5599 // Checks an event for the copy key (meta on Mac, and ctrl anywhere else) 5600 // e: Event 5601 // Event object to examine 5602 return e[evtCopyKey]; // Boolean 5603 } 5604}; 5605 5606connect.unsubscribe = connect.disconnect; 5607/*===== 5608 connect.unsubscribe = function(handle){ 5609 // summary: 5610 // Remove a topic listener. 5611 // handle: Handle 5612 // The handle returned from a call to subscribe. 5613 // example: 5614 // | var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); }; 5615 // | ... 5616 // | dojo.unsubscribe(alerter); 5617 }; 5618 =====*/ 5619 5620 1 && lang.mixin(dojo, connect); 5621return connect; 5622 5623}); 5624 5625 5626 5627}, 5628'dojo/on':function(){ 5629define(["./has!dom-addeventlistener?:./aspect", "./_base/kernel", "./sniff"], function(aspect, dojo, has){ 5630 5631 "use strict"; 5632 if( 1 ){ // check to make sure we are in a browser, this module should work anywhere 5633 var major = window.ScriptEngineMajorVersion; 5634 has.add("jscript", major && (major() + ScriptEngineMinorVersion() / 10)); 5635 has.add("event-orientationchange", has("touch") && !has("android")); // TODO: how do we detect this? 5636 has.add("event-stopimmediatepropagation", window.Event && !!window.Event.prototype && !!window.Event.prototype.stopImmediatePropagation); 5637 has.add("event-focusin", function(global, doc, element){ 5638 return 'onfocusin' in element; 5639 }); 5640 5641 if(has("touch")){ 5642 has.add("touch-can-modify-event-delegate", function(){ 5643 // This feature test checks whether deleting a property of an event delegate works 5644 // for a touch-enabled device. If it works, event delegation can be used as fallback 5645 // for browsers such as Safari in older iOS where deleting properties of the original 5646 // event does not work. 5647 var EventDelegate = function(){}; 5648 EventDelegate.prototype = 5649 document.createEvent("MouseEvents"); // original event 5650 // Attempt to modify a property of an event delegate and check if 5651 // it succeeds. Depending on browsers and on whether dojo/on's 5652 // strict mode is stripped in a Dojo build, there are 3 known behaviors: 5653 // it may either succeed, or raise an error, or fail to set the property 5654 // without raising an error. 5655 try{ 5656 var eventDelegate = new EventDelegate; 5657 eventDelegate.target = null; 5658 return eventDelegate.target === null; 5659 }catch(e){ 5660 return false; // cannot use event delegation 5661 } 5662 }); 5663 } 5664 } 5665 var on = function(target, type, listener, dontFix){ 5666 // summary: 5667 // A function that provides core event listening functionality. With this function 5668 // you can provide a target, event type, and listener to be notified of 5669 // future matching events that are fired. 5670 // target: Element|Object 5671 // This is the target object or DOM element that to receive events from 5672 // type: String|Function 5673 // This is the name of the event to listen for or an extension event type. 5674 // listener: Function 5675 // This is the function that should be called when the event fires. 5676 // returns: Object 5677 // An object with a remove() method that can be used to stop listening for this 5678 // event. 5679 // description: 5680 // To listen for "click" events on a button node, we can do: 5681 // | define(["dojo/on"], function(on){ 5682 // | on(button, "click", clickHandler); 5683 // | ... 5684 // Evented JavaScript objects can also have their own events. 5685 // | var obj = new Evented; 5686 // | on(obj, "foo", fooHandler); 5687 // And then we could publish a "foo" event: 5688 // | on.emit(obj, "foo", {key: "value"}); 5689 // We can use extension events as well. For example, you could listen for a tap gesture: 5690 // | define(["dojo/on", "dojo/gesture/tap", function(on, tap){ 5691 // | on(button, tap, tapHandler); 5692 // | ... 5693 // which would trigger fooHandler. Note that for a simple object this is equivalent to calling: 5694 // | obj.onfoo({key:"value"}); 5695 // If you use on.emit on a DOM node, it will use native event dispatching when possible. 5696 5697 if(typeof target.on == "function" && typeof type != "function" && !target.nodeType){ 5698 // delegate to the target's on() method, so it can handle it's own listening if it wants (unless it 5699 // is DOM node and we may be dealing with jQuery or Prototype's incompatible addition to the 5700 // Element prototype 5701 return target.on(type, listener); 5702 }
vendor: 17,232 bytes, lines 5703-6125
5703 // delegate to main listener code 5704 return on.parse(target, type, listener, addListener, dontFix, this); 5705 }; 5706 on.pausable = function(target, type, listener, dontFix){ 5707 // summary: 5708 // This function acts the same as on(), but with pausable functionality. The 5709 // returned signal object has pause() and resume() functions. Calling the 5710 // pause() method will cause the listener to not be called for future events. Calling the 5711 // resume() method will cause the listener to again be called for future events. 5712 var paused; 5713 var signal = on(target, type, function(){ 5714 if(!paused){ 5715 return listener.apply(this, arguments); 5716 } 5717 }, dontFix); 5718 signal.pause = function(){ 5719 paused = true; 5720 }; 5721 signal.resume = function(){ 5722 paused = false; 5723 }; 5724 return signal; 5725 }; 5726 on.once = function(target, type, listener, dontFix){ 5727 // summary: 5728 // This function acts the same as on(), but will only call the listener once. The 5729 // listener will be called for the first 5730 // event that takes place and then listener will automatically be removed. 5731 var signal = on(target, type, function(){ 5732 // remove this listener 5733 signal.remove(); 5734 // proceed to call the listener 5735 return listener.apply(this, arguments); 5736 }); 5737 return signal; 5738 }; 5739 on.parse = function(target, type, listener, addListener, dontFix, matchesTarget){ 5740 if(type.call){ 5741 // event handler function 5742 // on(node, touch.press, touchListener); 5743 return type.call(matchesTarget, target, listener); 5744 } 5745 5746 if(type instanceof Array){ 5747 // allow an array of event names (or event handler functions) 5748 events = type; 5749 }else if(type.indexOf(",") > -1){ 5750 // we allow comma delimited event names, so you can register for multiple events at once 5751 var events = type.split(/\s*,\s*/); 5752 } 5753 if(events){ 5754 var handles = []; 5755 var i = 0; 5756 var eventName; 5757 while(eventName = events[i++]){ 5758 handles.push(on.parse(target, eventName, listener, addListener, dontFix, matchesTarget)); 5759 } 5760 handles.remove = function(){ 5761 for(var i = 0; i < handles.length; i++){ 5762 handles[i].remove(); 5763 } 5764 }; 5765 return handles; 5766 } 5767 return addListener(target, type, listener, dontFix, matchesTarget); 5768 }; 5769 var touchEvents = /^touch/; 5770 function addListener(target, type, listener, dontFix, matchesTarget){ 5771 // event delegation: 5772 var selector = type.match(/(.*):(.*)/); 5773 // if we have a selector:event, the last one is interpreted as an event, and we use event delegation 5774 if(selector){ 5775 type = selector[2]; 5776 selector = selector[1]; 5777 // create the extension event for selectors and directly call it 5778 return on.selector(selector, type).call(matchesTarget, target, listener); 5779 } 5780 // test to see if it a touch event right now, so we don't have to do it every time it fires 5781 if(has("touch")){ 5782 if(touchEvents.test(type)){ 5783 // touch event, fix it 5784 listener = fixTouchListener(listener); 5785 } 5786 if(!has("event-orientationchange") && (type == "orientationchange")){ 5787 //"orientationchange" not supported <= Android 2.1, 5788 //but works through "resize" on window 5789 type = "resize"; 5790 target = window; 5791 listener = fixTouchListener(listener); 5792 } 5793 } 5794 if(addStopImmediate){ 5795 // add stopImmediatePropagation if it doesn't exist 5796 listener = addStopImmediate(listener); 5797 } 5798 // normal path, the target is |this| 5799 if(target.addEventListener){ 5800 // the target has addEventListener, which should be used if available (might or might not be a node, non-nodes can implement this method as well) 5801 // check for capture conversions 5802 var capture = type in captures, 5803 adjustedType = capture ? captures[type] : type; 5804 target.addEventListener(adjustedType, listener, capture); 5805 // create and return the signal 5806 return { 5807 remove: function(){ 5808 target.removeEventListener(adjustedType, listener, capture); 5809 } 5810 }; 5811 } 5812 type = "on" + type; 5813 if(fixAttach && target.attachEvent){ 5814 return fixAttach(target, type, listener); 5815 } 5816 throw new Error("Target must be an event emitter"); 5817 } 5818 on.matches = function(node, selector, context, children, matchesTarget) { 5819 // summary: 5820 // Check if a node match the current selector within the constraint of a context 5821 // node: DOMNode 5822 // The node that originate the event 5823 // selector: String 5824 // The selector to check against 5825 // context: DOMNode 5826 // The context to search in. 5827 // children: Boolean 5828 // Indicates if children elements of the selector should be allowed. This defaults to 5829 // true 5830 // matchesTarget: Object|dojo/query? 5831 // An object with a property "matches" as a function. Default is dojo/query. 5832 // Matching DOMNodes will be done against this function 5833 // The function must return a Boolean. 5834 // It will have 3 arguments: "node", "selector" and "context" 5835 // True is expected if "node" is matching the current "selector" in the passed "context" 5836 // returns: DOMNode? 5837 // The matching node, if any. Else you get false 5838 5839 // see if we have a valid matchesTarget or default to dojo/query 5840 matchesTarget = matchesTarget && matchesTarget.matches ? matchesTarget : dojo.query; 5841 children = children !== false; 5842 // there is a selector, so make sure it matches 5843 if(node.nodeType != 1){ 5844 // text node will fail in native match selector 5845 node = node.parentNode; 5846 } 5847 while(!matchesTarget.matches(node, selector, context)){ 5848 if(node == context || children === false || !(node = node.parentNode) || node.nodeType != 1){ // intentional assignment 5849 return false; 5850 } 5851 } 5852 return node; 5853 } 5854 on.selector = function(selector, eventType, children){ 5855 // summary: 5856 // Creates a new extension event with event delegation. This is based on 5857 // the provided event type (can be extension event) that 5858 // only calls the listener when the CSS selector matches the target of the event. 5859 // 5860 // The application must require() an appropriate level of dojo/query to handle the selector. 5861 // selector: 5862 // The CSS selector to use for filter events and determine the |this| of the event listener. 5863 // eventType: 5864 // The event to listen for 5865 // children: 5866 // Indicates if children elements of the selector should be allowed. This defaults to 5867 // true 5868 // example: 5869 // | require(["dojo/on", "dojo/mouse", "dojo/query!css2"], function(on, mouse){ 5870 // | on(node, on.selector(".my-class", mouse.enter), handlerForMyHover); 5871 return function(target, listener){ 5872 // if the selector is function, use it to select the node, otherwise use the matches method 5873 var matchesTarget = typeof selector == "function" ? {matches: selector} : this, 5874 bubble = eventType.bubble; 5875 function select(eventTarget){ 5876 return on.matches(eventTarget, selector, target, children, matchesTarget); 5877 } 5878 if(bubble){ 5879 // the event type doesn't naturally bubble, but has a bubbling form, use that, and give it the selector so it can perform the select itself 5880 return on(target, bubble(select), listener); 5881 } 5882 // standard event delegation 5883 return on(target, eventType, function(event){ 5884 // call select to see if we match 5885 var eventTarget = select(event.target); 5886 // if it matches we call the listener 5887 if (eventTarget) { 5888 return listener.call(eventTarget, event); 5889 } 5890 }); 5891 }; 5892 }; 5893 5894 function syntheticPreventDefault(){ 5895 this.cancelable = false; 5896 this.defaultPrevented = true; 5897 } 5898 function syntheticStopPropagation(){ 5899 this.bubbles = false; 5900 } 5901 var slice = [].slice, 5902 syntheticDispatch = on.emit = function(target, type, event){ 5903 // summary: 5904 // Fires an event on the target object. 5905 // target: 5906 // The target object to fire the event on. This can be a DOM element or a plain 5907 // JS object. If the target is a DOM element, native event emitting mechanisms 5908 // are used when possible. 5909 // type: 5910 // The event type name. You can emulate standard native events like "click" and 5911 // "mouseover" or create custom events like "open" or "finish". 5912 // event: 5913 // An object that provides the properties for the event. See https://developer.mozilla.org/en/DOM/event.initEvent 5914 // for some of the properties. These properties are copied to the event object. 5915 // Of particular importance are the cancelable and bubbles properties. The 5916 // cancelable property indicates whether or not the event has a default action 5917 // that can be cancelled. The event is cancelled by calling preventDefault() on 5918 // the event object. The bubbles property indicates whether or not the 5919 // event will bubble up the DOM tree. If bubbles is true, the event will be called 5920 // on the target and then each parent successively until the top of the tree 5921 // is reached or stopPropagation() is called. Both bubbles and cancelable 5922 // default to false. 5923 // returns: 5924 // If the event is cancelable and the event is not cancelled, 5925 // emit will return true. If the event is cancelable and the event is cancelled, 5926 // emit will return false. 5927 // details: 5928 // Note that this is designed to emit events for listeners registered through 5929 // dojo/on. It should actually work with any event listener except those 5930 // added through IE's attachEvent (IE8 and below's non-W3C event emitting 5931 // doesn't support custom event types). It should work with all events registered 5932 // through dojo/on. Also note that the emit method does do any default 5933 // action, it only returns a value to indicate if the default action should take 5934 // place. For example, emitting a keypress event would not cause a character 5935 // to appear in a textbox. 5936 // example: 5937 // To fire our own click event 5938 // | require(["dojo/on", "dojo/dom" 5939 // | ], function(on, dom){ 5940 // | on.emit(dom.byId("button"), "click", { 5941 // | cancelable: true, 5942 // | bubbles: true, 5943 // | screenX: 33, 5944 // | screenY: 44 5945 // | }); 5946 // We can also fire our own custom events: 5947 // | on.emit(dom.byId("slider"), "slide", { 5948 // | cancelable: true, 5949 // | bubbles: true, 5950 // | direction: "left-to-right" 5951 // | }); 5952 // | }); 5953 var args = slice.call(arguments, 2); 5954 var method = "on" + type; 5955 if("parentNode" in target){ 5956 // node (or node-like), create event controller methods 5957 var newEvent = args[0] = {}; 5958 for(var i in event){ 5959 newEvent[i] = event[i]; 5960 } 5961 newEvent.preventDefault = syntheticPreventDefault; 5962 newEvent.stopPropagation = syntheticStopPropagation; 5963 newEvent.target = target; 5964 newEvent.type = type; 5965 event = newEvent; 5966 } 5967 do{ 5968 // call any node which has a handler (note that ideally we would try/catch to simulate normal event propagation but that causes too much pain for debugging) 5969 target[method] && target[method].apply(target, args); 5970 // and then continue up the parent node chain if it is still bubbling (if started as bubbles and stopPropagation hasn't been called) 5971 }while(event && event.bubbles && (target = target.parentNode)); 5972 return event && event.cancelable && event; // if it is still true (was cancelable and was cancelled), return the event to indicate default action should happen 5973 }; 5974 var captures = has("event-focusin") ? {} : {focusin: "focus", focusout: "blur"}; 5975 if(!has("event-stopimmediatepropagation")){ 5976 var stopImmediatePropagation =function(){ 5977 this.immediatelyStopped = true; 5978 this.modified = true; // mark it as modified so the event will be cached in IE 5979 }; 5980 var addStopImmediate = function(listener){ 5981 return function(event){ 5982 if(!event.immediatelyStopped){// check to make sure it hasn't been stopped immediately 5983 event.stopImmediatePropagation = stopImmediatePropagation; 5984 return listener.apply(this, arguments); 5985 } 5986 }; 5987 } 5988 } 5989 if(has("dom-addeventlistener")){ 5990 // emitter that works with native event handling 5991 on.emit = function(target, type, event){ 5992 if(target.dispatchEvent && document.createEvent){ 5993 // use the native event emitting mechanism if it is available on the target object 5994 // create a generic event 5995 // we could create branch into the different types of event constructors, but 5996 // that would be a lot of extra code, with little benefit that I can see, seems 5997 // best to use the generic constructor and copy properties over, making it 5998 // easy to have events look like the ones created with specific initializers 5999 var ownerDocument = target.ownerDocument || document; 6000 var nativeEvent = ownerDocument.createEvent("HTMLEvents"); 6001 nativeEvent.initEvent(type, !!event.bubbles, !!event.cancelable); 6002 // and copy all our properties over 6003 for(var i in event){ 6004 if(!(i in nativeEvent)){ 6005 nativeEvent[i] = event[i]; 6006 } 6007 } 6008 return target.dispatchEvent(nativeEvent) && nativeEvent; 6009 } 6010 return syntheticDispatch.apply(on, arguments); // emit for a non-node 6011 }; 6012 }else{ 6013 // no addEventListener, basically old IE event normalization 6014 on._fixEvent = function(evt, sender){ 6015 // summary: 6016 // normalizes properties on the event object including event 6017 // bubbling methods, keystroke normalization, and x/y positions 6018 // evt: 6019 // native event object 6020 // sender: 6021 // node to treat as "currentTarget" 6022 if(!evt){ 6023 var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window; 6024 evt = w.event; 6025 } 6026 if(!evt){return evt;} 6027 try{ 6028 if(lastEvent && evt.type == lastEvent.type && evt.srcElement == lastEvent.target){ 6029 // should be same event, reuse event object (so it can be augmented); 6030 // accessing evt.srcElement rather than evt.target since evt.target not set on IE until fixup below 6031 evt = lastEvent; 6032 } 6033 }catch(e){ 6034 // will occur on IE on lastEvent.type reference if lastEvent points to a previous event that already 6035 // finished bubbling, but the setTimeout() to clear lastEvent hasn't fired yet 6036 } 6037 if(!evt.target){ // check to see if it has been fixed yet 6038 evt.target = evt.srcElement; 6039 evt.currentTarget = (sender || evt.srcElement); 6040 if(evt.type == "mouseover"){ 6041 evt.relatedTarget = evt.fromElement; 6042 } 6043 if(evt.type == "mouseout"){ 6044 evt.relatedTarget = evt.toElement; 6045 } 6046 if(!evt.stopPropagation){ 6047 evt.stopPropagation = stopPropagation; 6048 evt.preventDefault = preventDefault; 6049 } 6050 switch(evt.type){ 6051 case "keypress": 6052 var c = ("charCode" in evt ? evt.charCode : evt.keyCode); 6053 if (c==10){ 6054 // CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla 6055 c=0; 6056 evt.keyCode = 13; 6057 }else if(c==13||c==27){ 6058 c=0; // Mozilla considers ENTER and ESC non-printable 6059 }else if(c==3){ 6060 c=99; // Mozilla maps CTRL-BREAK to CTRL-c 6061 } 6062 // Mozilla sets keyCode to 0 when there is a charCode 6063 // but that stops the event on IE. 6064 evt.charCode = c; 6065 _setKeyChar(evt); 6066 break; 6067 } 6068 } 6069 return evt; 6070 }; 6071 var lastEvent, IESignal = function(handle){ 6072 this.handle = handle; 6073 }; 6074 IESignal.prototype.remove = function(){ 6075 delete _dojoIEListeners_[this.handle]; 6076 }; 6077 var fixListener = function(listener){ 6078 // this is a minimal function for closing on the previous listener with as few as variables as possible 6079 return function(evt){ 6080 evt = on._fixEvent(evt, this); 6081 var result = listener.call(this, evt); 6082 if(evt.modified){ 6083 // cache the last event and reuse it if we can 6084 if(!lastEvent){ 6085 setTimeout(function(){ 6086 lastEvent = null; 6087 }); 6088 } 6089 lastEvent = evt; 6090 } 6091 return result; 6092 }; 6093 }; 6094 var fixAttach = function(target, type, listener){ 6095 listener = fixListener(listener); 6096 if(((target.ownerDocument ? target.ownerDocument.parentWindow : target.parentWindow || target.window || window) != top || 6097 has("jscript") < 5.8) && 6098 !has("config-_allow_leaks")){ 6099 // IE will leak memory on certain handlers in frames (IE8 and earlier) and in unattached DOM nodes for JScript 5.7 and below. 6100 // Here we use global redirection to solve the memory leaks 6101 if(typeof _dojoIEListeners_ == "undefined"){ 6102 _dojoIEListeners_ = []; 6103 } 6104 var emitter = target[type]; 6105 if(!emitter || !emitter.listeners){ 6106 var oldListener = emitter; 6107 emitter = Function('event', 'var callee = arguments.callee; for(var i = 0; i<callee.listeners.length; i++){var listener = _dojoIEListeners_[callee.listeners[i]]; if(listener){listener.call(this,event);}}'); 6108 emitter.listeners = []; 6109 target[type] = emitter; 6110 emitter.global = this; 6111 if(oldListener){ 6112 emitter.listeners.push(_dojoIEListeners_.push(oldListener) - 1); 6113 } 6114 } 6115 var handle; 6116 emitter.listeners.push(handle = (emitter.global._dojoIEListeners_.push(listener) - 1)); 6117 return new IESignal(handle); 6118 } 6119 return aspect.after(target, type, listener, true); 6120 }; 6121 6122 var _setKeyChar = function(evt){ 6123 evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : ''; 6124 evt.charOrCode = evt.keyChar || evt.keyCode; // TODO: remove for 2.0 6125 };
6126 // Called in Event scope 6127 var stopPropagation = function(){ 6128 this.cancelBubble = true; 6129 }; 6130 var preventDefault = on._preventDefault = function(){ 6131 // Setting keyCode to 0 is the only way to prevent certain keypresses (namely 6132 // ctrl-combinations that correspond to menu accelerator keys). 6133 // Otoh, it prevents upstream listeners from getting this information 6134 // Try to split the difference here by clobbering keyCode only for ctrl 6135 // combinations. If you still need to access the key upstream, bubbledKeyCode is 6136 // provided as a workaround. 6137 this.bubbledKeyCode = this.keyCode; 6138 if(this.ctrlKey){ 6139 try{ 6140 // squelch errors when keyCode is read-only 6141 // (e.g. if keyCode is ctrl or shift) 6142 this.keyCode = 0; 6143 }catch(e){ 6144 } 6145 } 6146 this.defaultPrevented = true; 6147 this.returnValue = false; 6148 this.modified = true; // mark it as modified (for defaultPrevented flag) so the event will be cached in IE 6149 }; 6150 } 6151 if(has("touch")){ 6152 var EventDelegate = function(){}; 6153 var windowOrientation = window.orientation; 6154 var fixTouchListener = function(listener){ 6155 return function(originalEvent){ 6156 //Event normalization(for ontouchxxx and resize): 6157 //1.incorrect e.pageX|pageY in iOS 6158 //2.there are no "e.rotation", "e.scale" and "onorientationchange" in Android 6159 //3.More TBD e.g. force | screenX | screenX | clientX | clientY | radiusX | radiusY 6160 6161 // see if it has already been corrected 6162 var event = originalEvent.corrected; 6163 if(!event){ 6164 var type = originalEvent.type; 6165 try{ 6166 delete originalEvent.type; // on some JS engines (android), deleting properties makes them mutable 6167 }catch(e){} 6168 if(originalEvent.type){ 6169 // Deleting the property of the original event did not work (this is the case of 6170 // browsers such as older Safari iOS), hence fallback: 6171 if(has("touch-can-modify-event-delegate")){ 6172 // If deleting properties of delegated event works, use event delegation: 6173 EventDelegate.prototype = originalEvent; 6174 event = new EventDelegate; 6175 }else{ 6176 // Otherwise last fallback: other browsers, such as mobile Firefox, do not like 6177 // delegated properties, so we have to copy 6178 event = {}; 6179 for(var name in originalEvent){ 6180 event[name] = originalEvent[name]; 6181 } 6182 } 6183 // have to delegate methods to make them work 6184 event.preventDefault = function(){ 6185 originalEvent.preventDefault(); 6186 }; 6187 event.stopPropagation = function(){ 6188 originalEvent.stopPropagation(); 6189 }; 6190 }else{ 6191 // deletion worked, use property as is 6192 event = originalEvent; 6193 event.type = type; 6194 } 6195 originalEvent.corrected = event; 6196 if(type == 'resize'){ 6197 if(windowOrientation == window.orientation){ 6198 return null;//double tap causes an unexpected 'resize' in Android 6199 } 6200 windowOrientation = window.orientation; 6201 event.type = "orientationchange"; 6202 return listener.call(this, event); 6203 } 6204 // We use the original event and augment, rather than doing an expensive mixin operation 6205 if(!("rotation" in event)){ // test to see if it has rotation 6206 event.rotation = 0; 6207 event.scale = 1; 6208 } 6209 //use event.changedTouches[0].pageX|pageY|screenX|screenY|clientX|clientY|target 6210 var firstChangeTouch = event.changedTouches[0]; 6211 for(var i in firstChangeTouch){ // use for-in, we don't need to have dependency on dojo/_base/lang here 6212 delete event[i]; // delete it first to make it mutable 6213 event[i] = firstChangeTouch[i]; 6214 } 6215 } 6216 return listener.call(this, event); 6217 }; 6218 }; 6219 } 6220 return on; 6221}); 6222 6223}, 6224'dojo/topic':function(){ 6225define(["./Evented"], function(Evented){ 6226 6227 // module: 6228 // dojo/topic 6229 6230 var hub = new Evented; 6231 return { 6232 // summary: 6233 // Pubsub hub. 6234 // example: 6235 // | topic.subscribe("some/topic", function(event){ 6236 // | ... do something with event 6237 // | }); 6238 // | topic.publish("some/topic", {name:"some event", ...}); 6239 6240 publish: function(topic, event){ 6241 // summary: 6242 // Publishes a message to a topic on the pub/sub hub. All arguments after 6243 // the first will be passed to the subscribers, so any number of arguments 6244 // can be provided (not just event). 6245 // topic: String 6246 // The name of the topic to publish to 6247 // event: Object 6248 // An event to distribute to the topic listeners 6249 return hub.emit.apply(hub, arguments); 6250 }, 6251 6252 subscribe: function(topic, listener){ 6253 // summary: 6254 // Subscribes to a topic on the pub/sub hub 6255 // topic: String 6256 // The topic to subscribe to 6257 // listener: Function 6258 // A function to call when a message is published to the given topic 6259 return hub.on.apply(hub, arguments); 6260 } 6261 }; 6262}); 6263 6264}, 6265'dojo/Evented':function(){ 6266define(["./aspect", "./on"], function(aspect, on){ 6267 // module: 6268 // dojo/Evented 6269 6270 "use strict"; 6271 var after = aspect.after; 6272 function Evented(){ 6273 // summary: 6274 // A class that can be used as a mixin or base class, 6275 // to add on() and emit() methods to a class 6276 // for listening for events and emitting events: 6277 // example: 6278 // | define(["dojo/Evented", "dojo/_base/declare", "dojo/Stateful" 6279 // | ], function(Evented, declare, Stateful){ 6280 // | var EventedStateful = declare([Evented, Stateful], {...}); 6281 // | var instance = new EventedStateful(); 6282 // | instance.on("open", function(event){ 6283 // | ... do something with event 6284 // | }); 6285 // | 6286 // | instance.emit("open", {name:"some event", ...}); 6287 } 6288 Evented.prototype = { 6289 on: function(type, listener){ 6290 return on.parse(this, type, listener, function(target, type){ 6291 return after(target, 'on' + type, listener, true); 6292 }); 6293 }, 6294 emit: function(type, event){ 6295 var args = [this]; 6296 args.push.apply(args, arguments); 6297 return on.emit.apply(on, args); 6298 } 6299 }; 6300 return Evented; 6301}); 6302 6303}, 6304'dojo/aspect':function(){ 6305define([], function(){ 6306 6307 // module: 6308 // dojo/aspect 6309 6310 "use strict"; 6311 var undefined, nextId = 0; 6312 function advise(dispatcher, type, advice, receiveArguments){ 6313 var previous = dispatcher[type]; 6314 var around = type == "around"; 6315 var signal; 6316 if(around){ 6317 var advised = advice(function(){ 6318 return previous.advice(this, arguments); 6319 }); 6320 signal = { 6321 remove: function(){ 6322 if(advised){ 6323 advised = dispatcher = advice = null; 6324 } 6325 }, 6326 advice: function(target, args){ 6327 return advised ? 6328 advised.apply(target, args) : // called the advised function 6329 previous.advice(target, args); // cancelled, skip to next one 6330 } 6331 }; 6332 }else{ 6333 // create the remove handler 6334 signal = { 6335 remove: function(){ 6336 if(signal.advice){ 6337 var previous = signal.previous; 6338 var next = signal.next; 6339 if(!next && !previous){ 6340 delete dispatcher[type]; 6341 }else{ 6342 if(previous){ 6343 previous.next = next; 6344 }else{ 6345 dispatcher[type] = next; 6346 } 6347 if(next){ 6348 next.previous = previous; 6349 } 6350 } 6351 6352 // remove the advice to signal that this signal has been removed 6353 dispatcher = advice = signal.advice = null; 6354 } 6355 }, 6356 id: nextId++, 6357 advice: advice, 6358 receiveArguments: receiveArguments 6359 }; 6360 } 6361 if(previous && !around){ 6362 if(type == "after"){ 6363 // add the listener to the end of the list 6364 // note that we had to change this loop a little bit to workaround a bizarre IE10 JIT bug 6365 while(previous.next && (previous = previous.next)){} 6366 previous.next = signal; 6367 signal.previous = previous; 6368 }else if(type == "before"){ 6369 // add to beginning 6370 dispatcher[type] = signal; 6371 signal.next = previous; 6372 previous.previous = signal; 6373 } 6374 }else{ 6375 // around or first one just replaces 6376 dispatcher[type] = signal; 6377 } 6378 return signal; 6379 } 6380 function aspect(type){ 6381 return function(target, methodName, advice, receiveArguments){ 6382 var existing = target[methodName], dispatcher; 6383 if(!existing || existing.target != target){ 6384 // no dispatcher in place 6385 target[methodName] = dispatcher = function(){ 6386 var executionId = nextId; 6387 // before advice 6388 var args = arguments; 6389 var before = dispatcher.before; 6390 while(before){ 6391 args = before.advice.apply(this, args) || args; 6392 before = before.next; 6393 } 6394 // around advice
vendor: 4,726 bytes, lines 6395-6496
6395 if(dispatcher.around){ 6396 var results = dispatcher.around.advice(this, args); 6397 } 6398 // after advice 6399 var after = dispatcher.after; 6400 while(after && after.id < executionId){ 6401 if(after.receiveArguments){ 6402 var newResults = after.advice.apply(this, args); 6403 // change the return value only if a new value was returned 6404 results = newResults === undefined ? results : newResults; 6405 }else{ 6406 results = after.advice.call(this, results, args); 6407 } 6408 after = after.next; 6409 } 6410 return results; 6411 }; 6412 if(existing){ 6413 dispatcher.around = {advice: function(target, args){ 6414 return existing.apply(target, args); 6415 }}; 6416 } 6417 dispatcher.target = target; 6418 } 6419 var results = advise((dispatcher || existing), type, advice, receiveArguments); 6420 advice = null; 6421 return results; 6422 }; 6423 } 6424 6425 // TODOC: after/before/around return object 6426 6427 var after = aspect("after"); 6428 /*===== 6429 after = function(target, methodName, advice, receiveArguments){ 6430 // summary: 6431 // The "after" export of the aspect module is a function that can be used to attach 6432 // "after" advice to a method. This function will be executed after the original method 6433 // is executed. By default the function will be called with a single argument, the return 6434 // value of the original method, or the the return value of the last executed advice (if a previous one exists). 6435 // The fourth (optional) argument can be set to true to so the function receives the original 6436 // arguments (from when the original method was called) rather than the return value. 6437 // If there are multiple "after" advisors, they are executed in the order they were registered. 6438 // target: Object 6439 // This is the target object 6440 // methodName: String 6441 // This is the name of the method to attach to. 6442 // advice: Function 6443 // This is function to be called after the original method 6444 // receiveArguments: Boolean? 6445 // If this is set to true, the advice function receives the original arguments (from when the original mehtod 6446 // was called) rather than the return value of the original/previous method. 6447 // returns: 6448 // A signal object that can be used to cancel the advice. If remove() is called on this signal object, it will 6449 // stop the advice function from being executed. 6450 }; 6451 =====*/ 6452 6453 var before = aspect("before"); 6454 /*===== 6455 before = function(target, methodName, advice){ 6456 // summary: 6457 // The "before" export of the aspect module is a function that can be used to attach 6458 // "before" advice to a method. This function will be executed before the original method 6459 // is executed. This function will be called with the arguments used to call the method. 6460 // This function may optionally return an array as the new arguments to use to call 6461 // the original method (or the previous, next-to-execute before advice, if one exists). 6462 // If the before method doesn't return anything (returns undefined) the original arguments 6463 // will be preserved. 6464 // If there are multiple "before" advisors, they are executed in the reverse order they were registered. 6465 // target: Object 6466 // This is the target object 6467 // methodName: String 6468 // This is the name of the method to attach to. 6469 // advice: Function 6470 // This is function to be called before the original method 6471 }; 6472 =====*/ 6473 6474 var around = aspect("around"); 6475 /*===== 6476 around = function(target, methodName, advice){ 6477 // summary: 6478 // The "around" export of the aspect module is a function that can be used to attach 6479 // "around" advice to a method. The advisor function is immediately executed when 6480 // the around() is called, is passed a single argument that is a function that can be 6481 // called to continue execution of the original method (or the next around advisor). 6482 // The advisor function should return a function, and this function will be called whenever 6483 // the method is called. It will be called with the arguments used to call the method. 6484 // Whatever this function returns will be returned as the result of the method call (unless after advise changes it). 6485 // example: 6486 // If there are multiple "around" advisors, the most recent one is executed first, 6487 // which can then delegate to the next one and so on. For example: 6488 // | around(obj, "foo", function(originalFoo){ 6489 // | return function(){ 6490 // | var start = new Date().getTime(); 6491 // | var results = originalFoo.apply(this, arguments); // call the original 6492 // | var end = new Date().getTime(); 6493 // | console.log("foo execution took " + (end - start) + " ms"); 6494 // | return results; 6495 // | }; 6496 // | });
6497 // target: Object 6498 // This is the target object 6499 // methodName: String 6500 // This is the name of the method to attach to. 6501 // advice: Function 6502 // This is function to be called around the original method 6503 }; 6504 =====*/ 6505 6506 return { 6507 // summary: 6508 // provides aspect oriented programming functionality, allowing for 6509 // one to add before, around, or after advice on existing methods. 6510 // example: 6511 // | define(["dojo/aspect"], function(aspect){ 6512 // | var signal = aspect.after(targetObject, "methodName", function(someArgument){ 6513 // | this will be called when targetObject.methodName() is called, after the original function is called 6514 // | }); 6515 // 6516 // example: 6517 // The returned signal object can be used to cancel the advice. 6518 // | signal.remove(); // this will stop the advice from being executed anymore 6519 // | aspect.before(targetObject, "methodName", function(someArgument){ 6520 // | // this will be called when targetObject.methodName() is called, before the original function is called 6521 // | }); 6522 6523 before: before, 6524 around: around, 6525 after: after 6526 }; 6527}); 6528 6529}, 6530'dojo/_base/event':function(){ 6531define(["./kernel", "../on", "../has", "../dom-geometry"], function(dojo, on, has, dom){ 6532 // module: 6533 // dojo/_base/event 6534 6535 if(on._fixEvent){ 6536 var fixEvent = on._fixEvent; 6537 on._fixEvent = function(evt, se){ 6538 // add some additional normalization for back-compat, this isn't in on.js because it is somewhat more expensive 6539 evt = fixEvent(evt, se); 6540 if(evt){ 6541 dom.normalizeEvent(evt); 6542 } 6543 return evt; 6544 }; 6545 } 6546 6547 var ret = { 6548 // summary: 6549 // This module defines dojo DOM event API. Usually you should use dojo/on, and evt.stopPropagation() + 6550 // evt.preventDefault(), rather than this module. 6551 6552 fix: function(/*Event*/ evt, /*DOMNode*/ sender){ 6553 // summary: 6554 // normalizes properties on the event object including event 6555 // bubbling methods, keystroke normalization, and x/y positions 6556 // evt: Event 6557 // native event object 6558 // sender: DOMNode 6559 // node to treat as "currentTarget" 6560 if(on._fixEvent){ 6561 return on._fixEvent(evt, sender); 6562 } 6563 return evt; // Event 6564 }, 6565 6566 stop: function(/*Event*/ evt){ 6567 // summary: 6568 // prevents propagation and clobbers the default action of the 6569 // passed event 6570 // evt: Event 6571 // The event object. If omitted, window.event is used on IE. 6572 if(has("dom-addeventlistener") || (evt && evt.preventDefault)){ 6573 evt.preventDefault(); 6574 evt.stopPropagation(); 6575 }else{ 6576 evt = evt || window.event; 6577 evt.cancelBubble = true; 6578 on._preventDefault.call(evt); 6579 } 6580 } 6581 }; 6582 6583 if( 1 ){ 6584 dojo.fixEvent = ret.fix; 6585 dojo.stopEvent = ret.stop; 6586 } 6587 6588 return ret; 6589}); 6590 6591}, 6592'dojo/dom-geometry':function(){ 6593define(["./sniff", "./_base/window","./dom", "./dom-style"], 6594 function(has, win, dom, style){ 6595 // module: 6596 // dojo/dom-geometry 6597 6598 // the result object 6599 var geom = { 6600 // summary: 6601 // This module defines the core dojo DOM geometry API. 6602 }; 6603 6604 // Box functions will assume this model. 6605 // On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode. 6606 // Can be set to change behavior of box setters. 6607 6608 // can be either: 6609 // "border-box" 6610 // "content-box" (default) 6611 geom.boxModel = "content-box"; 6612 6613 // We punt per-node box mode testing completely. 6614 // If anybody cares, we can provide an additional (optional) unit 6615 // that overrides existing code to include per-node box sensitivity. 6616 6617 // Opera documentation claims that Opera 9 uses border-box in BackCompat mode. 6618 // but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box. 6619 // IIRC, earlier versions of Opera did in fact use border-box. 6620 // Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault. 6621 6622 if(has("ie") /*|| has("opera")*/){ 6623 // client code may have to adjust if compatMode varies across iframes 6624 geom.boxModel = document.compatMode == "BackCompat" ? "border-box" : "content-box"; 6625 } 6626 6627 geom.getPadExtents = function getPadExtents(/*DomNode*/ node, /*Object*/ computedStyle){ 6628 // summary: 6629 // Returns object with special values specifically useful for node 6630 // fitting. 6631 // description: 6632 // Returns an object with `w`, `h`, `l`, `t` properties: 6633 // | l/t/r/b = left/top/right/bottom padding (respectively) 6634 // | w = the total of the left and right padding 6635 // | h = the total of the top and bottom padding 6636 // If 'node' has position, l/t forms the origin for child nodes. 6637 // The w/h are used for calculating boxes. 6638 // Normally application code will not need to invoke this 6639 // directly, and will use the ...box... functions instead. 6640 // node: DOMNode 6641 // computedStyle: Object? 6642 // This parameter accepts computed styles object. 6643 // If this parameter is omitted, the functions will call 6644 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6645 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6646 // computedStyle parameter. Wherever possible, reuse the returned 6647 // object of dojo/dom-style.getComputedStyle(). 6648 6649 node = dom.byId(node); 6650 var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue, 6651 l = px(node, s.paddingLeft), t = px(node, s.paddingTop), r = px(node, s.paddingRight), b = px(node, s.paddingBottom); 6652 return {l: l, t: t, r: r, b: b, w: l + r, h: t + b}; 6653 }; 6654 6655 var none = "none"; 6656 6657 geom.getBorderExtents = function getBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){ 6658 // summary: 6659 // returns an object with properties useful for noting the border 6660 // dimensions. 6661 // description: 6662 // - l/t/r/b = the sum of left/top/right/bottom border (respectively) 6663 // - w = the sum of the left and right border 6664 // - h = the sum of the top and bottom border 6665 // 6666 // The w/h are used for calculating boxes. 6667 // Normally application code will not need to invoke this 6668 // directly, and will use the ...box... functions instead. 6669 // node: DOMNode 6670 // computedStyle: Object? 6671 // This parameter accepts computed styles object. 6672 // If this parameter is omitted, the functions will call 6673 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6674 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6675 // computedStyle parameter. Wherever possible, reuse the returned 6676 // object of dojo/dom-style.getComputedStyle(). 6677 6678 node = dom.byId(node); 6679 var px = style.toPixelValue, s = computedStyle || style.getComputedStyle(node), 6680 l = s.borderLeftStyle != none ? px(node, s.borderLeftWidth) : 0, 6681 t = s.borderTopStyle != none ? px(node, s.borderTopWidth) : 0, 6682 r = s.borderRightStyle != none ? px(node, s.borderRightWidth) : 0, 6683 b = s.borderBottomStyle != none ? px(node, s.borderBottomWidth) : 0; 6684 return {l: l, t: t, r: r, b: b, w: l + r, h: t + b}; 6685 }; 6686 6687 geom.getPadBorderExtents = function getPadBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){ 6688 // summary: 6689 // Returns object with properties useful for box fitting with 6690 // regards to padding. 6691 // description: 6692 // - l/t/r/b = the sum of left/top/right/bottom padding and left/top/right/bottom border (respectively) 6693 // - w = the sum of the left and right padding and border 6694 // - h = the sum of the top and bottom padding and border 6695 // 6696 // The w/h are used for calculating boxes. 6697 // Normally application code will not need to invoke this 6698 // directly, and will use the ...box... functions instead. 6699 // node: DOMNode 6700 // computedStyle: Object? 6701 // This parameter accepts computed styles object. 6702 // If this parameter is omitted, the functions will call 6703 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6704 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6705 // computedStyle parameter. Wherever possible, reuse the returned 6706 // object of dojo/dom-style.getComputedStyle(). 6707 6708 node = dom.byId(node); 6709 var s = computedStyle || style.getComputedStyle(node), 6710 p = geom.getPadExtents(node, s), 6711 b = geom.getBorderExtents(node, s); 6712 return { 6713 l: p.l + b.l, 6714 t: p.t + b.t,
6715 r: p.r + b.r, 6716 b: p.b + b.b, 6717 w: p.w + b.w, 6718 h: p.h + b.h 6719 }; 6720 }; 6721 6722 geom.getMarginExtents = function getMarginExtents(node, computedStyle){ 6723 // summary: 6724 // returns object with properties useful for box fitting with 6725 // regards to box margins (i.e., the outer-box). 6726 // 6727 // - l/t = marginLeft, marginTop, respectively 6728 // - w = total width, margin inclusive 6729 // - h = total height, margin inclusive 6730 // 6731 // The w/h are used for calculating boxes. 6732 // Normally application code will not need to invoke this 6733 // directly, and will use the ...box... functions instead. 6734 // node: DOMNode 6735 // computedStyle: Object? 6736 // This parameter accepts computed styles object. 6737 // If this parameter is omitted, the functions will call 6738 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6739 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6740 // computedStyle parameter. Wherever possible, reuse the returned 6741 // object of dojo/dom-style.getComputedStyle(). 6742 6743 node = dom.byId(node); 6744 var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue, 6745 l = px(node, s.marginLeft), t = px(node, s.marginTop), r = px(node, s.marginRight), b = px(node, s.marginBottom); 6746 return {l: l, t: t, r: r, b: b, w: l + r, h: t + b}; 6747 }; 6748 6749 // Box getters work in any box context because offsetWidth/clientWidth 6750 // are invariant wrt box context 6751 // 6752 // They do *not* work for display: inline objects that have padding styles 6753 // because the user agent ignores padding (it's bogus styling in any case) 6754 // 6755 // Be careful with IMGs because they are inline or block depending on 6756 // browser and browser mode. 6757 6758 // Although it would be easier to read, there are not separate versions of 6759 // _getMarginBox for each browser because: 6760 // 1. the branching is not expensive 6761 // 2. factoring the shared code wastes cycles (function call overhead) 6762 // 3. duplicating the shared code wastes bytes 6763 6764 geom.getMarginBox = function getMarginBox(/*DomNode*/ node, /*Object*/ computedStyle){ 6765 // summary: 6766 // returns an object that encodes the width, height, left and top 6767 // positions of the node's margin box. 6768 // node: DOMNode 6769 // computedStyle: Object? 6770 // This parameter accepts computed styles object. 6771 // If this parameter is omitted, the functions will call 6772 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6773 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6774 // computedStyle parameter. Wherever possible, reuse the returned 6775 // object of dojo/dom-style.getComputedStyle(). 6776 6777 node = dom.byId(node); 6778 var s = computedStyle || style.getComputedStyle(node), me = geom.getMarginExtents(node, s), 6779 l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode, px = style.toPixelValue, pcs; 6780 if(has("mozilla")){ 6781 // Mozilla: 6782 // If offsetParent has a computed overflow != visible, the offsetLeft is decreased 6783 // by the parent's border. 6784 // We don't want to compute the parent's style, so instead we examine node's 6785 // computed left/top which is more stable. 6786 var sl = parseFloat(s.left), st = parseFloat(s.top); 6787 if(!isNaN(sl) && !isNaN(st)){ 6788 l = sl; 6789 t = st; 6790 }else{ 6791 // If child's computed left/top are not parseable as a number (e.g. "auto"), we 6792 // have no choice but to examine the parent's computed style. 6793 if(p && p.style){ 6794 pcs = style.getComputedStyle(p); 6795 if(pcs.overflow != "visible"){ 6796 l += pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0; 6797 t += pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0; 6798 } 6799 } 6800 } 6801 }else if(has("opera") || (has("ie") == 8 && !has("quirks"))){ 6802 // On Opera and IE 8, offsetLeft/Top includes the parent's border 6803 if(p){ 6804 pcs = style.getComputedStyle(p); 6805 l -= pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0; 6806 t -= pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0; 6807 } 6808 } 6809 return {l: l, t: t, w: node.offsetWidth + me.w, h: node.offsetHeight + me.h}; 6810 }; 6811 6812 geom.getContentBox = function getContentBox(node, computedStyle){ 6813 // summary: 6814 // Returns an object that encodes the width, height, left and top 6815 // positions of the node's content box, irrespective of the 6816 // current box model. 6817 // node: DOMNode 6818 // computedStyle: Object? 6819 // This parameter accepts computed styles object. 6820 // If this parameter is omitted, the functions will call 6821 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6822 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6823 // computedStyle parameter. Wherever possible, reuse the returned 6824 // object of dojo/dom-style.getComputedStyle(). 6825 6826 // clientWidth/Height are important since the automatically account for scrollbars 6827 // fallback to offsetWidth/Height for special cases (see #3378) 6828 node = dom.byId(node); 6829 var s = computedStyle || style.getComputedStyle(node), w = node.clientWidth, h, 6830 pe = geom.getPadExtents(node, s), be = geom.getBorderExtents(node, s); 6831 if(!w){ 6832 w = node.offsetWidth; 6833 h = node.offsetHeight; 6834 }else{ 6835 h = node.clientHeight; 6836 be.w = be.h = 0; 6837 } 6838 // On Opera, offsetLeft includes the parent's border 6839 if(has("opera")){ 6840 pe.l += be.l; 6841 pe.t += be.t; 6842 } 6843 return {l: pe.l, t: pe.t, w: w - pe.w - be.w, h: h - pe.h - be.h}; 6844 }; 6845
vendor: 4,701 bytes, lines 6846-6969
6846 // Box setters depend on box context because interpretation of width/height styles 6847 // vary wrt box context. 6848 // 6849 // The value of boxModel is used to determine box context. 6850 // boxModel can be set directly to change behavior. 6851 // 6852 // Beware of display: inline objects that have padding styles 6853 // because the user agent ignores padding (it's a bogus setup anyway) 6854 // 6855 // Be careful with IMGs because they are inline or block depending on 6856 // browser and browser mode. 6857 // 6858 // Elements other than DIV may have special quirks, like built-in 6859 // margins or padding, or values not detectable via computedStyle. 6860 // In particular, margins on TABLE do not seems to appear 6861 // at all in computedStyle on Mozilla. 6862 6863 function setBox(/*DomNode*/ node, /*Number?*/ l, /*Number?*/ t, /*Number?*/ w, /*Number?*/ h, /*String?*/ u){ 6864 // summary: 6865 // sets width/height/left/top in the current (native) box-model 6866 // dimensions. Uses the unit passed in u. 6867 // node: 6868 // DOM Node reference. Id string not supported for performance 6869 // reasons. 6870 // l: 6871 // left offset from parent. 6872 // t: 6873 // top offset from parent. 6874 // w: 6875 // width in current box model. 6876 // h: 6877 // width in current box model. 6878 // u: 6879 // unit measure to use for other measures. Defaults to "px". 6880 u = u || "px"; 6881 var s = node.style; 6882 if(!isNaN(l)){ 6883 s.left = l + u; 6884 } 6885 if(!isNaN(t)){ 6886 s.top = t + u; 6887 } 6888 if(w >= 0){ 6889 s.width = w + u; 6890 } 6891 if(h >= 0){ 6892 s.height = h + u; 6893 } 6894 } 6895 6896 function isButtonTag(/*DomNode*/ node){ 6897 // summary: 6898 // True if the node is BUTTON or INPUT.type="button". 6899 return node.tagName.toLowerCase() == "button" || 6900 node.tagName.toLowerCase() == "input" && (node.getAttribute("type") || "").toLowerCase() == "button"; // boolean 6901 } 6902 6903 function usesBorderBox(/*DomNode*/ node){ 6904 // summary: 6905 // True if the node uses border-box layout. 6906 6907 // We could test the computed style of node to see if a particular box 6908 // has been specified, but there are details and we choose not to bother. 6909 6910 // TABLE and BUTTON (and INPUT type=button) are always border-box by default. 6911 // If you have assigned a different box to either one via CSS then 6912 // box functions will break. 6913 6914 return geom.boxModel == "border-box" || node.tagName.toLowerCase() == "table" || isButtonTag(node); // boolean 6915 } 6916 6917 geom.setContentSize = function setContentSize(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){ 6918 // summary: 6919 // Sets the size of the node's contents, irrespective of margins, 6920 // padding, or borders. 6921 // node: DOMNode 6922 // box: Object 6923 // hash with optional "w", and "h" properties for "width", and "height" 6924 // respectively. All specified properties should have numeric values in whole pixels. 6925 // computedStyle: Object? 6926 // This parameter accepts computed styles object. 6927 // If this parameter is omitted, the functions will call 6928 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6929 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6930 // computedStyle parameter. Wherever possible, reuse the returned 6931 // object of dojo/dom-style.getComputedStyle(). 6932 6933 node = dom.byId(node); 6934 var w = box.w, h = box.h; 6935 if(usesBorderBox(node)){ 6936 var pb = geom.getPadBorderExtents(node, computedStyle); 6937 if(w >= 0){ 6938 w += pb.w; 6939 } 6940 if(h >= 0){ 6941 h += pb.h; 6942 } 6943 } 6944 setBox(node, NaN, NaN, w, h); 6945 }; 6946 6947 var nilExtents = {l: 0, t: 0, w: 0, h: 0}; 6948 6949 geom.setMarginBox = function setMarginBox(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){ 6950 // summary: 6951 // sets the size of the node's margin box and placement 6952 // (left/top), irrespective of box model. Think of it as a 6953 // passthrough to setBox that handles box-model vagaries for 6954 // you. 6955 // node: DOMNode 6956 // box: Object 6957 // hash with optional "l", "t", "w", and "h" properties for "left", "right", "width", and "height" 6958 // respectively. All specified properties should have numeric values in whole pixels. 6959 // computedStyle: Object? 6960 // This parameter accepts computed styles object. 6961 // If this parameter is omitted, the functions will call 6962 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 6963 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 6964 // computedStyle parameter. Wherever possible, reuse the returned 6965 // object of dojo/dom-style.getComputedStyle(). 6966 6967 node = dom.byId(node); 6968 var s = computedStyle || style.getComputedStyle(node), w = box.w, h = box.h, 6969 // Some elements have special padding, margin, and box-model settings.
6970 // To use box functions you may need to set padding, margin explicitly. 6971 // Controlling box-model is harder, in a pinch you might set dojo/dom-geometry.boxModel. 6972 pb = usesBorderBox(node) ? nilExtents : geom.getPadBorderExtents(node, s), 6973 mb = geom.getMarginExtents(node, s); 6974 if(has("webkit")){ 6975 // on Safari (3.1.2), button nodes with no explicit size have a default margin 6976 // setting an explicit size eliminates the margin. 6977 // We have to swizzle the width to get correct margin reading. 6978 if(isButtonTag(node)){ 6979 var ns = node.style; 6980 if(w >= 0 && !ns.width){ 6981 ns.width = "4px"; 6982 } 6983 if(h >= 0 && !ns.height){ 6984 ns.height = "4px"; 6985 } 6986 } 6987 } 6988 if(w >= 0){ 6989 w = Math.max(w - pb.w - mb.w, 0); 6990 } 6991 if(h >= 0){ 6992 h = Math.max(h - pb.h - mb.h, 0); 6993 } 6994 setBox(node, box.l, box.t, w, h); 6995 }; 6996 6997 // ============================= 6998 // Positioning 6999 // ============================= 7000 7001 geom.isBodyLtr = function isBodyLtr(/*Document?*/ doc){ 7002 // summary: 7003 // Returns true if the current language is left-to-right, and false otherwise. 7004 // doc: Document? 7005 // Optional document to query. If unspecified, use win.doc. 7006 // returns: Boolean 7007 7008 doc = doc || win.doc; 7009 return (win.body(doc).dir || doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean 7010 }; 7011 7012 geom.docScroll = function docScroll(/*Document?*/ doc){ 7013 // summary: 7014 // Returns an object with {node, x, y} with corresponding offsets. 7015 // doc: Document? 7016 // Optional document to query. If unspecified, use win.doc. 7017 // returns: Object 7018 7019 doc = doc || win.doc; 7020 var node = win.doc.parentWindow || win.doc.defaultView; // use UI window, not dojo.global window. TODO: use dojo/window::get() except for circular dependency problem 7021 return "pageXOffset" in node ? {x: node.pageXOffset, y: node.pageYOffset } : 7022 (node = has("quirks") ? win.body(doc) : doc.documentElement) && 7023 {x: geom.fixIeBiDiScrollLeft(node.scrollLeft || 0, doc), y: node.scrollTop || 0 }; 7024 }; 7025 7026 if(has("ie")){ 7027 geom.getIeDocumentElementOffset = function getIeDocumentElementOffset(/*Document?*/ doc){ 7028 // summary: 7029 // returns the offset in x and y from the document body to the 7030 // visual edge of the page for IE 7031 // doc: Document? 7032 // Optional document to query. If unspecified, use win.doc. 7033 // description: 7034 // The following values in IE contain an offset: 7035 // | event.clientX 7036 // | event.clientY 7037 // | node.getBoundingClientRect().left 7038 // | node.getBoundingClientRect().top 7039 // But other position related values do not contain this offset, 7040 // such as node.offsetLeft, node.offsetTop, node.style.left and 7041 // node.style.top. The offset is always (2, 2) in LTR direction. 7042 // When the body is in RTL direction, the offset counts the width 7043 // of left scroll bar's width. This function computes the actual 7044 // offset. 7045 7046 //NOTE: assumes we're being called in an IE browser 7047 7048 doc = doc || win.doc; 7049 var de = doc.documentElement; // only deal with HTML element here, position() handles body/quirks 7050 7051 if(has("ie") < 8){ 7052 var r = de.getBoundingClientRect(), // works well for IE6+ 7053 l = r.left, t = r.top; 7054 if(has("ie") < 7){ 7055 l += de.clientLeft; // scrollbar size in strict/RTL, or, 7056 t += de.clientTop; // HTML border size in strict 7057 } 7058 return { 7059 x: l < 0 ? 0 : l, // FRAME element border size can lead to inaccurate negative values 7060 y: t < 0 ? 0 : t 7061 }; 7062 }else{ 7063 return { 7064 x: 0, 7065 y: 0 7066 }; 7067 } 7068 }; 7069 } 7070 7071 geom.fixIeBiDiScrollLeft = function fixIeBiDiScrollLeft(/*Integer*/ scrollLeft, /*Document?*/ doc){ 7072 // summary: 7073 // In RTL direction, scrollLeft should be a negative value, but IE 7074 // returns a positive one. All codes using documentElement.scrollLeft 7075 // must call this function to fix this error, otherwise the position 7076 // will offset to right when there is a horizontal scrollbar. 7077 // scrollLeft: Number 7078 // doc: Document? 7079 // Optional document to query. If unspecified, use win.doc. 7080 // returns: Number 7081 7082 // In RTL direction, scrollLeft should be a negative value, but IE 7083 // returns a positive one. All codes using documentElement.scrollLeft 7084 // must call this function to fix this error, otherwise the position 7085 // will offset to right when there is a horizontal scrollbar. 7086 7087 doc = doc || win.doc; 7088 var ie = has("ie"); 7089 if(ie && !geom.isBodyLtr(doc)){
7090 var qk = has("quirks"), 7091 de = qk ? win.body(doc) : doc.documentElement, 7092 pwin = win.global; // TODO: use winUtils.get(doc) after resolving circular dependency b/w dom-geometry.js and dojo/window.js 7093 if(ie == 6 && !qk && pwin.frameElement && de.scrollHeight > de.clientHeight){ 7094 scrollLeft += de.clientLeft; // workaround ie6+strict+rtl+iframe+vertical-scrollbar bug where clientWidth is too small by clientLeft pixels 7095 } 7096 return (ie < 8 || qk) ? (scrollLeft + de.clientWidth - de.scrollWidth) : -scrollLeft; // Integer 7097 } 7098 return scrollLeft; // Integer 7099 }; 7100 7101 geom.position = function(/*DomNode*/ node, /*Boolean?*/ includeScroll){ 7102 // summary: 7103 // Gets the position and size of the passed element relative to 7104 // the viewport (if includeScroll==false), or relative to the 7105 // document root (if includeScroll==true). 7106 // 7107 // description: 7108 // Returns an object of the form: 7109 // `{ x: 100, y: 300, w: 20, h: 15 }`. 7110 // If includeScroll==true, the x and y values will include any 7111 // document offsets that may affect the position relative to the 7112 // viewport. 7113 // Uses the border-box model (inclusive of border and padding but 7114 // not margin). Does not act as a setter. 7115 // node: DOMNode|String 7116 // includeScroll: Boolean? 7117 // returns: Object 7118 7119 node = dom.byId(node); 7120 var db = win.body(node.ownerDocument), 7121 ret = node.getBoundingClientRect(); 7122 ret = {x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top}; 7123 7124 if(has("ie") < 9){ 7125 // On IE<9 there's a 2px offset that we need to adjust for, see dojo.getIeDocumentElementOffset() 7126 var offset = geom.getIeDocumentElementOffset(node.ownerDocument); 7127 7128 // fixes the position in IE, quirks mode 7129 ret.x -= offset.x + (has("quirks") ? db.clientLeft + db.offsetLeft : 0); 7130 ret.y -= offset.y + (has("quirks") ? db.clientTop + db.offsetTop : 0); 7131 } 7132 7133 // account for document scrolling 7134 // if offsetParent is used, ret value already includes scroll position 7135 // so we may have to actually remove that value if !includeScroll 7136 if(includeScroll){ 7137 var scroll = geom.docScroll(node.ownerDocument); 7138 ret.x += scroll.x; 7139 ret.y += scroll.y; 7140 } 7141 7142 return ret; // Object 7143 }; 7144 7145 // random "private" functions wildly used throughout the toolkit 7146 7147 geom.getMarginSize = function getMarginSize(/*DomNode*/ node, /*Object*/ computedStyle){ 7148 // summary: 7149 // returns an object that encodes the width and height of 7150 // the node's margin box 7151 // node: DOMNode|String 7152 // computedStyle: Object? 7153 // This parameter accepts computed styles object. 7154 // If this parameter is omitted, the functions will call 7155 // dojo/dom-style.getComputedStyle to get one. It is a better way, calling 7156 // dojo/dom-style.getComputedStyle once, and then pass the reference to this 7157 // computedStyle parameter. Wherever possible, reuse the returned 7158 // object of dojo/dom-style.getComputedStyle(). 7159 7160 node = dom.byId(node); 7161 var me = geom.getMarginExtents(node, computedStyle || style.getComputedStyle(node)); 7162 var size = node.getBoundingClientRect(); 7163 return { 7164 w: (size.right - size.left) + me.w, 7165 h: (size.bottom - size.top) + me.h 7166 }; 7167 }; 7168 7169 geom.normalizeEvent = function(event){ 7170 // summary: 7171 // Normalizes the geometry of a DOM event, normalizing the pageX, pageY, 7172 // offsetX, offsetY, layerX, and layerX properties 7173 // event: Object 7174 if(!("layerX" in event)){ 7175 event.layerX = event.offsetX; 7176 event.layerY = event.offsetY; 7177 } 7178 if(!has("dom-addeventlistener")){ 7179 // old IE version 7180 // FIXME: scroll position query is duped from dojo/_base/html to 7181 // avoid dependency on that entire module. Now that HTML is in 7182 // Base, we should convert back to something similar there. 7183 var se = event.target; 7184 var doc = (se && se.ownerDocument) || document; 7185 // DO NOT replace the following to use dojo/_base/window.body(), in IE, document.documentElement should be used 7186 // here rather than document.body 7187 var docBody = has("quirks") ? doc.body : doc.documentElement; 7188 var offset = geom.getIeDocumentElementOffset(doc);
7189 event.pageX = event.clientX + geom.fixIeBiDiScrollLeft(docBody.scrollLeft || 0, doc) - offset.x; 7190 event.pageY = event.clientY + (docBody.scrollTop || 0) - offset.y; 7191 } 7192 }; 7193 7194 // TODO: evaluate separate getters/setters for position and sizes? 7195 7196 return geom; 7197}); 7198 7199}, 7200'dojo/_base/window':function(){ 7201define(["./kernel", "./lang", "../sniff"], function(dojo, lang, has){ 7202// module: 7203// dojo/_base/window 7204 7205var ret = { 7206 // summary: 7207 // API to save/set/restore the global/document scope. 7208 7209 global: dojo.global, 7210 /*===== 7211 global: { 7212 // summary: 7213 // Alias for the current window. 'global' can be modified 7214 // for temporary context shifting. See also withGlobal(). 7215 // description: 7216 // Use this rather than referring to 'window' to ensure your code runs 7217 // correctly in managed contexts. 7218 }, 7219 =====*/ 7220 7221 doc: dojo.global["document"] || null, 7222 /*===== 7223 doc: { 7224 // summary: 7225 // Alias for the current document. 'doc' can be modified 7226 // for temporary context shifting. See also withDoc(). 7227 // description: 7228 // Use this rather than referring to 'window.document' to ensure your code runs 7229 // correctly in managed contexts. 7230 // example: 7231 // | n.appendChild(dojo.doc.createElement('div')); 7232 }, 7233 =====*/ 7234 7235 body: function(/*Document?*/ doc){ 7236 // summary: 7237 // Return the body element of the specified document or of dojo/_base/window::doc. 7238 // example: 7239 // | win.body().appendChild(dojo.doc.createElement('div')); 7240 7241 // Note: document.body is not defined for a strict xhtml document 7242 // Would like to memoize this, but dojo.doc can change vi dojo.withDoc(). 7243 doc = doc || dojo.doc; 7244 return doc.body || doc.getElementsByTagName("body")[0]; // Node 7245 }, 7246 7247 setContext: function(/*Object*/ globalObject, /*DocumentElement*/ globalDocument){ 7248 // summary: 7249 // changes the behavior of many core Dojo functions that deal with 7250 // namespace and DOM lookup, changing them to work in a new global 7251 // context (e.g., an iframe). The varibles dojo.global and dojo.doc 7252 // are modified as a result of calling this function and the result of 7253 // `dojo.body()` likewise differs. 7254 dojo.global = ret.global = globalObject; 7255 dojo.doc = ret.doc = globalDocument; 7256 }, 7257 7258 withGlobal: function( /*Object*/ globalObject, 7259 /*Function*/ callback, 7260 /*Object?*/ thisObject, 7261 /*Array?*/ cbArguments){ 7262 // summary: 7263 // Invoke callback with globalObject as dojo.global and 7264 // globalObject.document as dojo.doc. 7265 // description: 7266 // Invoke callback with globalObject as dojo.global and 7267 // globalObject.document as dojo.doc. If provided, globalObject 7268 // will be executed in the context of object thisObject 7269 // When callback() returns or throws an error, the dojo.global 7270 // and dojo.doc will be restored to its previous state. 7271 7272 var oldGlob = dojo.global; 7273 try{ 7274 dojo.global = ret.global = globalObject; 7275 return ret.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments); 7276 }finally{ 7277 dojo.global = ret.global = oldGlob; 7278 } 7279 }, 7280 7281 withDoc: function( /*DocumentElement*/ documentObject, 7282 /*Function*/ callback, 7283 /*Object?*/ thisObject, 7284 /*Array?*/ cbArguments){ 7285 // summary: 7286 // Invoke callback with documentObject as dojo/_base/window::doc. 7287 // description: 7288 // Invoke callback with documentObject as dojo/_base/window::doc. If provided, 7289 // callback will be executed in the context of object thisObject 7290 // When callback() returns or throws an error, the dojo/_base/window::doc will 7291 // be restored to its previous state. 7292 7293 var oldDoc = ret.doc, 7294 oldQ = has("quirks"), 7295 oldIE = has("ie"), isIE, mode, pwin; 7296 7297 try{ 7298 dojo.doc = ret.doc = documentObject; 7299 // update dojo.isQuirks and the value of the has feature "quirks". 7300 // remove setting dojo.isQuirks and dojo.isIE for 2.0 7301 dojo.isQuirks = has.add("quirks", dojo.doc.compatMode == "BackCompat", true, true); // no need to check for QuirksMode which was Opera 7 only 7302 7303 if(has("ie")){ 7304 if((pwin = documentObject.parentWindow) && pwin.navigator){ 7305 // re-run IE detection logic and update dojo.isIE / has("ie") 7306 // (the only time parentWindow/navigator wouldn't exist is if we were not 7307 // passed an actual legitimate document object) 7308 isIE = parseFloat(pwin.navigator.appVersion.split("MSIE ")[1]) || undefined; 7309 mode = documentObject.documentMode; 7310 if(mode && mode != 5 && Math.floor(isIE) != mode){ 7311 isIE = mode; 7312 } 7313 dojo.isIE = has.add("ie", isIE, true, true); 7314 } 7315 } 7316 7317 if(thisObject && typeof callback == "string"){ 7318 callback = thisObject[callback]; 7319 } 7320 7321 return callback.apply(thisObject, cbArguments || []); 7322 }finally{ 7323 dojo.doc = ret.doc = oldDoc; 7324 dojo.isQuirks = has.add("quirks", oldQ, true, true); 7325 dojo.isIE = has.add("ie", oldIE, true, true); 7326 } 7327 } 7328}; 7329 7330 1 && lang.mixin(dojo, ret); 7331 7332return ret; 7333 7334}); 7335 7336}, 7337'dojo/dom':function(){ 7338define(["./sniff", "./_base/window"], 7339 function(has, win){ 7340 // module: 7341 // dojo/dom 7342 7343 // FIXME: need to add unit tests for all the semi-public methods 7344 7345 if(has("ie") <= 7){ 7346 try{
vendor: 4,151 bytes, lines 7347-7481
7347 document.execCommand("BackgroundImageCache", false, true); 7348 }catch(e){ 7349 // sane browsers don't have cache "issues" 7350 } 7351 } 7352 7353 // ============================= 7354 // DOM Functions 7355 // ============================= 7356 7357 // the result object 7358 var dom = { 7359 // summary: 7360 // This module defines the core dojo DOM API. 7361 }; 7362 7363 if(has("ie")){ 7364 dom.byId = function(id, doc){ 7365 if(typeof id != "string"){ 7366 return id; 7367 } 7368 var _d = doc || win.doc, te = id && _d.getElementById(id); 7369 // attributes.id.value is better than just id in case the 7370 // user has a name=id inside a form 7371 if(te && (te.attributes.id.value == id || te.id == id)){ 7372 return te; 7373 }else{ 7374 var eles = _d.all[id]; 7375 if(!eles || eles.nodeName){ 7376 eles = [eles]; 7377 } 7378 // if more than 1, choose first with the correct id 7379 var i = 0; 7380 while((te = eles[i++])){ 7381 if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){ 7382 return te; 7383 } 7384 } 7385 } 7386 }; 7387 }else{ 7388 dom.byId = function(id, doc){ 7389 // inline'd type check. 7390 // be sure to return null per documentation, to match IE branch. 7391 return ((typeof id == "string") ? (doc || win.doc).getElementById(id) : id) || null; // DOMNode 7392 }; 7393 } 7394 /*===== 7395 dom.byId = function(id, doc){ 7396 // summary: 7397 // Returns DOM node with matching `id` attribute or falsy value (ex: null or undefined) 7398 // if not found. If `id` is a DomNode, this function is a no-op. 7399 // 7400 // id: String|DOMNode 7401 // A string to match an HTML id attribute or a reference to a DOM Node 7402 // 7403 // doc: Document? 7404 // Document to work in. Defaults to the current value of 7405 // dojo/_base/window.doc. Can be used to retrieve 7406 // node references from other documents. 7407 // 7408 // example: 7409 // Look up a node by ID: 7410 // | require(["dojo/dom"], function(dom){ 7411 // | var n = dom.byId("foo"); 7412 // | }); 7413 // 7414 // example: 7415 // Check if a node exists, and use it. 7416 // | require(["dojo/dom"], function(dom){ 7417 // | var n = dom.byId("bar"); 7418 // | if(n){ doStuff() ... } 7419 // | }); 7420 // 7421 // example: 7422 // Allow string or DomNode references to be passed to a custom function: 7423 // | require(["dojo/dom"], function(dom){ 7424 // | var foo = function(nodeOrId){ 7425 // | nodeOrId = dom.byId(nodeOrId); 7426 // | // ... more stuff 7427 // | } 7428 // | }); 7429 }; 7430 =====*/ 7431 7432 dom.isDescendant = function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){ 7433 // summary: 7434 // Returns true if node is a descendant of ancestor 7435 // node: DOMNode|String 7436 // string id or node reference to test 7437 // ancestor: DOMNode|String 7438 // string id or node reference of potential parent to test against 7439 // 7440 // example: 7441 // Test is node id="bar" is a descendant of node id="foo" 7442 // | require(["dojo/dom"], function(dom){ 7443 // | if(dom.isDescendant("bar", "foo")){ ... } 7444 // | }); 7445 7446 try{ 7447 node = dom.byId(node); 7448 ancestor = dom.byId(ancestor); 7449 while(node){ 7450 if(node == ancestor){ 7451 return true; // Boolean 7452 } 7453 node = node.parentNode; 7454 } 7455 }catch(e){ /* squelch, return false */ } 7456 return false; // Boolean 7457 }; 7458 7459 7460 // TODO: do we need setSelectable in the base? 7461 7462 // Add feature test for user-select CSS property 7463 // (currently known to work in all but IE < 10 and Opera) 7464 // TODO: The user-select CSS property as of May 2014 is no longer part of 7465 // any CSS specification. In IE, -ms-user-select does not do the same thing 7466 // as the unselectable attribute on elements; namely, dijit Editor buttons 7467 // do not properly prevent the content of the editable content frame from 7468 // unblurring. As a result, the -ms- prefixed version is omitted here. 7469 has.add("css-user-select", function(global, doc, element){ 7470 // Avoid exception when dom.js is loaded in non-browser environments 7471 if(!element){ return false; } 7472 7473 var style = element.style; 7474 var prefixes = ["Khtml", "O", "Moz", "Webkit"], 7475 i = prefixes.length, 7476 name = "userSelect", 7477 prefix; 7478 7479 // Iterate prefixes from most to least likely 7480 do{ 7481 if(typeof style[name] !== "undefined"){
7482 // Supported; return property name 7483 return name; 7484 } 7485 }while(i-- && (name = prefixes[i] + "UserSelect")); 7486 7487 // Not supported if we didn't return before now 7488 return false; 7489 }); 7490 7491 /*===== 7492 dom.setSelectable = function(node, selectable){ 7493 // summary: 7494 // Enable or disable selection on a node 7495 // node: DOMNode|String 7496 // id or reference to node 7497 // selectable: Boolean 7498 // state to put the node in. false indicates unselectable, true 7499 // allows selection. 7500 // example: 7501 // Make the node id="bar" unselectable 7502 // | require(["dojo/dom"], function(dom){ 7503 // | dom.setSelectable("bar"); 7504 // | }); 7505 // example: 7506 // Make the node id="bar" selectable 7507 // | require(["dojo/dom"], function(dom){ 7508 // | dom.setSelectable("bar", true); 7509 // | }); 7510 }; 7511 =====*/ 7512 7513 var cssUserSelect = has("css-user-select"); 7514 dom.setSelectable = cssUserSelect ? function(node, selectable){ 7515 // css-user-select returns a (possibly vendor-prefixed) CSS property name 7516 dom.byId(node).style[cssUserSelect] = selectable ? "" : "none"; 7517 } : function(node, selectable){ 7518 node = dom.byId(node); 7519 7520 // (IE < 10 / Opera) Fall back to setting/removing the 7521 // unselectable attribute on the element and all its children 7522 var nodes = node.getElementsByTagName("*"), 7523 i = nodes.length; 7524 7525 if(selectable){ 7526 node.removeAttribute("unselectable"); 7527 while(i--){ 7528 nodes[i].removeAttribute("unselectable"); 7529 } 7530 }else{ 7531 node.setAttribute("unselectable", "on"); 7532 while(i--){ 7533 nodes[i].setAttribute("unselectable", "on"); 7534 } 7535 } 7536 }; 7537 7538 return dom; 7539}); 7540 7541}, 7542'dojo/dom-style':function(){ 7543define(["./sniff", "./dom"], function(has, dom){ 7544 // module: 7545 // dojo/dom-style 7546 7547 // ============================= 7548 // Style Functions 7549 // ============================= 7550 7551 // getComputedStyle drives most of the style code. 7552 // Wherever possible, reuse the returned object. 7553 // 7554 // API functions below that need to access computed styles accept an 7555 // optional computedStyle parameter. 7556 // If this parameter is omitted, the functions will call getComputedStyle themselves. 7557 // This way, calling code can access computedStyle once, and then pass the reference to 7558 // multiple API functions. 7559 7560 // Although we normally eschew argument validation at this 7561 // level, here we test argument 'node' for (duck)type, 7562 // by testing nodeType, ecause 'document' is the 'parentNode' of 'body' 7563 // it is frequently sent to this function even 7564 // though it is not Element. 7565 var getComputedStyle, style = { 7566 // summary: 7567 // This module defines the core dojo DOM style API. 7568 }; 7569 if(has("webkit")){ 7570 getComputedStyle = function(/*DomNode*/ node){ 7571 var s; 7572 if(node.nodeType == 1){ 7573 var dv = node.ownerDocument.defaultView; 7574 s = dv.getComputedStyle(node, null); 7575 if(!s && node.style){ 7576 node.style.display = ""; 7577 s = dv.getComputedStyle(node, null); 7578 } 7579 } 7580 return s || {}; 7581 }; 7582 }
vendor: 9,086 bytes, lines 7582-7842
7582else if(has("ie") && (has("ie") < 9 || has("quirks"))){ 7583 getComputedStyle = function(node){ 7584 // IE (as of 7) doesn't expose Element like sane browsers 7585 // currentStyle can be null on IE8! 7586 return node.nodeType == 1 /* ELEMENT_NODE*/ && node.currentStyle ? node.currentStyle : {}; 7587 }; 7588 }else{ 7589 getComputedStyle = function(node){ 7590 return node.nodeType == 1 /* ELEMENT_NODE*/ ? 7591 node.ownerDocument.defaultView.getComputedStyle(node, null) : {}; 7592 }; 7593 } 7594 style.getComputedStyle = getComputedStyle; 7595 /*===== 7596 style.getComputedStyle = function(node){ 7597 // summary: 7598 // Returns a "computed style" object. 7599 // 7600 // description: 7601 // Gets a "computed style" object which can be used to gather 7602 // information about the current state of the rendered node. 7603 // 7604 // Note that this may behave differently on different browsers. 7605 // Values may have different formats and value encodings across 7606 // browsers. 7607 // 7608 // Note also that this method is expensive. Wherever possible, 7609 // reuse the returned object. 7610 // 7611 // Use the dojo/dom-style.get() method for more consistent (pixelized) 7612 // return values. 7613 // 7614 // node: DOMNode 7615 // A reference to a DOM node. Does NOT support taking an 7616 // ID string for speed reasons. 7617 // example: 7618 // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){ 7619 // | domStyle.getComputedStyle(dom.byId('foo')).borderWidth; 7620 // | }); 7621 // 7622 // example: 7623 // Reusing the returned object, avoiding multiple lookups: 7624 // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){ 7625 // | var cs = domStyle.getComputedStyle(dom.byId("someNode")); 7626 // | var w = cs.width, h = cs.height; 7627 // | }); 7628 return; // CSS2Properties 7629 }; 7630 =====*/ 7631 7632 var toPixel; 7633 if(!has("ie")){ 7634 toPixel = function(element, value){ 7635 // style values can be floats, client code may want 7636 // to round for integer pixels. 7637 return parseFloat(value) || 0; 7638 }; 7639 }else{ 7640 toPixel = function(element, avalue){ 7641 if(!avalue){ return 0; } 7642 // on IE7, medium is usually 4 pixels 7643 if(avalue == "medium"){ return 4; } 7644 // style values can be floats, client code may 7645 // want to round this value for integer pixels. 7646 if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); } 7647 var s = element.style, rs = element.runtimeStyle, cs = element.currentStyle, 7648 sLeft = s.left, rsLeft = rs.left; 7649 rs.left = cs.left; 7650 try{ 7651 // 'avalue' may be incompatible with style.left, which can cause IE to throw 7652 // this has been observed for border widths using "thin", "medium", "thick" constants 7653 // those particular constants could be trapped by a lookup 7654 // but perhaps there are more 7655 s.left = avalue; 7656 avalue = s.pixelLeft; 7657 }catch(e){ 7658 avalue = 0; 7659 } 7660 s.left = sLeft; 7661 rs.left = rsLeft; 7662 return avalue; 7663 }; 7664 } 7665 style.toPixelValue = toPixel; 7666 /*===== 7667 style.toPixelValue = function(node, value){ 7668 // summary: 7669 // converts style value to pixels on IE or return a numeric value. 7670 // node: DOMNode 7671 // value: String 7672 // returns: Number 7673 }; 7674 =====*/ 7675 7676 // FIXME: there opacity quirks on FF that we haven't ported over. Hrm. 7677 7678 var astr = "DXImageTransform.Microsoft.Alpha"; 7679 var af = function(n, f){ 7680 try{ 7681 return n.filters.item(astr); 7682 }catch(e){ 7683 return f ? {} : null; 7684 } 7685 }; 7686 7687 var _getOpacity = 7688 has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(node){ 7689 try{ 7690 return af(node).Opacity / 100; // Number 7691 }catch(e){ 7692 return 1; // Number 7693 } 7694 } : 7695 function(node){ 7696 return getComputedStyle(node).opacity; 7697 }; 7698 7699 var _setOpacity = 7700 has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(/*DomNode*/ node, /*Number*/ opacity){ 7701 if(opacity === ""){ opacity = 1; } 7702 var ov = opacity * 100, fullyOpaque = opacity === 1; 7703 7704 // on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661), 7705 // but still update the opacity value so we can get a correct reading if it is read later: 7706 // af(node, 1).Enabled = !fullyOpaque; 7707 7708 if(fullyOpaque){ 7709 node.style.zoom = ""; 7710 if(af(node)){ 7711 node.style.filter = node.style.filter.replace( 7712 new RegExp("\\s*progid:" + astr + "\\([^\\)]+?\\)", "i"), ""); 7713 } 7714 }else{ 7715 node.style.zoom = 1; 7716 if(af(node)){ 7717 af(node, 1).Opacity = ov; 7718 }else{ 7719 node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")"; 7720 } 7721 af(node, 1).Enabled = true; 7722 } 7723 7724 if(node.tagName.toLowerCase() == "tr"){ 7725 for(var td = node.firstChild; td; td = td.nextSibling){ 7726 if(td.tagName.toLowerCase() == "td"){ 7727 _setOpacity(td, opacity); 7728 } 7729 } 7730 } 7731 return opacity; 7732 } : 7733 function(node, opacity){ 7734 return node.style.opacity = opacity; 7735 }; 7736 7737 var _pixelNamesCache = { 7738 left: true, top: true 7739 }; 7740 var _pixelRegExp = /margin|padding|width|height|max|min|offset/; // |border 7741 function _toStyleValue(node, type, value){ 7742 //TODO: should we really be doing string case conversion here? Should we cache it? Need to profile! 7743 type = type.toLowerCase(); 7744 if(has("ie") || has("trident")){ 7745 if(value == "auto"){ 7746 if(type == "height"){ return node.offsetHeight; } 7747 if(type == "width"){ return node.offsetWidth; } 7748 } 7749 if(type == "fontweight"){ 7750 switch(value){ 7751 case 700: return "bold"; 7752 case 400: 7753 default: return "normal"; 7754 } 7755 } 7756 } 7757 if(!(type in _pixelNamesCache)){ 7758 _pixelNamesCache[type] = _pixelRegExp.test(type); 7759 } 7760 return _pixelNamesCache[type] ? toPixel(node, value) : value; 7761 } 7762 7763 var _floatAliases = {cssFloat: 1, styleFloat: 1, "float": 1}; 7764 7765 // public API 7766 7767 style.get = function getStyle(/*DOMNode|String*/ node, /*String?*/ name){ 7768 // summary: 7769 // Accesses styles on a node. 7770 // description: 7771 // Getting the style value uses the computed style for the node, so the value 7772 // will be a calculated value, not just the immediate node.style value. 7773 // Also when getting values, use specific style names, 7774 // like "borderBottomWidth" instead of "border" since compound values like 7775 // "border" are not necessarily reflected as expected. 7776 // If you want to get node dimensions, use `dojo/dom-geometry.getMarginBox()`, 7777 // `dojo/dom-geometry.getContentBox()` or `dojo/dom-geometry.getPosition()`. 7778 // node: DOMNode|String 7779 // id or reference to node to get style for 7780 // name: String? 7781 // the style property to get 7782 // example: 7783 // Passing only an ID or node returns the computed style object of 7784 // the node: 7785 // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){ 7786 // | domStyle.get("thinger"); 7787 // | }); 7788 // example: 7789 // Passing a node and a style property returns the current 7790 // normalized, computed value for that property: 7791 // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){ 7792 // | domStyle.get("thinger", "opacity"); // 1 by default 7793 // | }); 7794 7795 var n = dom.byId(node), l = arguments.length, op = (name == "opacity"); 7796 if(l == 2 && op){ 7797 return _getOpacity(n); 7798 } 7799 name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name; 7800 var s = style.getComputedStyle(n); 7801 return (l == 1) ? s : _toStyleValue(n, name, s[name] || n.style[name]); /* CSS2Properties||String||Number */ 7802 }; 7803 7804 style.set = function setStyle(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){ 7805 // summary: 7806 // Sets styles on a node. 7807 // node: DOMNode|String 7808 // id or reference to node to set style for 7809 // name: String|Object 7810 // the style property to set in DOM-accessor format 7811 // ("borderWidth", not "border-width") or an object with key/value 7812 // pairs suitable for setting each property. 7813 // value: String? 7814 // If passed, sets value on the node for style, handling 7815 // cross-browser concerns. When setting a pixel value, 7816 // be sure to include "px" in the value. For instance, top: "200px". 7817 // Otherwise, in some cases, some browsers will not apply the style. 7818 // 7819 // example: 7820 // Passing a node, a style property, and a value changes the 7821 // current display of the node and returns the new computed value 7822 // | require(["dojo/dom-style"], function(domStyle){ 7823 // | domStyle.set("thinger", "opacity", 0.5); // == 0.5 7824 // | }); 7825 // 7826 // example: 7827 // Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node: 7828 // | require(["dojo/dom-style"], function(domStyle){ 7829 // | domStyle.set("thinger", { 7830 // | "opacity": 0.5, 7831 // | "border": "3px solid black", 7832 // | "height": "300px" 7833 // | }); 7834 // | }); 7835 // 7836 // example: 7837 // When the CSS style property is hyphenated, the JavaScript property is camelCased. 7838 // font-size becomes fontSize, and so on. 7839 // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){ 7840 // | domStyle.set("thinger",{ 7841 // | fontSize:"14pt", 7842 // | letterSpacing:"1.2em"
7843 // | }); 7844 // | }); 7845 // 7846 // example: 7847 // dojo/NodeList implements .style() using the same syntax, omitting the "node" parameter, calling 7848 // dojo/dom-style.get() on every element of the list. See: `dojo/query` and `dojo/NodeList` 7849 // | require(["dojo/dom-style", "dojo/query", "dojo/NodeList-dom"], 7850 // | function(domStyle, query){ 7851 // | query(".someClassName").style("visibility","hidden"); 7852 // | // or 7853 // | query("#baz > div").style({ 7854 // | opacity:0.75, 7855 // | fontSize:"13pt" 7856 // | }); 7857 // | }); 7858 7859 var n = dom.byId(node), l = arguments.length, op = (name == "opacity"); 7860 name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name; 7861 if(l == 3){ 7862 return op ? _setOpacity(n, value) : n.style[name] = value; // Number 7863 } 7864 for(var x in name){ 7865 style.set(node, x, name[x]); 7866 } 7867 return style.getComputedStyle(n); 7868 }; 7869 7870 return style; 7871}); 7872 7873}, 7874'dojo/mouse':function(){ 7875define(["./_base/kernel", "./on", "./has", "./dom", "./_base/window"], function(dojo, on, has, dom, win){ 7876 7877 // module: 7878 // dojo/mouse 7879 7880 has.add("dom-quirks", win.doc && win.doc.compatMode == "BackCompat"); 7881 has.add("events-mouseenter", win.doc && "onmouseenter" in win.doc.createElement("div")); 7882 has.add("events-mousewheel", win.doc && 'onmousewheel' in win.doc); 7883 7884 var mouseButtons; 7885 if((has("dom-quirks") && has("ie")) || !has("dom-addeventlistener")){ 7886 mouseButtons = { 7887 LEFT: 1, 7888 MIDDLE: 4, 7889 RIGHT: 2, 7890 // helper functions 7891 isButton: function(e, button){ return e.button & button; }, 7892 isLeft: function(e){ return e.button & 1; }, 7893 isMiddle: function(e){ return e.button & 4; }, 7894 isRight: function(e){ return e.button & 2; } 7895 }; 7896 }else{ 7897 mouseButtons = { 7898 LEFT: 0, 7899 MIDDLE: 1, 7900 RIGHT: 2, 7901 // helper functions 7902 isButton: function(e, button){ return e.button == button; }, 7903 isLeft: function(e){ return e.button == 0; }, 7904 isMiddle: function(e){ return e.button == 1; }, 7905 isRight: function(e){ return e.button == 2; } 7906 }; 7907 } 7908 dojo.mouseButtons = mouseButtons; 7909 7910/*===== 7911 dojo.mouseButtons = { 7912 // LEFT: Number 7913 // Numeric value of the left mouse button for the platform. 7914 LEFT: 0, 7915 // MIDDLE: Number 7916 // Numeric value of the middle mouse button for the platform. 7917 MIDDLE: 1, 7918 // RIGHT: Number 7919 // Numeric value of the right mouse button for the platform. 7920 RIGHT: 2, 7921 7922 isButton: function(e, button){ 7923 // summary: 7924 // Checks an event object for a pressed button 7925 // e: Event 7926 // Event object to examine 7927 // button: Number 7928 // The button value (example: dojo.mouseButton.LEFT) 7929 return e.button == button; // Boolean 7930 }, 7931 isLeft: function(e){ 7932 // summary: 7933 // Checks an event object for the pressed left button 7934 // e: Event 7935 // Event object to examine 7936 return e.button == 0; // Boolean 7937 }, 7938 isMiddle: function(e){ 7939 // summary: 7940 // Checks an event object for the pressed middle button 7941 // e: Event 7942 // Event object to examine 7943 return e.button == 1; // Boolean 7944 }, 7945 isRight: function(e){ 7946 // summary: 7947 // Checks an event object for the pressed right button 7948 // e: Event 7949 // Event object to examine 7950 return e.button == 2; // Boolean 7951 } 7952 }; 7953=====*/ 7954 7955 function eventHandler(type, selectHandler){ 7956 // emulation of mouseenter/leave with mouseover/out using descendant checking 7957 var handler = function(node, listener){ 7958 return on(node, type, function(evt){ 7959 if(selectHandler){ 7960 return selectHandler(evt, listener); 7961 } 7962 if(!dom.isDescendant(evt.relatedTarget, node)){ 7963 return listener.call(this, evt); 7964 } 7965 }); 7966 }; 7967 handler.bubble = function(select){ 7968 return eventHandler(type, function(evt, listener){ 7969 // using a selector, use the select function to determine if the mouse moved inside the selector and was previously outside the selector 7970 var target = select(evt.target); 7971 var relatedTarget = evt.relatedTarget; 7972 if(target && (target != (relatedTarget && relatedTarget.nodeType == 1 && select(relatedTarget)))){ 7973 return listener.call(target, evt); 7974 } 7975 }); 7976 }; 7977 return handler; 7978 } 7979 var wheel; 7980 if(has("events-mousewheel")){ 7981 wheel = 'mousewheel'; 7982 }else{ //firefox 7983 wheel = function(node, listener){ 7984 return on(node, 'DOMMouseScroll', function(evt){ 7985 evt.wheelDelta = -evt.detail; 7986 listener.call(this, evt); 7987 }); 7988 }; 7989 } 7990 return { 7991 // summary: 7992 // This module provide mouse event handling utility functions and exports
7993 // mouseenter and mouseleave event emulation. 7994 // example: 7995 // To use these events, you register a mouseenter like this: 7996 // | define(["dojo/on", "dojo/mouse"], function(on, mouse){ 7997 // | on(targetNode, mouse.enter, function(event){ 7998 // | dojo.addClass(targetNode, "highlighted"); 7999 // | }); 8000 // | on(targetNode, mouse.leave, function(event){ 8001 // | dojo.removeClass(targetNode, "highlighted"); 8002 // | }); 8003 8004 _eventHandler: eventHandler, // for dojo/touch 8005 8006 // enter: Synthetic Event 8007 // This is an extension event for the mouseenter that IE provides, emulating the 8008 // behavior on other browsers. 8009 enter: eventHandler("mouseover"), 8010 8011 // leave: Synthetic Event 8012 // This is an extension event for the mouseleave that IE provides, emulating the 8013 // behavior on other browsers. 8014 leave: eventHandler("mouseout"), 8015 8016 // wheel: Normalized Mouse Wheel Event 8017 // This is an extension event for the mousewheel that non-Mozilla browsers provide, 8018 // emulating the behavior on Mozilla based browsers. 8019 wheel: wheel, 8020 8021 isLeft: mouseButtons.isLeft, 8022 /*===== 8023 isLeft: function(){ 8024 // summary: 8025 // Test an event object (from a mousedown event) to see if the left button was pressed. 8026 }, 8027 =====*/ 8028 8029 isMiddle: mouseButtons.isMiddle, 8030 /*===== 8031 isMiddle: function(){ 8032 // summary: 8033 // Test an event object (from a mousedown event) to see if the middle button was pressed. 8034 }, 8035 =====*/ 8036 8037 isRight: mouseButtons.isRight 8038 /*===== 8039 , isRight: function(){ 8040 // summary: 8041 // Test an event object (from a mousedown event) to see if the right button was pressed. 8042 } 8043 =====*/ 8044 }; 8045}); 8046 8047}, 8048'dojo/_base/sniff':function(){ 8049define(["./kernel", "./lang", "../sniff"], function(dojo, lang, has){ 8050 // module: 8051 // dojo/_base/sniff 8052 8053 /*===== 8054 return { 8055 // summary: 8056 // Deprecated. New code should use dojo/sniff. 8057 // This module populates the dojo browser version sniffing properties like dojo.isIE. 8058 }; 8059 =====*/ 8060 8061 if(! 1 ){ 8062 return has; 8063 } 8064 8065 // no idea what this is for, or if it's used 8066 dojo._name = "browser"; 8067 8068 lang.mixin(dojo, { 8069 // isBrowser: Boolean 8070 // True if the client is a web-browser 8071 isBrowser: true, 8072 8073 // isFF: Number|undefined 8074 // Version as a Number if client is FireFox. undefined otherwise. Corresponds to 8075 // major detected FireFox version (1.5, 2, 3, etc.) 8076 isFF: has("ff"), 8077 8078 // isIE: Number|undefined 8079 // Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to 8080 // major detected IE version (6, 7, 8, etc.) 8081 isIE: has("ie"), 8082 8083 // isKhtml: Number|undefined 8084 // Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major 8085 // detected version. 8086 isKhtml: has("khtml"), 8087 8088 // isWebKit: Number|undefined 8089 // Version as a Number if client is a WebKit-derived browser (Konqueror, 8090 // Safari, Chrome, etc.). undefined otherwise. 8091 isWebKit: has("webkit"), 8092 8093 // isMozilla: Number|undefined 8094 // Version as a Number if client is a Mozilla-based browser (Firefox, 8095 // SeaMonkey). undefined otherwise. Corresponds to major detected version. 8096 isMozilla: has("mozilla"), 8097 // isMoz: Number|undefined 8098 // Version as a Number if client is a Mozilla-based browser (Firefox, 8099 // SeaMonkey). undefined otherwise. Corresponds to major detected version. 8100 isMoz: has("mozilla"), 8101 8102 // isOpera: Number|undefined 8103 // Version as a Number if client is Opera. undefined otherwise. Corresponds to 8104 // major detected version. 8105 isOpera: has("opera"), 8106 8107 // isSafari: Number|undefined 8108 // Version as a Number if client is Safari or iPhone. undefined otherwise. 8109 isSafari: has("safari"), 8110 8111 // isChrome: Number|undefined 8112 // Version as a Number if client is Chrome browser. undefined otherwise. 8113 isChrome: has("chrome"), 8114 8115 // isMac: Boolean 8116 // True if the client runs on Mac 8117 isMac: has("mac"), 8118 8119 // isIos: Number|undefined 8120 // Version as a Number if client is iPhone, iPod, or iPad. undefined otherwise. 8121 isIos: has("ios"), 8122 8123 // isAndroid: Number|undefined 8124 // Version as a Number if client is android browser. undefined otherwise. 8125 isAndroid: has("android"), 8126 8127 // isWii: Boolean 8128 // True if client is Wii 8129 isWii: has("wii"), 8130 8131 // isQuirks: Boolean 8132 // Page is in quirks mode.
8133 isQuirks: has("quirks"), 8134 8135 // isAir: Boolean 8136 // True if client is Adobe Air 8137 isAir: has("air") 8138 }); 8139 8140 return has; 8141}); 8142 8143}, 8144'dojo/keys':function(){ 8145define(["./_base/kernel", "./sniff"], function(dojo, has){ 8146 8147 // module: 8148 // dojo/keys 8149 8150 return dojo.keys = { 8151 // summary: 8152 // Definitions for common key values. Client code should test keyCode against these named constants, 8153 // as the actual codes can vary by browser. 8154 8155 BACKSPACE: 8, 8156 TAB: 9, 8157 CLEAR: 12, 8158 ENTER: 13, 8159 SHIFT: 16, 8160 CTRL: 17, 8161 ALT: 18, 8162 META: has("webkit") ? 91 : 224, // the apple key on macs 8163 PAUSE: 19, 8164 CAPS_LOCK: 20, 8165 ESCAPE: 27, 8166 SPACE: 32, 8167 PAGE_UP: 33, 8168 PAGE_DOWN: 34, 8169 END: 35, 8170 HOME: 36, 8171 LEFT_ARROW: 37, 8172 UP_ARROW: 38, 8173 RIGHT_ARROW: 39, 8174 DOWN_ARROW: 40, 8175 INSERT: 45, 8176 DELETE: 46, 8177 HELP: 47, 8178 LEFT_WINDOW: 91, 8179 RIGHT_WINDOW: 92, 8180 SELECT: 93, 8181 NUMPAD_0: 96, 8182 NUMPAD_1: 97, 8183 NUMPAD_2: 98, 8184 NUMPAD_3: 99, 8185 NUMPAD_4: 100, 8186 NUMPAD_5: 101, 8187 NUMPAD_6: 102, 8188 NUMPAD_7: 103, 8189 NUMPAD_8: 104, 8190 NUMPAD_9: 105, 8191 NUMPAD_MULTIPLY: 106, 8192 NUMPAD_PLUS: 107, 8193 NUMPAD_ENTER: 108, 8194 NUMPAD_MINUS: 109, 8195 NUMPAD_PERIOD: 110, 8196 NUMPAD_DIVIDE: 111, 8197 F1: 112, 8198 F2: 113, 8199 F3: 114, 8200 F4: 115, 8201 F5: 116, 8202 F6: 117, 8203 F7: 118, 8204 F8: 119, 8205 F9: 120, 8206 F10: 121, 8207 F11: 122, 8208 F12: 123, 8209 F13: 124, 8210 F14: 125, 8211 F15: 126, 8212 NUM_LOCK: 144, 8213 SCROLL_LOCK: 145, 8214 UP_DPAD: 175, 8215 DOWN_DPAD: 176, 8216 LEFT_DPAD: 177, 8217 RIGHT_DPAD: 178, 8218 // virtual key mapping 8219 copyKey: has("mac") && !has("air") ? (has("safari") ? 91 : 224 ) : 17 8220 }; 8221}); 8222 8223}, 8224'dojo/_base/Deferred':function(){ 8225define([ 8226 "./kernel", 8227 "../Deferred", 8228 "../promise/Promise", 8229 "../errors/CancelError", 8230 "../has", 8231 "./lang", 8232 "../when" 8233], function(dojo, NewDeferred, Promise, CancelError, has, lang, when){ 8234 // module: 8235 // dojo/_base/Deferred 8236 8237 var mutator = function(){}; 8238 var freeze = Object.freeze || function(){}; 8239 // A deferred provides an API for creating and resolving a promise. 8240 var Deferred = dojo.Deferred = function(/*Function?*/ canceller){ 8241 // summary: 8242 // Deprecated. This module defines the legacy dojo/_base/Deferred API. 8243 // New code should use dojo/Deferred instead. 8244 // description: 8245 // The Deferred API is based on the concept of promises that provide a 8246 // generic interface into the eventual completion of an asynchronous action. 8247 // The motivation for promises fundamentally is about creating a 8248 // separation of concerns that allows one to achieve the same type of 8249 // call patterns and logical data flow in asynchronous code as can be 8250 // achieved in synchronous code. Promises allows one 8251 // to be able to call a function purely with arguments needed for 8252 // execution, without conflating the call with concerns of whether it is 8253 // sync or async. One shouldn't need to alter a call's arguments if the 8254 // implementation switches from sync to async (or vice versa). By having 8255 // async functions return promises, the concerns of making the call are 8256 // separated from the concerns of asynchronous interaction (which are 8257 // handled by the promise). 8258 // 8259 // The Deferred is a type of promise that provides methods for fulfilling the 8260 // promise with a successful result or an error. The most important method for 8261 // working with Dojo's promises is the then() method, which follows the 8262 // CommonJS proposed promise API. An example of using a Dojo promise: 8263 // 8264 // | var resultingPromise = someAsyncOperation.then(function(result){ 8265 // | ... handle result ... 8266 // | }, 8267 // | function(error){ 8268 // | ... handle error ... 8269 // | }); 8270 // 8271 // The .then() call returns a new promise that represents the result of the 8272 // execution of the callback. The callbacks will never affect the original promises value. 8273 // 8274 // The Deferred instances also provide the following functions for backwards compatibility: 8275 // 8276 // - addCallback(handler) 8277 // - addErrback(handler) 8278 // - callback(result) 8279 // - errback(result) 8280 // 8281 // Callbacks are allowed to return promises themselves, so 8282 // you can build complicated sequences of events with ease. 8283 // 8284 // The creator of the Deferred may specify a canceller. The canceller 8285 // is a function that will be called if Deferred.cancel is called 8286 // before the Deferred fires. You can use this to implement clean 8287 // aborting of an XMLHttpRequest, etc. Note that cancel will fire the 8288 // deferred with a CancelledError (unless your canceller returns 8289 // another kind of error), so the errbacks should be prepared to 8290 // handle that error for cancellable Deferreds. 8291 // example: 8292 // | var deferred = new Deferred(); 8293 // | setTimeout(function(){ deferred.callback({success: true}); }, 1000); 8294 // | return deferred; 8295 // example: 8296 // Deferred objects are often used when making code asynchronous. It 8297 // may be easiest to write functions in a synchronous manner and then 8298 // split code using a deferred to trigger a response to a long-lived 8299 // operation. For example, instead of register a callback function to 8300 // denote when a rendering operation completes, the function can 8301 // simply return a deferred: 8302 // 8303 // | // callback style: 8304 // | function renderLotsOfData(data, callback){ 8305 // | var success = false 8306 // | try{ 8307 // | for(var x in data){ 8308 // | renderDataitem(data[x]); 8309 // | } 8310 // | success = true; 8311 // | }catch(e){ } 8312 // | if(callback){ 8313 // | callback(success); 8314 // | } 8315 // | } 8316 // 8317 // | // using callback style 8318 // | renderLotsOfData(someDataObj, function(success){ 8319 // | // handles success or failure 8320 // | if(!success){ 8321 // | promptUserToRecover(); 8322 // | } 8323 // | });
8324 // | // NOTE: no way to add another callback here!! 8325 // example: 8326 // Using a Deferred doesn't simplify the sending code any, but it 8327 // provides a standard interface for callers and senders alike, 8328 // providing both with a simple way to service multiple callbacks for 8329 // an operation and freeing both sides from worrying about details 8330 // such as "did this get called already?". With Deferreds, new 8331 // callbacks can be added at any time. 8332 // 8333 // | // Deferred style: 8334 // | function renderLotsOfData(data){ 8335 // | var d = new Deferred(); 8336 // | try{ 8337 // | for(var x in data){ 8338 // | renderDataitem(data[x]); 8339 // | } 8340 // | d.callback(true); 8341 // | }catch(e){ 8342 // | d.errback(new Error("rendering failed")); 8343 // | } 8344 // | return d; 8345 // | } 8346 // 8347 // | // using Deferred style 8348 // | renderLotsOfData(someDataObj).then(null, function(){ 8349 // | promptUserToRecover(); 8350 // | }); 8351 // | // NOTE: addErrback and addCallback both return the Deferred 8352 // | // again, so we could chain adding callbacks or save the 8353 // | // deferred for later should we need to be notified again. 8354 // example: 8355 // In this example, renderLotsOfData is synchronous and so both 8356 // versions are pretty artificial. Putting the data display on a 8357 // timeout helps show why Deferreds rock: 8358 // 8359 // | // Deferred style and async func 8360 // | function renderLotsOfData(data){ 8361 // | var d = new Deferred(); 8362 // | setTimeout(function(){ 8363 // | try{ 8364 // | for(var x in data){ 8365 // | renderDataitem(data[x]); 8366 // | } 8367 // | d.callback(true); 8368 // | }catch(e){ 8369 // | d.errback(new Error("rendering failed")); 8370 // | } 8371 // | }, 100); 8372 // | return d; 8373 // | } 8374 // 8375 // | // using Deferred style 8376 // | renderLotsOfData(someDataObj).then(null, function(){ 8377 // | promptUserToRecover(); 8378 // | }); 8379 // 8380 // Note that the caller doesn't have to change his code at all to 8381 // handle the asynchronous case. 8382 8383 var result, finished, canceled, fired, isError, head, nextListener; 8384 var promise = (this.promise = new Promise()); 8385 8386 function complete(value){ 8387 if(finished){ 8388 throw new Error("This deferred has already been resolved"); 8389 } 8390 result = value; 8391 finished = true; 8392 notify(); 8393 } 8394 function notify(){ 8395 var mutated; 8396 while(!mutated && nextListener){ 8397 var listener = nextListener; 8398 nextListener = nextListener.next; 8399 if((mutated = (listener.progress == mutator))){ // assignment and check 8400 finished = false; 8401 } 8402 8403 var func = (isError ? listener.error : listener.resolved); 8404 if(has("config-useDeferredInstrumentation")){ 8405 if(isError && NewDeferred.instrumentRejected){ 8406 NewDeferred.instrumentRejected(result, !!func); 8407 } 8408 } 8409 if(func){ 8410 try{ 8411 var newResult = func(result); 8412 if (newResult && typeof newResult.then === "function"){ 8413 newResult.then(lang.hitch(listener.deferred, "resolve"), lang.hitch(listener.deferred, "reject"), lang.hitch(listener.deferred, "progress")); 8414 continue; 8415 } 8416 var unchanged = mutated && newResult === undefined; 8417 if(mutated && !unchanged){ 8418 isError = newResult instanceof Error; 8419 } 8420 listener.deferred[unchanged && isError ? "reject" : "resolve"](unchanged ? result : newResult); 8421 }catch(e){ 8422 listener.deferred.reject(e); 8423 } 8424 }else{ 8425 if(isError){ 8426 listener.deferred.reject(result); 8427 }else{ 8428 listener.deferred.resolve(result); 8429 } 8430 } 8431 } 8432 } 8433 8434 this.isResolved = promise.isResolved = function(){ 8435 // summary: 8436 // Checks whether the deferred has been resolved. 8437 // returns: Boolean 8438 8439 return fired == 0; 8440 }; 8441 8442 this.isRejected = promise.isRejected = function(){ 8443 // summary: 8444 // Checks whether the deferred has been rejected. 8445 // returns: Boolean 8446 8447 return fired == 1; 8448 }; 8449 8450 this.isFulfilled = promise.isFulfilled = function(){ 8451 // summary: 8452 // Checks whether the deferred has been resolved or rejected. 8453 // returns: Boolean 8454 8455 return fired >= 0; 8456 }; 8457 8458 this.isCanceled = promise.isCanceled = function(){ 8459 // summary: 8460 // Checks whether the deferred has been canceled. 8461 // returns: Boolean 8462 8463 return canceled; 8464 }; 8465 8466 // calling resolve will resolve the promise 8467 this.resolve = this.callback = function(value){ 8468 // summary: 8469 // Fulfills the Deferred instance successfully with the provide value 8470 this.fired = fired = 0; 8471 this.results = [value, null];
8472 complete(value); 8473 }; 8474 8475 8476 // calling error will indicate that the promise failed 8477 this.reject = this.errback = function(error){ 8478 // summary: 8479 // Fulfills the Deferred instance as an error with the provided error 8480 isError = true; 8481 this.fired = fired = 1; 8482 if(has("config-useDeferredInstrumentation")){ 8483 if(NewDeferred.instrumentRejected){ 8484 NewDeferred.instrumentRejected(error, !!nextListener); 8485 } 8486 } 8487 complete(error); 8488 this.results = [null, error]; 8489 }; 8490 // call progress to provide updates on the progress on the completion of the promise 8491 this.progress = function(update){ 8492 // summary: 8493 // Send progress events to all listeners 8494 var listener = nextListener; 8495 while(listener){ 8496 var progress = listener.progress; 8497 progress && progress(update); 8498 listener = listener.next; 8499 } 8500 }; 8501 this.addCallbacks = function(callback, errback){ 8502 // summary: 8503 // Adds callback and error callback for this deferred instance. 8504 // callback: Function? 8505 // The callback attached to this deferred object. 8506 // errback: Function? 8507 // The error callback attached to this deferred object. 8508 // returns: 8509 // Returns this deferred object. 8510 this.then(callback, errback, mutator); 8511 return this; // Deferred 8512 }; 8513 // provide the implementation of the promise 8514 promise.then = this.then = function(/*Function?*/resolvedCallback, /*Function?*/errorCallback, /*Function?*/progressCallback){ 8515 // summary: 8516 // Adds a fulfilledHandler, errorHandler, and progressHandler to be called for 8517 // completion of a promise. The fulfilledHandler is called when the promise 8518 // is fulfilled. The errorHandler is called when a promise fails. The 8519 // progressHandler is called for progress events. All arguments are optional 8520 // and non-function values are ignored. The progressHandler is not only an 8521 // optional argument, but progress events are purely optional. Promise 8522 // providers are not required to ever create progress events. 8523 // 8524 // This function will return a new promise that is fulfilled when the given 8525 // fulfilledHandler or errorHandler callback is finished. This allows promise 8526 // operations to be chained together. The value returned from the callback 8527 // handler is the fulfillment value for the returned promise. If the callback 8528 // throws an error, the returned promise will be moved to failed state. 8529 // 8530 // returns: 8531 // Returns a new promise that represents the result of the 8532 // execution of the callback. The callbacks will never affect the original promises value. 8533 // example: 8534 // An example of using a CommonJS compliant promise: 8535 // | asyncComputeTheAnswerToEverything(). 8536 // | then(addTwo). 8537 // | then(printResult, onError); 8538 // | >44 8539 // 8540 var returnDeferred = progressCallback == mutator ? this : new Deferred(promise.cancel); 8541 var listener = { 8542 resolved: resolvedCallback, 8543 error: errorCallback, 8544 progress: progressCallback, 8545 deferred: returnDeferred 8546 }; 8547 if(nextListener){ 8548 head = head.next = listener; 8549 } 8550 else{ 8551 nextListener = head = listener; 8552 } 8553 if(finished){ 8554 notify(); 8555 } 8556 return returnDeferred.promise; // Promise 8557 }; 8558 var deferred = this; 8559 promise.cancel = this.cancel = function(){ 8560 // summary: 8561 // Cancels the asynchronous operation 8562 if(!finished){ 8563 var error = canceller && canceller(deferred); 8564 if(!finished){ 8565 if (!(error instanceof Error)){ 8566 error = new CancelError(error); 8567 } 8568 error.log = false; 8569 deferred.reject(error); 8570 } 8571 } 8572 canceled = true; 8573 }; 8574 freeze(promise); 8575 }; 8576 lang.extend(Deferred, { 8577 addCallback: function(/*Function*/ callback){ 8578 // summary: 8579 // Adds successful callback for this deferred instance. 8580 // returns: 8581 // Returns this deferred object. 8582 return this.addCallbacks(lang.hitch.apply(dojo, arguments)); // Deferred 8583 }, 8584 8585 addErrback: function(/*Function*/ errback){ 8586 // summary: 8587 // Adds error callback for this deferred instance. 8588 // returns: 8589 // Returns this deferred object. 8590 return this.addCallbacks(null, lang.hitch.apply(dojo, arguments)); // Deferred 8591 }, 8592 8593 addBoth: function(/*Function*/ callback){ 8594 // summary:
vendor: 8,083 bytes, lines 8595-8859
8595 // Add handler as both successful callback and error callback for this deferred instance. 8596 // returns: 8597 // Returns this deferred object. 8598 var enclosed = lang.hitch.apply(dojo, arguments); 8599 return this.addCallbacks(enclosed, enclosed); // Deferred 8600 }, 8601 fired: -1 8602 }); 8603 8604 Deferred.when = dojo.when = when; 8605 8606 return Deferred; 8607}); 8608 8609}, 8610'dojo/Deferred':function(){ 8611define([ 8612 "./has", 8613 "./_base/lang", 8614 "./errors/CancelError", 8615 "./promise/Promise", 8616 "require" 8617], function(has, lang, CancelError, Promise, instrumentation){ 8618 "use strict"; 8619 8620 // module: 8621 // dojo/Deferred 8622 8623 var PROGRESS = 0, 8624 RESOLVED = 1, 8625 REJECTED = 2; 8626 var FULFILLED_ERROR_MESSAGE = "This deferred has already been fulfilled."; 8627 8628 var freezeObject = Object.freeze || function(){}; 8629 8630 var signalWaiting = function(waiting, type, result, rejection, deferred){ 8631 if( 0 ){ 8632 if(type === REJECTED && Deferred.instrumentRejected && waiting.length === 0){ 8633 Deferred.instrumentRejected(result, false, rejection, deferred); 8634 } 8635 } 8636 8637 for(var i = 0; i < waiting.length; i++){ 8638 signalListener(waiting[i], type, result, rejection); 8639 } 8640 }; 8641 8642 var signalListener = function(listener, type, result, rejection){ 8643 var func = listener[type]; 8644 var deferred = listener.deferred; 8645 if(func){ 8646 try{ 8647 var newResult = func(result); 8648 if(type === PROGRESS){ 8649 if(typeof newResult !== "undefined"){ 8650 signalDeferred(deferred, type, newResult); 8651 } 8652 }else{ 8653 if(newResult && typeof newResult.then === "function"){ 8654 listener.cancel = newResult.cancel; 8655 newResult.then( 8656 // Only make resolvers if they're actually going to be used 8657 makeDeferredSignaler(deferred, RESOLVED), 8658 makeDeferredSignaler(deferred, REJECTED), 8659 makeDeferredSignaler(deferred, PROGRESS)); 8660 return; 8661 } 8662 signalDeferred(deferred, RESOLVED, newResult); 8663 } 8664 }catch(error){ 8665 signalDeferred(deferred, REJECTED, error); 8666 } 8667 }else{ 8668 signalDeferred(deferred, type, result); 8669 } 8670 8671 if( 0 ){ 8672 if(type === REJECTED && Deferred.instrumentRejected){ 8673 Deferred.instrumentRejected(result, !!func, rejection, deferred.promise); 8674 } 8675 } 8676 }; 8677 8678 var makeDeferredSignaler = function(deferred, type){ 8679 return function(value){ 8680 signalDeferred(deferred, type, value); 8681 }; 8682 }; 8683 8684 var signalDeferred = function(deferred, type, result){ 8685 if(!deferred.isCanceled()){ 8686 switch(type){ 8687 case PROGRESS: 8688 deferred.progress(result); 8689 break; 8690 case RESOLVED: 8691 deferred.resolve(result); 8692 break; 8693 case REJECTED: 8694 deferred.reject(result); 8695 break; 8696 } 8697 } 8698 }; 8699 8700 var Deferred = function(canceler){ 8701 // summary: 8702 // Creates a new deferred. This API is preferred over 8703 // `dojo/_base/Deferred`. 8704 // description: 8705 // Creates a new deferred, as an abstraction over (primarily) 8706 // asynchronous operations. The deferred is the private interface 8707 // that should not be returned to calling code. That's what the 8708 // `promise` is for. See `dojo/promise/Promise`. 8709 // canceler: Function? 8710 // Will be invoked if the deferred is canceled. The canceler 8711 // receives the reason the deferred was canceled as its argument. 8712 // The deferred is rejected with its return value, or a new 8713 // `dojo/errors/CancelError` instance. 8714 8715 // promise: dojo/promise/Promise 8716 // The public promise object that clients can add callbacks to. 8717 var promise = this.promise = new Promise(); 8718 8719 var deferred = this; 8720 var fulfilled, result, rejection; 8721 var canceled = false; 8722 var waiting = []; 8723 8724 if( 0 && Error.captureStackTrace){ 8725 Error.captureStackTrace(deferred, Deferred); 8726 Error.captureStackTrace(promise, Deferred); 8727 } 8728 8729 this.isResolved = promise.isResolved = function(){ 8730 // summary: 8731 // Checks whether the deferred has been resolved. 8732 // returns: Boolean 8733 8734 return fulfilled === RESOLVED; 8735 }; 8736 8737 this.isRejected = promise.isRejected = function(){ 8738 // summary: 8739 // Checks whether the deferred has been rejected. 8740 // returns: Boolean 8741 8742 return fulfilled === REJECTED; 8743 }; 8744 8745 this.isFulfilled = promise.isFulfilled = function(){ 8746 // summary: 8747 // Checks whether the deferred has been resolved or rejected. 8748 // returns: Boolean 8749 8750 return !!fulfilled; 8751 }; 8752 8753 this.isCanceled = promise.isCanceled = function(){ 8754 // summary: 8755 // Checks whether the deferred has been canceled. 8756 // returns: Boolean 8757 8758 return canceled; 8759 }; 8760 8761 this.progress = function(update, strict){ 8762 // summary: 8763 // Emit a progress update on the deferred. 8764 // description: 8765 // Emit a progress update on the deferred. Progress updates 8766 // can be used to communicate updates about the asynchronous 8767 // operation before it has finished. 8768 // update: any 8769 // The progress update. Passed to progbacks. 8770 // strict: Boolean? 8771 // If strict, will throw an error if the deferred has already 8772 // been fulfilled and consequently no progress can be emitted. 8773 // returns: dojo/promise/Promise 8774 // Returns the original promise for the deferred. 8775 8776 if(!fulfilled){ 8777 signalWaiting(waiting, PROGRESS, update, null, deferred); 8778 return promise; 8779 }else if(strict === true){ 8780 throw new Error(FULFILLED_ERROR_MESSAGE); 8781 }else{ 8782 return promise; 8783 } 8784 }; 8785 8786 this.resolve = function(value, strict){ 8787 // summary: 8788 // Resolve the deferred. 8789 // description: 8790 // Resolve the deferred, putting it in a success state. 8791 // value: any 8792 // The result of the deferred. Passed to callbacks. 8793 // strict: Boolean? 8794 // If strict, will throw an error if the deferred has already 8795 // been fulfilled and consequently cannot be resolved. 8796 // returns: dojo/promise/Promise 8797 // Returns the original promise for the deferred. 8798 8799 if(!fulfilled){ 8800 // Set fulfilled, store value. After signaling waiting listeners unset 8801 // waiting. 8802 signalWaiting(waiting, fulfilled = RESOLVED, result = value, null, deferred); 8803 waiting = null; 8804 return promise; 8805 }else if(strict === true){ 8806 throw new Error(FULFILLED_ERROR_MESSAGE); 8807 }else{ 8808 return promise; 8809 } 8810 }; 8811 8812 var reject = this.reject = function(error, strict){ 8813 // summary: 8814 // Reject the deferred. 8815 // description: 8816 // Reject the deferred, putting it in an error state. 8817 // error: any 8818 // The error result of the deferred. Passed to errbacks. 8819 // strict: Boolean? 8820 // If strict, will throw an error if the deferred has already 8821 // been fulfilled and consequently cannot be rejected. 8822 // returns: dojo/promise/Promise 8823 // Returns the original promise for the deferred. 8824 8825 if(!fulfilled){ 8826 if( 0 && Error.captureStackTrace){ 8827 Error.captureStackTrace(rejection = {}, reject); 8828 } 8829 signalWaiting(waiting, fulfilled = REJECTED, result = error, rejection, deferred); 8830 waiting = null; 8831 return promise; 8832 }else if(strict === true){ 8833 throw new Error(FULFILLED_ERROR_MESSAGE); 8834 }else{ 8835 return promise; 8836 } 8837 }; 8838 8839 this.then = promise.then = function(callback, errback, progback){ 8840 // summary: 8841 // Add new callbacks to the deferred. 8842 // description: 8843 // Add new callbacks to the deferred. Callbacks can be added 8844 // before or after the deferred is fulfilled. 8845 // callback: Function? 8846 // Callback to be invoked when the promise is resolved. 8847 // Receives the resolution value. 8848 // errback: Function? 8849 // Callback to be invoked when the promise is rejected. 8850 // Receives the rejection error. 8851 // progback: Function? 8852 // Callback to be invoked when the promise emits a progress 8853 // update. Receives the progress update. 8854 // returns: dojo/promise/Promise 8855 // Returns a new promise for the result of the callback(s). 8856 // This can be used for chaining many asynchronous operations. 8857 8858 var listener = [progback, callback, errback]; 8859 // Ensure we cancel the promise we're waiting for, or if callback/errback
8860 // have returned a promise, cancel that one. 8861 listener.cancel = promise.cancel; 8862 listener.deferred = new Deferred(function(reason){ 8863 // Check whether cancel is really available, returned promises are not 8864 // required to expose `cancel` 8865 return listener.cancel && listener.cancel(reason); 8866 }); 8867 if(fulfilled && !waiting){ 8868 signalListener(listener, fulfilled, result, rejection); 8869 }else{ 8870 waiting.push(listener); 8871 } 8872 return listener.deferred.promise; 8873 }; 8874 8875 this.cancel = promise.cancel = function(reason, strict){ 8876 // summary: 8877 // Inform the deferred it may cancel its asynchronous operation. 8878 // description: 8879 // Inform the deferred it may cancel its asynchronous operation. 8880 // The deferred's (optional) canceler is invoked and the 8881 // deferred will be left in a rejected state. Can affect other 8882 // promises that originate with the same deferred. 8883 // reason: any 8884 // A message that may be sent to the deferred's canceler, 8885 // explaining why it's being canceled. 8886 // strict: Boolean? 8887 // If strict, will throw an error if the deferred has already 8888 // been fulfilled and consequently cannot be canceled. 8889 // returns: any 8890 // Returns the rejection reason if the deferred was canceled 8891 // normally. 8892 8893 if(!fulfilled){ 8894 // Cancel can be called even after the deferred is fulfilled 8895 if(canceler){ 8896 var returnedReason = canceler(reason); 8897 reason = typeof returnedReason === "undefined" ? reason : returnedReason; 8898 } 8899 canceled = true; 8900 if(!fulfilled){ 8901 // Allow canceler to provide its own reason, but fall back to a CancelError 8902 if(typeof reason === "undefined"){ 8903 reason = new CancelError(); 8904 } 8905 reject(reason); 8906 return reason; 8907 }else if(fulfilled === REJECTED && result === reason){ 8908 return reason; 8909 } 8910 }else if(strict === true){ 8911 throw new Error(FULFILLED_ERROR_MESSAGE); 8912 } 8913 }; 8914 8915 freezeObject(promise); 8916 }; 8917 8918 Deferred.prototype.toString = function(){ 8919 // returns: String 8920 // Returns `[object Deferred]`. 8921 8922 return "[object Deferred]"; 8923 }; 8924 8925 if(instrumentation){ 8926 instrumentation(Deferred); 8927 } 8928 8929 return Deferred; 8930}); 8931 8932}, 8933'dojo/errors/CancelError':function(){ 8934define(["./create"], function(create){ 8935 // module: 8936 // dojo/errors/CancelError 8937 8938 /*===== 8939 return function(){ 8940 // summary: 8941 // Default error if a promise is canceled without a reason. 8942 }; 8943 =====*/ 8944 8945 return create("CancelError", null, null, { dojoType: "cancel" }); 8946}); 8947 8948}, 8949'dojo/errors/create':function(){ 8950define(["../_base/lang"], function(lang){ 8951 return function(name, ctor, base, props){ 8952 base = base || Error; 8953 8954 var ErrorCtor = function(message){ 8955 if(base === Error){ 8956 if(Error.captureStackTrace){ 8957 Error.captureStackTrace(this, ErrorCtor); 8958 } 8959 8960 // Error.call() operates on the returned error 8961 // object rather than operating on |this| 8962 var err = Error.call(this, message), 8963 prop; 8964 8965 // Copy own properties from err to |this| 8966 for(prop in err){ 8967 if(err.hasOwnProperty(prop)){ 8968 this[prop] = err[prop]; 8969 } 8970 } 8971 8972 // messsage is non-enumerable in ES5 8973 this.message = message; 8974 // stack is non-enumerable in at least Firefox 8975 this.stack = err.stack; 8976 }else{ 8977 base.apply(this, arguments); 8978 } 8979 if(ctor){ 8980 ctor.apply(this, arguments); 8981 } 8982 }; 8983 8984 ErrorCtor.prototype = lang.delegate(base.prototype, props); 8985 ErrorCtor.prototype.name = name; 8986 ErrorCtor.prototype.constructor = ErrorCtor; 8987 8988 return ErrorCtor; 8989 }; 8990}); 8991 8992}, 8993'dojo/promise/Promise':function(){ 8994define([ 8995 "../_base/lang" 8996], function(lang){ 8997 "use strict"; 8998 8999 // module: 9000 // dojo/promise/Promise 9001 9002 function throwAbstract(){ 9003 throw new TypeError("abstract"); 9004 } 9005 9006 return lang.extend(function Promise(){ 9007 // summary: 9008 // The public interface to a deferred. 9009 // description: 9010 // The public interface to a deferred. All promises in Dojo are 9011 // instances of this class. 9012 }, { 9013 then: function(callback, errback, progback){ 9014 // summary: 9015 // Add new callbacks to the promise. 9016 // description: 9017 // Add new callbacks to the deferred. Callbacks can be added 9018 // before or after the deferred is fulfilled. 9019 // callback: Function? 9020 // Callback to be invoked when the promise is resolved. 9021 // Receives the resolution value. 9022 // errback: Function? 9023 // Callback to be invoked when the promise is rejected. 9024 // Receives the rejection error. 9025 // progback: Function? 9026 // Callback to be invoked when the promise emits a progress 9027 // update. Receives the progress update. 9028 // returns: dojo/promise/Promise 9029 // Returns a new promise for the result of the callback(s). 9030 // This can be used for chaining many asynchronous operations. 9031 9032 throwAbstract(); 9033 }, 9034 9035 cancel: function(reason, strict){ 9036 // summary: 9037 // Inform the deferred it may cancel its asynchronous operation. 9038 // description: 9039 // Inform the deferred it may cancel its asynchronous operation. 9040 // The deferred's (optional) canceler is invoked and the 9041 // deferred will be left in a rejected state. Can affect other 9042 // promises that originate with the same deferred. 9043 // reason: any 9044 // A message that may be sent to the deferred's canceler, 9045 // explaining why it's being canceled. 9046 // strict: Boolean? 9047 // If strict, will throw an error if the deferred has already 9048 // been fulfilled and consequently cannot be canceled. 9049 // returns: any 9050 // Returns the rejection reason if the deferred was canceled 9051 // normally. 9052 9053 throwAbstract(); 9054 }, 9055 9056 isResolved: function(){ 9057 // summary: 9058 // Checks whether the promise has been resolved. 9059 // returns: Boolean 9060 9061 throwAbstract(); 9062 }, 9063 9064 isRejected: function(){ 9065 // summary: 9066 // Checks whether the promise has been rejected. 9067 // returns: Boolean 9068 9069 throwAbstract(); 9070 }, 9071 9072 isFulfilled: function(){ 9073 // summary: 9074 // Checks whether the promise has been resolved or rejected. 9075 // returns: Boolean 9076 9077 throwAbstract(); 9078 }, 9079 9080 isCanceled: function(){ 9081 // summary: 9082 // Checks whether the promise has been canceled. 9083 // returns: Boolean 9084 9085 throwAbstract(); 9086 }, 9087 9088 always: function(callbackOrErrback){ 9089 // summary: 9090 // Add a callback to be invoked when the promise is resolved 9091 // or rejected. 9092 // callbackOrErrback: Function? 9093 // A function that is used both as a callback and errback. 9094 // returns: dojo/promise/Promise 9095 // Returns a new promise for the result of the callback/errback. 9096 9097 return this.then(callbackOrErrback, callbackOrErrback); 9098 }, 9099 9100 otherwise: function(errback){ 9101 // summary: 9102 // Add new errbacks to the promise. 9103 // errback: Function? 9104 // Callback to be invoked when the promise is rejected. 9105 // returns: dojo/promise/Promise 9106 // Returns a new promise for the result of the errback. 9107 9108 return this.then(null, errback); 9109 }, 9110 9111 trace: function(){ 9112 return this; 9113 }, 9114 9115 traceRejected: function(){ 9116 return this; 9117 }, 9118 9119 toString: function(){ 9120 // returns: string 9121 // Returns `[object Promise]`. 9122 9123 return "[object Promise]"; 9124 } 9125 }); 9126}); 9127 9128}, 9129'dojo/when':function(){ 9130define([ 9131 "./Deferred", 9132 "./promise/Promise" 9133], function(Deferred, Promise){
9134 "use strict"; 9135 9136 // module: 9137 // dojo/when 9138 9139 return function when(valueOrPromise, callback, errback, progback){ 9140 // summary: 9141 // Transparently applies callbacks to values and/or promises. 9142 // description: 9143 // Accepts promises but also transparently handles non-promises. If no 9144 // callbacks are provided returns a promise, regardless of the initial 9145 // value. Foreign promises are converted. 9146 // 9147 // If callbacks are provided and the initial value is not a promise, 9148 // the callback is executed immediately with no error handling. Returns 9149 // a promise if the initial value is a promise, or the result of the 9150 // callback otherwise. 9151 // valueOrPromise: 9152 // Either a regular value or an object with a `then()` method that 9153 // follows the Promises/A specification. 9154 // callback: Function? 9155 // Callback to be invoked when the promise is resolved, or a non-promise 9156 // is received. 9157 // errback: Function? 9158 // Callback to be invoked when the promise is rejected. 9159 // progback: Function? 9160 // Callback to be invoked when the promise emits a progress update. 9161 // returns: dojo/promise/Promise 9162 // Promise, or if a callback is provided, the result of the callback. 9163 9164 var receivedPromise = valueOrPromise && typeof valueOrPromise.then === "function"; 9165 var nativePromise = receivedPromise && valueOrPromise instanceof Promise; 9166 9167 if(!receivedPromise){ 9168 if(arguments.length > 1){ 9169 return callback ? callback(valueOrPromise) : valueOrPromise; 9170 }else{ 9171 return new Deferred().resolve(valueOrPromise); 9172 } 9173 }else if(!nativePromise){ 9174 var deferred = new Deferred(valueOrPromise.cancel); 9175 valueOrPromise.then(deferred.resolve, deferred.reject, deferred.progress); 9176 valueOrPromise = deferred.promise; 9177 } 9178 9179 if(callback || errback || progback){ 9180 return valueOrPromise.then(callback, errback, progback); 9181 } 9182 return valueOrPromise; 9183 }; 9184}); 9185 9186}, 9187'dojo/_base/json':function(){ 9188define(["./kernel", "../json"], function(dojo, json){ 9189 9190// module: 9191// dojo/_base/json 9192 9193/*===== 9194return { 9195 // summary: 9196 // This module defines the dojo JSON API. 9197}; 9198=====*/ 9199 9200dojo.fromJson = function(/*String*/ js){ 9201 // summary: 9202 // Parses a JavaScript expression and returns a JavaScript value. 9203 // description: 9204 // Throws for invalid JavaScript expressions. It does not use a strict JSON parser. It 9205 // always delegates to eval(). The content passed to this method must therefore come 9206 // from a trusted source. 9207 // It is recommend that you use dojo/json's parse function for an 9208 // implementation uses the (faster) native JSON parse when available. 9209 // js: 9210 // a string literal of a JavaScript expression, for instance: 9211 // `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'` 9212 9213 return eval("(" + js + ")"); // Object 9214}; 9215 9216/*===== 9217dojo._escapeString = function(){ 9218 // summary: 9219 // Adds escape sequences for non-visual characters, double quote and 9220 // backslash and surrounds with double quotes to form a valid string 9221 // literal. 9222}; 9223=====*/ 9224dojo._escapeString = json.stringify; // just delegate to json.stringify 9225 9226dojo.toJsonIndentStr = "\t"; 9227dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint){ 9228 // summary: 9229 // Returns a [JSON](http://json.org) serialization of an object. 9230 // description: 9231 // Returns a [JSON](http://json.org) serialization of an object. 9232 // Note that this doesn't check for infinite recursion, so don't do that! 9233 // It is recommend that you use dojo/json's stringify function for an lighter 9234 // and faster implementation that matches the native JSON API and uses the 9235 // native JSON serializer when available. 9236 // it: 9237 // an object to be serialized. Objects may define their own 9238 // serialization via a special "__json__" or "json" function 9239 // property. If a specialized serializer has been defined, it will 9240 // be used as a fallback. 9241 // Note that in 1.6, toJson would serialize undefined, but this no longer supported 9242 // since it is not supported by native JSON serializer. 9243 // prettyPrint: 9244 // if true, we indent objects and arrays to make the output prettier. 9245 // The variable `dojo.toJsonIndentStr` is used as the indent string -- 9246 // to use something other than the default (tab), change that variable 9247 // before calling dojo.toJson(). 9248 // Note that if native JSON support is available, it will be used for serialization, 9249 // and native implementations vary on the exact spacing used in pretty printing. 9250 // returns: 9251 // A JSON string serialization of the passed-in object. 9252 // example: 9253 // simple serialization of a trivial object 9254 // | var jsonStr = dojo.toJson({ howdy: "stranger!", isStrange: true });
vendor: 6,903 bytes, lines 9255-9448
9255 // | doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr); 9256 // example: 9257 // a custom serializer for an objects of a particular class: 9258 // | dojo.declare("Furby", null, { 9259 // | furbies: "are strange", 9260 // | furbyCount: 10, 9261 // | __json__: function(){ 9262 // | }, 9263 // | }); 9264 9265 // use dojo/json 9266 return json.stringify(it, function(key, value){ 9267 if(value){ 9268 var tf = value.__json__||value.json; 9269 if(typeof tf == "function"){ 9270 return tf.call(value); 9271 } 9272 } 9273 return value; 9274 }, prettyPrint && dojo.toJsonIndentStr); // String 9275}; 9276 9277return dojo; 9278}); 9279 9280}, 9281'dojo/json':function(){ 9282define(["./has"], function(has){ 9283 "use strict"; 9284 var hasJSON = typeof JSON != "undefined"; 9285 has.add("json-parse", hasJSON); // all the parsers work fine 9286 // Firefox 3.5/Gecko 1.9 fails to use replacer in stringify properly https://bugzilla.mozilla.org/show_bug.cgi?id=509184 9287 has.add("json-stringify", hasJSON && JSON.stringify({a:0}, function(k,v){return v||1;}) == '{"a":1}'); 9288 9289 /*===== 9290 return { 9291 // summary: 9292 // Functions to parse and serialize JSON 9293 9294 parse: function(str, strict){ 9295 // summary: 9296 // Parses a [JSON](http://json.org) string to return a JavaScript object. 9297 // description: 9298 // This function follows [native JSON API](https://developer.mozilla.org/en/JSON) 9299 // Throws for invalid JSON strings. This delegates to eval() if native JSON 9300 // support is not available. By default this will evaluate any valid JS expression. 9301 // With the strict parameter set to true, the parser will ensure that only 9302 // valid JSON strings are parsed (otherwise throwing an error). Without the strict 9303 // parameter, the content passed to this method must come 9304 // from a trusted source. 9305 // str: 9306 // a string literal of a JSON item, for instance: 9307 // `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'` 9308 // strict: 9309 // When set to true, this will ensure that only valid, secure JSON is ever parsed. 9310 // Make sure this is set to true for untrusted content. Note that on browsers/engines 9311 // without native JSON support, setting this to true will run slower. 9312 }, 9313 stringify: function(value, replacer, spacer){ 9314 // summary: 9315 // Returns a [JSON](http://json.org) serialization of an object. 9316 // description: 9317 // Returns a [JSON](http://json.org) serialization of an object. 9318 // This function follows [native JSON API](https://developer.mozilla.org/en/JSON) 9319 // Note that this doesn't check for infinite recursion, so don't do that! 9320 // value: 9321 // A value to be serialized. 9322 // replacer: 9323 // A replacer function that is called for each value and can return a replacement 9324 // spacer: 9325 // A spacer string to be used for pretty printing of JSON 9326 // example: 9327 // simple serialization of a trivial object 9328 // | define(["dojo/json"], function(JSON){ 9329 // | var jsonStr = JSON.stringify({ howdy: "stranger!", isStrange: true }); 9330 // | doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr); 9331 } 9332 }; 9333 =====*/ 9334 9335 if(has("json-stringify")){ 9336 return JSON; 9337 }else{ 9338 var escapeString = function(/*String*/str){ 9339 // summary: 9340 // Adds escape sequences for non-visual characters, double quote and 9341 // backslash and surrounds with double quotes to form a valid string 9342 // literal. 9343 return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'). 9344 replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n"). 9345 replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string 9346 }; 9347 return { 9348 parse: has("json-parse") ? JSON.parse : function(str, strict){ 9349 if(strict && !/^([\s\[\{]*(?:"(?:\\.|[^"])*"|-?\d[\d\.]*(?:[Ee][+-]?\d+)?|null|true|false|)[\s\]\}]*(?:,|:|$))+$/.test(str)){ 9350 throw new SyntaxError("Invalid characters in JSON"); 9351 } 9352 return eval('(' + str + ')'); 9353 }, 9354 stringify: function(value, replacer, spacer){ 9355 var undef; 9356 if(typeof replacer == "string"){ 9357 spacer = replacer; 9358 replacer = null; 9359 } 9360 function stringify(it, indent, key){ 9361 if(replacer){ 9362 it = replacer(key, it); 9363 } 9364 var val, objtype = typeof it; 9365 if(objtype == "number"){ 9366 return isFinite(it) ? it + "" : "null"; 9367 } 9368 if(objtype == "boolean"){ 9369 return it + ""; 9370 } 9371 if(it === null){ 9372 return "null"; 9373 } 9374 if(typeof it == "string"){ 9375 return escapeString(it); 9376 } 9377 if(objtype == "function" || objtype == "undefined"){ 9378 return undef; // undefined 9379 } 9380 // short-circuit for objects that support "json" serialization 9381 // if they return "self" then just pass-through... 9382 if(typeof it.toJSON == "function"){ 9383 return stringify(it.toJSON(key), indent, key); 9384 } 9385 if(it instanceof Date){ 9386 return '"{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z"'.replace(/\{(\w+)(\+)?\}/g, function(t, prop, plus){ 9387 var num = it["getUTC" + prop]() + (plus ? 1 : 0); 9388 return num < 10 ? "0" + num : num; 9389 }); 9390 } 9391 if(it.valueOf() !== it){ 9392 // primitive wrapper, try again unwrapped: 9393 return stringify(it.valueOf(), indent, key); 9394 } 9395 var nextIndent= spacer ? (indent + spacer) : ""; 9396 /* we used to test for DOM nodes and throw, but FF serializes them as {}, so cross-browser consistency is probably not efficiently attainable */ 9397 9398 var sep = spacer ? " " : ""; 9399 var newLine = spacer ? "\n" : ""; 9400 9401 // array 9402 if(it instanceof Array){ 9403 var itl = it.length, res = []; 9404 for(key = 0; key < itl; key++){ 9405 var obj = it[key]; 9406 val = stringify(obj, nextIndent, key); 9407 if(typeof val != "string"){ 9408 val = "null"; 9409 } 9410 res.push(newLine + nextIndent + val); 9411 } 9412 return "[" + res.join(",") + newLine + indent + "]"; 9413 } 9414 // generic object code path 9415 var output = []; 9416 for(key in it){ 9417 var keyStr; 9418 if(it.hasOwnProperty(key)){ 9419 if(typeof key == "number"){ 9420 keyStr = '"' + key + '"'; 9421 }else if(typeof key == "string"){ 9422 keyStr = escapeString(key); 9423 }else{ 9424 // skip non-string or number keys 9425 continue; 9426 } 9427 val = stringify(it[key], nextIndent, key); 9428 if(typeof val != "string"){ 9429 // skip non-serializable values 9430 continue; 9431 } 9432 // At this point, the most non-IE browsers don't get in this branch 9433 // (they have native JSON), so push is definitely the way to 9434 output.push(newLine + nextIndent + keyStr + ":" + sep + val); 9435 } 9436 } 9437 return "{" + output.join(",") + newLine + indent + "}"; // String 9438 } 9439 return stringify(value, "", ""); 9440 } 9441 }; 9442 } 9443}); 9444 9445}, 9446'dojo/_base/Color':function(){ 9447define(["./kernel", "./lang", "./array", "./config"], function(dojo, lang, ArrayUtil, config){ 9448
9449 var Color = dojo.Color = function(/*Array|String|Object*/ color){ 9450 // summary: 9451 // Takes a named string, hex string, array of rgb or rgba values, 9452 // an object with r, g, b, and a properties, or another `Color` object 9453 // and creates a new Color instance to work from. 9454 // 9455 // example: 9456 // Work with a Color instance: 9457 // | require(["dojo/_base/color"], function(Color){ 9458 // | var c = new Color(); 9459 // | c.setColor([0,0,0]); // black 9460 // | var hex = c.toHex(); // #000000 9461 // | }); 9462 // 9463 // example: 9464 // Work with a node's color: 9465 // | 9466 // | require(["dojo/_base/color", "dojo/dom-style"], function(Color, domStyle){ 9467 // | var color = domStyle("someNode", "backgroundColor"); 9468 // | var n = new Color(color); 9469 // | // adjust the color some 9470 // | n.r *= .5; 9471 // | console.log(n.toString()); // rgb(128, 255, 255); 9472 // | }); 9473 if(color){ this.setColor(color); } 9474 }; 9475 9476 // FIXME: 9477 // there's got to be a more space-efficient way to encode or discover 9478 // these!! Use hex? 9479 Color.named = { 9480 // summary: 9481 // Dictionary list of all CSS named colors, by name. Values are 3-item arrays with corresponding RG and B values. 9482 "black": [0,0,0], 9483 "silver": [192,192,192], 9484 "gray": [128,128,128], 9485 "white": [255,255,255], 9486 "maroon": [128,0,0], 9487 "red": [255,0,0], 9488 "purple": [128,0,128], 9489 "fuchsia":[255,0,255], 9490 "green": [0,128,0], 9491 "lime": [0,255,0], 9492 "olive": [128,128,0], 9493 "yellow": [255,255,0], 9494 "navy": [0,0,128], 9495 "blue": [0,0,255], 9496 "teal": [0,128,128], 9497 "aqua": [0,255,255], 9498 "transparent": config.transparentColor || [0,0,0,0] 9499 }; 9500 9501 lang.extend(Color, { 9502 r: 255, g: 255, b: 255, a: 1, 9503 _set: function(r, g, b, a){ 9504 var t = this; t.r = r; t.g = g; t.b = b; t.a = a; 9505 }, 9506 setColor: function(/*Array|String|Object*/ color){ 9507 // summary: 9508 // Takes a named string, hex string, array of rgb or rgba values, 9509 // an object with r, g, b, and a properties, or another `Color` object 9510 // and sets this color instance to that value. 9511 // 9512 // example: 9513 // | require(["dojo/_base/color"], function(Color){ 9514 // | var c = new Color(); // no color 9515 // | c.setColor("#ededed"); // greyish 9516 // | }); 9517 if(lang.isString(color)){ 9518 Color.fromString(color, this); 9519 }else if(lang.isArray(color)){ 9520 Color.fromArray(color, this); 9521 }else{ 9522 this._set(color.r, color.g, color.b, color.a); 9523 if(!(color instanceof Color)){ this.sanitize(); } 9524 } 9525 return this; // Color 9526 }, 9527 sanitize: function(){ 9528 // summary: 9529 // Ensures the object has correct attributes 9530 // description: 9531 // the default implementation does nothing, include dojo.colors to 9532 // augment it with real checks 9533 return this; // Color 9534 }, 9535 toRgb: function(){ 9536 // summary: 9537 // Returns 3 component array of rgb values 9538 // example: 9539 // | require(["dojo/_base/color"], function(Color){ 9540 // | var c = new Color("#000000"); 9541 // | console.log(c.toRgb()); // [0,0,0] 9542 // | }); 9543 var t = this; 9544 return [t.r, t.g, t.b]; // Array 9545 }, 9546 toRgba: function(){ 9547 // summary: 9548 // Returns a 4 component array of rgba values from the color 9549 // represented by this object. 9550 var t = this; 9551 return [t.r, t.g, t.b, t.a]; // Array 9552 }, 9553 toHex: function(){ 9554 // summary: 9555 // Returns a CSS color string in hexadecimal representation 9556 // example: 9557 // | require(["dojo/_base/color"], function(Color){ 9558 // | console.log(new Color([0,0,0]).toHex()); // #000000 9559 // | }); 9560 var arr = ArrayUtil.map(["r", "g", "b"], function(x){ 9561 var s = this[x].toString(16); 9562 return s.length < 2 ? "0" + s : s; 9563 }, this); 9564 return "#" + arr.join(""); // String 9565 }, 9566 toCss: function(/*Boolean?*/ includeAlpha){ 9567 // summary: 9568 // Returns a css color string in rgb(a) representation 9569 // example: 9570 // | require(["dojo/_base/color"], function(Color){ 9571 // | var c = new Color("#FFF").toCss(); 9572 // | console.log(c); // rgb('255','255','255') 9573 // | }); 9574 var t = this, rgb = t.r + ", " + t.g + ", " + t.b; 9575 return (includeAlpha ? "rgba(" + rgb + ", " + t.a : "rgb(" + rgb) + ")"; // String 9576 }, 9577 toString: function(){ 9578 // summary: 9579 // Returns a visual representation of the color 9580 return this.toCss(true); // String 9581 } 9582 }); 9583 9584 Color.blendColors = dojo.blendColors = function( 9585 /*Color*/ start, 9586 /*Color*/ end, 9587 /*Number*/ weight, 9588 /*Color?*/ obj 9589 ){ 9590 // summary: 9591 // Blend colors end and start with weight from 0 to 1, 0.5 being a 50/50 blend, 9592 // can reuse a previously allocated Color object for the result 9593 var t = obj || new Color(); 9594 ArrayUtil.forEach(["r", "g", "b", "a"], function(x){ 9595 t[x] = start[x] + (end[x] - start[x]) * weight; 9596 if(x != "a"){ t[x] = Math.round(t[x]); } 9597 }); 9598 return t.sanitize(); // Color 9599 }; 9600 9601 Color.fromRgb = dojo.colorFromRgb = function(/*String*/ color, /*Color?*/ obj){ 9602 // summary:
9603 // Returns a `Color` instance from a string of the form 9604 // "rgb(...)" or "rgba(...)". Optionally accepts a `Color` 9605 // object to update with the parsed value and return instead of 9606 // creating a new object. 9607 // returns: 9608 // A Color object. If obj is passed, it will be the return value. 9609 var m = color.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/); 9610 return m && Color.fromArray(m[1].split(/\s*,\s*/), obj); // Color 9611 }; 9612 9613 Color.fromHex = dojo.colorFromHex = function(/*String*/ color, /*Color?*/ obj){ 9614 // summary: 9615 // Converts a hex string with a '#' prefix to a color object. 9616 // Supports 12-bit #rgb shorthand. Optionally accepts a 9617 // `Color` object to update with the parsed value. 9618 // 9619 // returns: 9620 // A Color object. If obj is passed, it will be the return value. 9621 // 9622 // example: 9623 // | require(["dojo/_base/color"], function(Color){ 9624 // | var thing = new Color().fromHex("#ededed"); // grey, longhand 9625 // | var thing2 = new Color().fromHex("#000"); // black, shorthand 9626 // | }); 9627 var t = obj || new Color(), 9628 bits = (color.length == 4) ? 4 : 8, 9629 mask = (1 << bits) - 1; 9630 color = Number("0x" + color.substr(1)); 9631 if(isNaN(color)){ 9632 return null; // Color 9633 } 9634 ArrayUtil.forEach(["b", "g", "r"], function(x){ 9635 var c = color & mask; 9636 color >>= bits; 9637 t[x] = bits == 4 ? 17 * c : c; 9638 }); 9639 t.a = 1; 9640 return t; // Color 9641 }; 9642 9643 Color.fromArray = dojo.colorFromArray = function(/*Array*/ a, /*Color?*/ obj){ 9644 // summary: 9645 // Builds a `Color` from a 3 or 4 element array, mapping each 9646 // element in sequence to the rgb(a) values of the color. 9647 // example: 9648 // | require(["dojo/_base/color"], function(Color){ 9649 // | var myColor = new Color().fromArray([237,237,237,0.5]); // grey, 50% alpha 9650 // | }); 9651 // returns: 9652 // A Color object. If obj is passed, it will be the return value. 9653 var t = obj || new Color(); 9654 t._set(Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3])); 9655 if(isNaN(t.a)){ t.a = 1; } 9656 return t.sanitize(); // Color 9657 }; 9658 9659 Color.fromString = dojo.colorFromString = function(/*String*/ str, /*Color?*/ obj){ 9660 // summary: 9661 // Parses `str` for a color value. Accepts hex, rgb, and rgba 9662 // style color values. 9663 // description: 9664 // Acceptable input values for str may include arrays of any form 9665 // accepted by dojo.colorFromArray, hex strings such as "#aaaaaa", or 9666 // rgb or rgba strings such as "rgb(133, 200, 16)" or "rgba(10, 10, 9667 // 10, 50)" 9668 // returns: 9669 // A Color object. If obj is passed, it will be the return value. 9670 var a = Color.named[str]; 9671 return a && Color.fromArray(a, obj) || Color.fromRgb(str, obj) || Color.fromHex(str, obj); // Color 9672 }; 9673 9674 return Color; 9675}); 9676 9677}, 9678'dojo/_base/browser':function(){ 9679if(require.has){ 9680 require.has.add("config-selectorEngine", "acme"); 9681} 9682define([ 9683 "../ready", 9684 "./kernel", 9685 "./connect", // until we decide if connect is going back into non-browser environments 9686 "./unload", 9687 "./window", 9688 "./event", 9689 "./html", 9690 "./NodeList", 9691 "../query", 9692 "./xhr", 9693 "./fx"], function(dojo){ 9694 9695 // module: 9696 // dojo/_base/browser 9697 9698 /*===== 9699 return { 9700 // summary: 9701 // This module causes the browser-only base modules to be loaded. 9702 }; 9703 =====*/ 9704 9705 return dojo; 9706}); 9707 9708}, 9709'dojo/_base/unload':function(){ 9710define(["./kernel", "./lang", "../on"], function(dojo, lang, on){ 9711 9712// module: 9713// dojo/unload 9714 9715var win = window; 9716 9717var unload = { 9718 // summary: 9719 // This module contains the document and window unload detection API. 9720 // This module is deprecated. Use on(window, "unload", func) 9721 // and on(window, "beforeunload", func) instead. 9722 9723 addOnWindowUnload: function(/*Object|Function?*/ obj, /*String|Function?*/ functionName){ 9724 // summary: 9725 // Registers a function to be triggered when window.onunload fires. 9726 // Deprecated, use on(window, "unload", lang.hitch(obj, functionName)) instead. 9727 // description: 9728 // The first time that addOnWindowUnload is called Dojo 9729 // will register a page listener to trigger your unload 9730 // handler with. Note that registering these handlers may 9731 // destroy "fastback" page caching in browsers that support 9732 // it. Be careful trying to modify the DOM or access 9733 // JavaScript properties during this phase of page unloading: 9734 // they may not always be available. Consider 9735 // addOnUnload() if you need to modify the DOM or do 9736 // heavy JavaScript work since it fires at the equivalent of 9737 // the page's "onbeforeunload" event. 9738 // example: 9739 // | var afunc = function() {console.log("global function");}; 9740 // | require(["dojo/_base/unload"], function(unload) { 9741 // | var foo = {bar: function(){ console.log("bar unloading...");}, 9742 // | data: "mydata"}; 9743 // | unload.addOnWindowUnload(afunc); 9744 // | unload.addOnWindowUnload(foo, "bar"); 9745 // | unload.addOnWindowUnload(foo, function(){console.log("", this.data);}); 9746 // | }); 9747 9748 if (!dojo.windowUnloaded){ 9749 on(win, "unload", (dojo.windowUnloaded = function(){ 9750 // summary: 9751 // signal fired by impending window destruction. You may use 9752 // dojo.addOnWindowUnload() to register a listener for this 9753 // event. NOTE: if you wish to dojo.connect() to this method 9754 // to perform page/application cleanup, be aware that this 9755 // event WILL NOT fire if no handler has been registered with 9756 // addOnWindowUnload(). This behavior started in Dojo 1.3. 9757 // Previous versions always triggered windowUnloaded(). See 9758 // addOnWindowUnload for more info. 9759 })); 9760 } 9761 on(win, "unload", lang.hitch(obj, functionName)); 9762 }, 9763 9764 addOnUnload: function(/*Object?|Function?*/ obj, /*String|Function?*/ functionName){ 9765 // summary: 9766 // Registers a function to be triggered when the page unloads. 9767 // Deprecated, use on(window, "beforeunload", lang.hitch(obj, functionName)) instead. 9768 // description: 9769 // The first time that addOnUnload is called Dojo will 9770 // register a page listener to trigger your unload handler 9771 // with. 9772 // 9773 // In a browser environment, the functions will be triggered 9774 // during the window.onbeforeunload event. Be careful of doing 9775 // too much work in an unload handler. onbeforeunload can be 9776 // triggered if a link to download a file is clicked, or if 9777 // the link is a javascript: link. In these cases, the 9778 // onbeforeunload event fires, but the document is not 9779 // actually destroyed. So be careful about doing destructive 9780 // operations in a dojo.addOnUnload callback. 9781 // 9782 // Further note that calling dojo.addOnUnload will prevent 9783 // browsers from using a "fast back" cache to make page 9784 // loading via back button instantaneous. 9785 // example: 9786 // | var afunc = function() {console.log("global function");}; 9787 // | require(["dojo/_base/unload"], function(unload) { 9788 // | var foo = {bar: function(){ console.log("bar unloading...");}, 9789 // | data: "mydata"}; 9790 // | unload.addOnUnload(afunc); 9791 // | unload.addOnUnload(foo, "bar"); 9792 // | unload.addOnUnload(foo, function(){console.log("", this.data);}); 9793 // | }); 9794 9795 on(win, "beforeunload", lang.hitch(obj, functionName)); 9796 } 9797}; 9798 9799dojo.addOnWindowUnload = unload.addOnWindowUnload; 9800dojo.addOnUnload = unload.addOnUnload; 9801 9802return unload; 9803 9804}); 9805 9806}, 9807'dojo/_base/html':function(){ 9808define(["./kernel", "../dom", "../dom-style", "../dom-attr", "../dom-prop", "../dom-class", "../dom-construct", "../dom-geometry"], function(dojo, dom, style, attr, prop, cls, ctr, geom){ 9809 // module: 9810 // dojo/dom 9811 9812 /*===== 9813 return { 9814 // summary: 9815 // This module is a stub for the core dojo DOM API. 9816 }; 9817 =====*/ 9818 9819 // mix-in dom 9820 dojo.byId = dom.byId; 9821 dojo.isDescendant = dom.isDescendant; 9822 dojo.setSelectable = dom.setSelectable; 9823 9824 // mix-in dom-attr 9825 dojo.getAttr = attr.get; 9826 dojo.setAttr = attr.set; 9827 dojo.hasAttr = attr.has; 9828 dojo.removeAttr = attr.remove; 9829 dojo.getNodeProp = attr.getNodeProp; 9830 9831 dojo.attr = function(node, name, value){ 9832 // summary: 9833 // Gets or sets an attribute on an HTML element. 9834 // description: 9835 // Handles normalized getting and setting of attributes on DOM 9836 // Nodes. If 2 arguments are passed, and a the second argument is a 9837 // string, acts as a getter. 9838 // 9839 // If a third argument is passed, or if the second argument is a 9840 // map of attributes, acts as a setter. 9841 // 9842 // When passing functions as values, note that they will not be 9843 // directly assigned to slots on the node, but rather the default 9844 // behavior will be removed and the new behavior will be added 9845 // using `dojo.connect()`, meaning that event handler properties 9846 // will be normalized and that some caveats with regards to 9847 // non-standard behaviors for onsubmit apply. Namely that you 9848 // should cancel form submission using `dojo.stopEvent()` on the 9849 // passed event object instead of returning a boolean value from 9850 // the handler itself. 9851 // node: DOMNode|String 9852 // id or reference to the element to get or set the attribute on 9853 // name: String|Object 9854 // the name of the attribute to get or set. 9855 // value: String? 9856 // The value to set for the attribute 9857 // returns: 9858 // when used as a getter, the value of the requested attribute 9859 // or null if that attribute does not have a specified or 9860 // default value; 9861 // 9862 // when used as a setter, the DOM node 9863 // 9864 // example: 9865 // | // get the current value of the "foo" attribute on a node 9866 // | dojo.attr(dojo.byId("nodeId"), "foo"); 9867 // | // or we can just pass the id: 9868 // | dojo.attr("nodeId", "foo"); 9869 // 9870 // example: 9871 // | // use attr() to set the tab index 9872 // | dojo.attr("nodeId", "tabIndex", 3); 9873 // | 9874 // 9875 // example: 9876 // Set multiple values at once, including event handlers: 9877 // | dojo.attr("formId", { 9878 // | "foo": "bar", 9879 // | "tabIndex": -1, 9880 // | "method": "POST", 9881 // | "onsubmit": function(e){
9882 // | // stop submitting the form. Note that the IE behavior 9883 // | // of returning true or false will have no effect here 9884 // | // since our handler is connect()ed to the built-in 9885 // | // onsubmit behavior and so we need to use 9886 // | // dojo.stopEvent() to ensure that the submission 9887 // | // doesn't proceed. 9888 // | dojo.stopEvent(e); 9889 // | 9890 // | // submit the form with Ajax 9891 // | dojo.xhrPost({ form: "formId" }); 9892 // | } 9893 // | }); 9894 // 9895 // example: 9896 // Style is s special case: Only set with an object hash of styles 9897 // | dojo.attr("someNode",{ 9898 // | id:"bar", 9899 // | style:{ 9900 // | width:"200px", height:"100px", color:"#000" 9901 // | } 9902 // | }); 9903 // 9904 // example: 9905 // Again, only set style as an object hash of styles: 9906 // | var obj = { color:"#fff", backgroundColor:"#000" }; 9907 // | dojo.attr("someNode", "style", obj); 9908 // | 9909 // | // though shorter to use `dojo.style()` in this case: 9910 // | dojo.style("someNode", obj); 9911 9912 if(arguments.length == 2){ 9913 return attr[typeof name == "string" ? "get" : "set"](node, name); 9914 } 9915 return attr.set(node, name, value); 9916 }; 9917 9918 // mix-in dom-class 9919 dojo.hasClass = cls.contains; 9920 dojo.addClass = cls.add; 9921 dojo.removeClass = cls.remove; 9922 dojo.toggleClass = cls.toggle; 9923 dojo.replaceClass = cls.replace; 9924 9925 // mix-in dom-construct 9926 dojo._toDom = dojo.toDom = ctr.toDom; 9927 dojo.place = ctr.place; 9928 dojo.create = ctr.create; 9929 dojo.empty = function(node){ ctr.empty(node); }; 9930 dojo._destroyElement = dojo.destroy = function(node){ ctr.destroy(node); }; 9931 9932 // mix-in dom-geometry 9933 dojo._getPadExtents = dojo.getPadExtents = geom.getPadExtents; 9934 dojo._getBorderExtents = dojo.getBorderExtents = geom.getBorderExtents; 9935 dojo._getPadBorderExtents = dojo.getPadBorderExtents = geom.getPadBorderExtents; 9936 dojo._getMarginExtents = dojo.getMarginExtents = geom.getMarginExtents; 9937 dojo._getMarginSize = dojo.getMarginSize = geom.getMarginSize; 9938 dojo._getMarginBox = dojo.getMarginBox = geom.getMarginBox; 9939 dojo.setMarginBox = geom.setMarginBox; 9940 dojo._getContentBox = dojo.getContentBox = geom.getContentBox; 9941 dojo.setContentSize = geom.setContentSize; 9942 dojo._isBodyLtr = dojo.isBodyLtr = geom.isBodyLtr; 9943 dojo._docScroll = dojo.docScroll = geom.docScroll; 9944 dojo._getIeDocumentElementOffset = dojo.getIeDocumentElementOffset = geom.getIeDocumentElementOffset; 9945 dojo._fixIeBiDiScrollLeft = dojo.fixIeBiDiScrollLeft = geom.fixIeBiDiScrollLeft; 9946 dojo.position = geom.position; 9947 9948 dojo.marginBox = function marginBox(/*DomNode|String*/node, /*Object?*/box){ 9949 // summary: 9950 // Getter/setter for the margin-box of node. 9951 // description: 9952 // Getter/setter for the margin-box of node. 9953 // Returns an object in the expected format of box (regardless 9954 // if box is passed). The object might look like: 9955 // `{ l: 50, t: 200, w: 300: h: 150 }` 9956 // for a node offset from its parent 50px to the left, 200px from 9957 // the top with a margin width of 300px and a margin-height of 9958 // 150px. 9959 // node: 9960 // id or reference to DOM Node to get/set box for 9961 // box: 9962 // If passed, denotes that dojo.marginBox() should 9963 // update/set the margin box for node. Box is an object in the 9964 // above format. All properties are optional if passed. 9965 // example: 9966 // Retrieve the margin box of a passed node 9967 // | var box = dojo.marginBox("someNodeId"); 9968 // | console.dir(box); 9969 // 9970 // example: 9971 // Set a node's margin box to the size of another node 9972 // | var box = dojo.marginBox("someNodeId"); 9973 // | dojo.marginBox("someOtherNode", box); 9974 return box ? geom.setMarginBox(node, box) : geom.getMarginBox(node); // Object 9975 }; 9976 9977 dojo.contentBox = function contentBox(/*DomNode|String*/node, /*Object?*/box){ 9978 // summary: 9979 // Getter/setter for the content-box of node. 9980 // description: 9981 // Returns an object in the expected format of box (regardless if box is passed). 9982 // The object might look like: 9983 // `{ l: 50, t: 200, w: 300: h: 150 }` 9984 // for a node offset from its parent 50px to the left, 200px from 9985 // the top with a content width of 300px and a content-height of 9986 // 150px. Note that the content box may have a much larger border 9987 // or margin box, depending on the box model currently in use and 9988 // CSS values set/inherited for node. 9989 // While the getter will return top and left values, the 9990 // setter only accepts setting the width and height. 9991 // node: 9992 // id or reference to DOM Node to get/set box for 9993 // box: 9994 // If passed, denotes that dojo.contentBox() should 9995 // update/set the content box for node. Box is an object in the 9996 // above format, but only w (width) and h (height) are supported. 9997 // All properties are optional if passed. 9998 return box ? geom.setContentSize(node, box) : geom.getContentBox(node); // Object 9999 }; 10000 10001 dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){ 10002 // summary: 10003 // Deprecated: Use position() for border-box x/y/w/h 10004 // or marginBox() for margin-box w/h/l/t. 10005 // 10006 // Returns an object that measures margin-box (w)idth/(h)eight 10007 // and absolute position x/y of the border-box. Also returned 10008 // is computed (l)eft and (t)op values in pixels from the 10009 // node's offsetParent as returned from marginBox(). 10010 // Return value will be in the form: 10011 //| { l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 } 10012 // Does not act as a setter. If includeScroll is passed, the x and 10013 // y params are affected as one would expect in dojo.position(). 10014 dojo.deprecated("dojo.coords()", "Use dojo.position() or dojo.marginBox()."); 10015 node = dom.byId(node); 10016 var s = style.getComputedStyle(node), mb = geom.getMarginBox(node, s); 10017 var abs = geom.position(node, includeScroll);
10018 mb.x = abs.x; 10019 mb.y = abs.y; 10020 return mb; // Object 10021 }; 10022 10023 // mix-in dom-prop 10024 dojo.getProp = prop.get; 10025 dojo.setProp = prop.set; 10026 10027 dojo.prop = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){ 10028 // summary: 10029 // Gets or sets a property on an HTML element. 10030 // description: 10031 // Handles normalized getting and setting of properties on DOM 10032 // Nodes. If 2 arguments are passed, and a the second argument is a 10033 // string, acts as a getter. 10034 // 10035 // If a third argument is passed, or if the second argument is a 10036 // map of attributes, acts as a setter. 10037 // 10038 // When passing functions as values, note that they will not be 10039 // directly assigned to slots on the node, but rather the default 10040 // behavior will be removed and the new behavior will be added 10041 // using `dojo.connect()`, meaning that event handler properties 10042 // will be normalized and that some caveats with regards to 10043 // non-standard behaviors for onsubmit apply. Namely that you 10044 // should cancel form submission using `dojo.stopEvent()` on the 10045 // passed event object instead of returning a boolean value from 10046 // the handler itself. 10047 // node: 10048 // id or reference to the element to get or set the property on 10049 // name: 10050 // the name of the property to get or set. 10051 // value: 10052 // The value to set for the property 10053 // returns: 10054 // when used as a getter, the value of the requested property 10055 // or null if that attribute does not have a specified or 10056 // default value; 10057 // 10058 // when used as a setter, the DOM node 10059 // 10060 // example: 10061 // | // get the current value of the "foo" property on a node 10062 // | dojo.prop(dojo.byId("nodeId"), "foo"); 10063 // | // or we can just pass the id: 10064 // | dojo.prop("nodeId", "foo"); 10065 // 10066 // example: 10067 // | // use prop() to set the tab index 10068 // | dojo.prop("nodeId", "tabIndex", 3); 10069 // | 10070 // 10071 // example: 10072 // Set multiple values at once, including event handlers: 10073 // | dojo.prop("formId", { 10074 // | "foo": "bar", 10075 // | "tabIndex": -1, 10076 // | "method": "POST", 10077 // | "onsubmit": function(e){ 10078 // | // stop submitting the form. Note that the IE behavior 10079 // | // of returning true or false will have no effect here 10080 // | // since our handler is connect()ed to the built-in 10081 // | // onsubmit behavior and so we need to use 10082 // | // dojo.stopEvent() to ensure that the submission 10083 // | // doesn't proceed. 10084 // | dojo.stopEvent(e); 10085 // | 10086 // | // submit the form with Ajax 10087 // | dojo.xhrPost({ form: "formId" }); 10088 // | } 10089 // | }); 10090 // 10091 // example: 10092 // Style is s special case: Only set with an object hash of styles 10093 // | dojo.prop("someNode",{ 10094 // | id:"bar", 10095 // | style:{ 10096 // | width:"200px", height:"100px", color:"#000" 10097 // | } 10098 // | }); 10099 // 10100 // example: 10101 // Again, only set style as an object hash of styles: 10102 // | var obj = { color:"#fff", backgroundColor:"#000" }; 10103 // | dojo.prop("someNode", "style", obj); 10104 // | 10105 // | // though shorter to use `dojo.style()` in this case: 10106 // | dojo.style("someNode", obj); 10107 10108 if(arguments.length == 2){ 10109 return prop[typeof name == "string" ? "get" : "set"](node, name); 10110 } 10111 // setter 10112 return prop.set(node, name, value); 10113 }; 10114 10115 // mix-in dom-style 10116 dojo.getStyle = style.get; 10117 dojo.setStyle = style.set; 10118 dojo.getComputedStyle = style.getComputedStyle; 10119 dojo.__toPixelValue = dojo.toPixelValue = style.toPixelValue; 10120 10121 dojo.style = function(node, name, value){ 10122 // summary: 10123 // Accesses styles on a node. If 2 arguments are 10124 // passed, acts as a getter. If 3 arguments are passed, acts 10125 // as a setter. 10126 // description: 10127 // Getting the style value uses the computed style for the node, so the value 10128 // will be a calculated value, not just the immediate node.style value. 10129 // Also when getting values, use specific style names, 10130 // like "borderBottomWidth" instead of "border" since compound values like 10131 // "border" are not necessarily reflected as expected. 10132 // If you want to get node dimensions, use `dojo.marginBox()`, 10133 // `dojo.contentBox()` or `dojo.position()`. 10134 // node: DOMNode|String 10135 // id or reference to node to get/set style for 10136 // name: String|Object? 10137 // the style property to set in DOM-accessor format 10138 // ("borderWidth", not "border-width") or an object with key/value 10139 // pairs suitable for setting each property. 10140 // value: String? 10141 // If passed, sets value on the node for style, handling 10142 // cross-browser concerns. When setting a pixel value, 10143 // be sure to include "px" in the value. For instance, top: "200px". 10144 // Otherwise, in some cases, some browsers will not apply the style. 10145 // returns: 10146 // when used as a getter, return the computed style of the node if passing in an ID or node, 10147 // or return the normalized, computed value for the property when passing in a node and a style property 10148 // example: 10149 // Passing only an ID or node returns the computed style object of 10150 // the node: 10151 // | dojo.style("thinger"); 10152 // example: 10153 // Passing a node and a style property returns the current 10154 // normalized, computed value for that property: 10155 // | dojo.style("thinger", "opacity"); // 1 by default 10156 // 10157 // example: 10158 // Passing a node, a style property, and a value changes the 10159 // current display of the node and returns the new computed value 10160 // | dojo.style("thinger", "opacity", 0.5); // == 0.5 10161 // 10162 // example: 10163 // Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node: 10164 // | dojo.style("thinger", { 10165 // | "opacity": 0.5, 10166 // | "border": "3px solid black", 10167 // | "height": "300px" 10168 // | }); 10169 // 10170 // example: 10171 // When the CSS style property is hyphenated, the JavaScript property is camelCased. 10172 // font-size becomes fontSize, and so on. 10173 // | dojo.style("thinger",{ 10174 // | fontSize:"14pt", 10175 // | letterSpacing:"1.2em"
10176 // | }); 10177 // 10178 // example: 10179 // dojo/NodeList implements .style() using the same syntax, omitting the "node" parameter, calling 10180 // dojo.style() on every element of the list. See: `dojo/query` and `dojo/NodeList` 10181 // | dojo.query(".someClassName").style("visibility","hidden"); 10182 // | // or 10183 // | dojo.query("#baz > div").style({ 10184 // | opacity:0.75, 10185 // | fontSize:"13pt" 10186 // | }); 10187 10188 switch(arguments.length){ 10189 case 1: 10190 return style.get(node); 10191 case 2: 10192 return style[typeof name == "string" ? "get" : "set"](node, name); 10193 } 10194 // setter 10195 return style.set(node, name, value); 10196 }; 10197 10198 return dojo; 10199}); 10200 10201}, 10202'dojo/dom-attr':function(){ 10203define(["exports", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-prop"], 10204 function(exports, has, lang, dom, style, prop){ 10205 // module: 10206 // dojo/dom-attr 10207 // summary: 10208 // This module defines the core dojo DOM attributes API. 10209 10210 // TODOC: summary not showing up in output see https://github.com/csnover/js-doc-parse/issues/42 10211 10212 // ============================= 10213 // Element attribute Functions 10214 // ============================= 10215 10216 // This module will be obsolete soon. Use dojo/prop instead. 10217 10218 // dojo/dom-attr.get() should conform to http://www.w3.org/TR/DOM-Level-2-Core/ 10219 10220 // attribute-related functions (to be obsolete soon) 10221 var forcePropNames = { 10222 innerHTML: 1, 10223 textContent:1, 10224 className: 1, 10225 htmlFor: has("ie"), 10226 value: 1 10227 }, 10228 attrNames = { 10229 // original attribute names 10230 classname: "class", 10231 htmlfor: "for", 10232 // for IE 10233 tabindex: "tabIndex", 10234 readonly: "readOnly" 10235 }; 10236 10237 function _hasAttr(node, name){ 10238 var attr = node.getAttributeNode && node.getAttributeNode(name); 10239 return !!attr && attr.specified; // Boolean 10240 } 10241 10242 // There is a difference in the presence of certain properties and their default values 10243 // between browsers. For example, on IE "disabled" is present on all elements, 10244 // but it is value is "false"; "tabIndex" of <div> returns 0 by default on IE, yet other browsers 10245 // can return -1. 10246 10247 exports.has = function hasAttr(/*DOMNode|String*/ node, /*String*/ name){ 10248 // summary: 10249 // Returns true if the requested attribute is specified on the 10250 // given element, and false otherwise. 10251 // node: DOMNode|String 10252 // id or reference to the element to check 10253 // name: String 10254 // the name of the attribute 10255 // returns: Boolean 10256 // true if the requested attribute is specified on the 10257 // given element, and false otherwise 10258 10259 var lc = name.toLowerCase(); 10260 return forcePropNames[prop.names[lc] || name] || _hasAttr(dom.byId(node), attrNames[lc] || name); // Boolean 10261 }; 10262 10263 exports.get = function getAttr(/*DOMNode|String*/ node, /*String*/ name){ 10264 // summary: 10265 // Gets an attribute on an HTML element. 10266 // description: 10267 // Handles normalized getting of attributes on DOM Nodes. 10268 // node: DOMNode|String 10269 // id or reference to the element to get the attribute on 10270 // name: String 10271 // the name of the attribute to get. 10272 // returns: 10273 // the value of the requested attribute or null if that attribute does not have a specified or 10274 // default value; 10275 // 10276 // example: 10277 // | // get the current value of the "foo" attribute on a node 10278 // | require(["dojo/dom-attr", "dojo/dom"], function(domAttr, dom){ 10279 // | domAttr.get(dom.byId("nodeId"), "foo"); 10280 // | // or we can just pass the id: 10281 // | domAttr.get("nodeId", "foo"); 10282 // | }); 10283 // | 10284 10285 node = dom.byId(node); 10286 var lc = name.toLowerCase(), 10287 propName = prop.names[lc] || name, 10288 forceProp = forcePropNames[propName], 10289 value = node[propName]; // should we access this attribute via a property or via getAttribute()? 10290 10291 if(forceProp && typeof value != "undefined"){ 10292 // node's property 10293 return value; // Anything 10294 } 10295 10296 if(propName == "textContent"){ 10297 return prop.get(node, propName); 10298 } 10299 10300 if(propName != "href" && (typeof value == "boolean" || lang.isFunction(value))){ 10301 // node's property 10302 return value; // Anything 10303 } 10304 // node's attribute 10305 // we need _hasAttr() here to guard against IE returning a default value 10306 var attrName = attrNames[lc] || name; 10307 return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything 10308 }; 10309 10310 exports.set = function setAttr(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){ 10311 // summary: 10312 // Sets an attribute on an HTML element. 10313 // description: 10314 // Handles normalized setting of attributes on DOM Nodes. 10315 // 10316 // When passing functions as values, note that they will not be 10317 // directly assigned to slots on the node, but rather the default 10318 // behavior will be removed and the new behavior will be added 10319 // using `dojo.connect()`, meaning that event handler properties 10320 // will be normalized and that some caveats with regards to 10321 // non-standard behaviors for onsubmit apply. Namely that you 10322 // should cancel form submission using `dojo.stopEvent()` on the 10323 // passed event object instead of returning a boolean value from 10324 // the handler itself. 10325 // node: DOMNode|String 10326 // id or reference to the element to set the attribute on 10327 // name: String|Object 10328 // the name of the attribute to set, or a hash of key-value pairs to set. 10329 // value: String? 10330 // the value to set for the attribute, if the name is a string. 10331 // returns: 10332 // the DOM node 10333 // 10334 // example: 10335 // | // use attr() to set the tab index 10336 // | require(["dojo/dom-attr"], function(domAttr){ 10337 // | domAttr.set("nodeId", "tabIndex", 3); 10338 // | }); 10339 // 10340 // example: 10341 // Set multiple values at once, including event handlers: 10342 // | require(["dojo/dom-attr"], 10343 // | function(domAttr){ 10344 // | domAttr.set("formId", { 10345 // | "foo": "bar", 10346 // | "tabIndex": -1, 10347 // | "method": "POST" 10348 // | } 10349 // | }); 10350 10351 node = dom.byId(node); 10352 if(arguments.length == 2){ // inline'd type check 10353 // the object form of setter: the 2nd argument is a dictionary 10354 for(var x in name){ 10355 exports.set(node, x, name[x]); 10356 } 10357 return node; // DomNode 10358 } 10359 var lc = name.toLowerCase(), 10360 propName = prop.names[lc] || name, 10361 forceProp = forcePropNames[propName]; 10362 if(propName == "style" && typeof value != "string"){ // inline'd type check 10363 // special case: setting a style 10364 style.set(node, value); 10365 return node; // DomNode 10366 } 10367 if(forceProp || typeof value == "boolean" || lang.isFunction(value)){ 10368 return prop.set(node, name, value); 10369 } 10370 // node's attribute 10371 node.setAttribute(attrNames[lc] || name, value); 10372 return node; // DomNode 10373 }; 10374 10375 exports.remove = function removeAttr(/*DOMNode|String*/ node, /*String*/ name){ 10376 // summary: 10377 // Removes an attribute from an HTML element. 10378 // node: DOMNode|String 10379 // id or reference to the element to remove the attribute from 10380 // name: String 10381 // the name of the attribute to remove 10382 10383 dom.byId(node).removeAttribute(attrNames[name.toLowerCase()] || name); 10384 }; 10385 10386 exports.getNodeProp = function getNodeProp(/*DomNode|String*/ node, /*String*/ name){ 10387 // summary: 10388 // Returns an effective value of a property or an attribute. 10389 // node: DOMNode|String 10390 // id or reference to the element to remove the attribute from 10391 // name: String 10392 // the name of the attribute 10393 // returns: 10394 // the value of the attribute 10395 10396 node = dom.byId(node); 10397 var lc = name.toLowerCase(), propName = prop.names[lc] || name; 10398 if((propName in node) && propName != "href"){ 10399 // node's property 10400 return node[propName]; // Anything 10401 } 10402 // node's attribute 10403 var attrName = attrNames[lc] || name; 10404 return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything 10405 }; 10406}); 10407 10408}, 10409'dojo/dom-prop':function(){ 10410define(["exports", "./_base/kernel", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-construct", "./_base/connect"], 10411 function(exports, dojo, has, lang, dom, style, ctr, conn){ 10412 // module: 10413 // dojo/dom-prop 10414 // summary: 10415 // This module defines the core dojo DOM properties API. 10416 10417 // TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42 10418 10419 // ============================= 10420 // Element properties Functions 10421 // ============================= 10422 10423 // helper to connect events 10424 var _evtHdlrMap = {}, _ctr = 0, _attrId = dojo._scopeName + "attrid"; 10425 has.add('dom-textContent', function (global, doc, element) { return 'textContent' in element; });
vendor: 6,258 bytes, lines 10426-10628
10426 10427 exports.names = { 10428 // properties renamed to avoid clashes with reserved words 10429 "class": "className", 10430 "for": "htmlFor", 10431 // properties written as camelCase 10432 tabindex: "tabIndex", 10433 readonly: "readOnly", 10434 colspan: "colSpan", 10435 frameborder: "frameBorder", 10436 rowspan: "rowSpan", 10437 textcontent: "textContent", 10438 valuetype: "valueType" 10439 }; 10440 10441 function getText(/*DOMNode*/node){ 10442 // summary: 10443 // recursion method for get('textContent') to use. Gets text value for a node. 10444 // description: 10445 // Juse uses nodedValue so things like <br/> tags do not end up in 10446 // the text as any sort of line return. 10447 var text = "", ch = node.childNodes; 10448 for(var i = 0, n; n = ch[i]; i++){ 10449 //Skip comments. 10450 if(n.nodeType != 8){ 10451 if(n.nodeType == 1){ 10452 text += getText(n); 10453 }else{ 10454 text += n.nodeValue; 10455 } 10456 } 10457 } 10458 return text; 10459 } 10460 10461 exports.get = function getProp(/*DOMNode|String*/ node, /*String*/ name){ 10462 // summary: 10463 // Gets a property on an HTML element. 10464 // description: 10465 // Handles normalized getting of properties on DOM nodes. 10466 // 10467 // node: DOMNode|String 10468 // id or reference to the element to get the property on 10469 // name: String 10470 // the name of the property to get. 10471 // returns: 10472 // the value of the requested property or its default value 10473 // 10474 // example: 10475 // | // get the current value of the "foo" property on a node 10476 // | require(["dojo/dom-prop", "dojo/dom"], function(domProp, dom){ 10477 // | domProp.get(dom.byId("nodeId"), "foo"); 10478 // | // or we can just pass the id: 10479 // | domProp.get("nodeId", "foo"); 10480 // | }); 10481 10482 node = dom.byId(node); 10483 var lc = name.toLowerCase(), propName = exports.names[lc] || name; 10484 10485 if(propName == "textContent" && !has("dom-textContent")){ 10486 return getText(node); 10487 } 10488 10489 return node[propName]; // Anything 10490 }; 10491 10492 exports.set = function setProp(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){ 10493 // summary: 10494 // Sets a property on an HTML element. 10495 // description: 10496 // Handles normalized setting of properties on DOM nodes. 10497 // 10498 // When passing functions as values, note that they will not be 10499 // directly assigned to slots on the node, but rather the default 10500 // behavior will be removed and the new behavior will be added 10501 // using `dojo.connect()`, meaning that event handler properties 10502 // will be normalized and that some caveats with regards to 10503 // non-standard behaviors for onsubmit apply. Namely that you 10504 // should cancel form submission using `dojo.stopEvent()` on the 10505 // passed event object instead of returning a boolean value from 10506 // the handler itself. 10507 // node: DOMNode|String 10508 // id or reference to the element to set the property on 10509 // name: String|Object 10510 // the name of the property to set, or a hash object to set 10511 // multiple properties at once. 10512 // value: String? 10513 // The value to set for the property 10514 // returns: 10515 // the DOM node 10516 // 10517 // example: 10518 // | // use prop() to set the tab index 10519 // | require(["dojo/dom-prop"], function(domProp){ 10520 // | domProp.set("nodeId", "tabIndex", 3); 10521 // | }); 10522 // 10523 // example: 10524 // Set multiple values at once, including event handlers: 10525 // | require(["dojo/dom-prop"], function(domProp){ 10526 // | domProp.set("formId", { 10527 // | "foo": "bar", 10528 // | "tabIndex": -1, 10529 // | "method": "POST", 10530 // | }); 10531 // | }); 10532 10533 node = dom.byId(node); 10534 var l = arguments.length; 10535 if(l == 2 && typeof name != "string"){ // inline'd type check 10536 // the object form of setter: the 2nd argument is a dictionary 10537 for(var x in name){ 10538 exports.set(node, x, name[x]); 10539 } 10540 return node; // DomNode 10541 } 10542 var lc = name.toLowerCase(), propName = exports.names[lc] || name; 10543 if(propName == "style" && typeof value != "string"){ // inline'd type check 10544 // special case: setting a style 10545 style.set(node, value); 10546 return node; // DomNode 10547 } 10548 if(propName == "innerHTML"){ 10549 // special case: assigning HTML 10550 // the hash lists elements with read-only innerHTML on IE 10551 if(has("ie") && node.tagName.toLowerCase() in {col: 1, colgroup: 1, 10552 table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1}){ 10553 ctr.empty(node); 10554 node.appendChild(ctr.toDom(value, node.ownerDocument)); 10555 }else{ 10556 node[propName] = value; 10557 } 10558 return node; // DomNode 10559 } 10560 if(propName == "textContent" && !has("dom-textContent")) { 10561 ctr.empty(node); 10562 node.appendChild(node.ownerDocument.createTextNode(value)); 10563 return node; 10564 } 10565 if(lang.isFunction(value)){ 10566 // special case: assigning an event handler 10567 // clobber if we can 10568 var attrId = node[_attrId]; 10569 if(!attrId){ 10570 attrId = _ctr++; 10571 node[_attrId] = attrId; 10572 } 10573 if(!_evtHdlrMap[attrId]){ 10574 _evtHdlrMap[attrId] = {}; 10575 } 10576 var h = _evtHdlrMap[attrId][propName]; 10577 if(h){ 10578 //h.remove(); 10579 conn.disconnect(h); 10580 }else{ 10581 try{ 10582 delete node[propName]; 10583 }catch(e){} 10584 } 10585 // ensure that event objects are normalized, etc. 10586 if(value){ 10587 //_evtHdlrMap[attrId][propName] = on(node, propName, value); 10588 _evtHdlrMap[attrId][propName] = conn.connect(node, propName, value); 10589 }else{ 10590 node[propName] = null; 10591 } 10592 return node; // DomNode 10593 } 10594 node[propName] = value; 10595 return node; // DomNode 10596 }; 10597}); 10598 10599}, 10600'dojo/dom-construct':function(){ 10601define(["exports", "./_base/kernel", "./sniff", "./_base/window", "./dom", "./dom-attr"], 10602 function(exports, dojo, has, win, dom, attr){ 10603 // module: 10604 // dojo/dom-construct 10605 // summary: 10606 // This module defines the core dojo DOM construction API. 10607 10608 // TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42 10609 10610 // support stuff for toDom() 10611 var tagWrap = { 10612 option: ["select"], 10613 tbody: ["table"], 10614 thead: ["table"], 10615 tfoot: ["table"], 10616 tr: ["table", "tbody"], 10617 td: ["table", "tbody", "tr"], 10618 th: ["table", "thead", "tr"], 10619 legend: ["fieldset"], 10620 caption: ["table"], 10621 colgroup: ["table"], 10622 col: ["table", "colgroup"], 10623 li: ["ul"] 10624 }, 10625 reTag = /<\s*([\w\:]+)/, 10626 masterNode = {}, masterNum = 0, 10627 masterName = "__" + dojo._scopeName + "ToDomId"; 10628
vendor: 7,974 bytes, lines 10629-10853
10629 // generate start/end tag strings to use 10630 // for the injection for each special tag wrap case. 10631 for(var param in tagWrap){ 10632 if(tagWrap.hasOwnProperty(param)){ 10633 var tw = tagWrap[param]; 10634 tw.pre = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">"; 10635 tw.post = "</" + tw.reverse().join("></") + ">"; 10636 // the last line is destructive: it reverses the array, 10637 // but we don't care at this point 10638 } 10639 } 10640 10641 var html5domfix; 10642 if(has("ie") <= 8){ 10643 html5domfix = function(doc){ 10644 doc.__dojo_html5_tested = "yes"; 10645 var div = create('div', {innerHTML: "<nav>a</nav>", style: {visibility: "hidden"}}, doc.body); 10646 if(div.childNodes.length !== 1){ 10647 ('abbr article aside audio canvas details figcaption figure footer header ' + 10648 'hgroup mark meter nav output progress section summary time video').replace( 10649 /\b\w+\b/g, function(n){ 10650 doc.createElement(n); 10651 } 10652 ); 10653 } 10654 destroy(div); 10655 } 10656 } 10657 10658 function _insertBefore(/*DomNode*/ node, /*DomNode*/ ref){ 10659 var parent = ref.parentNode; 10660 if(parent){ 10661 parent.insertBefore(node, ref); 10662 } 10663 } 10664 10665 function _insertAfter(/*DomNode*/ node, /*DomNode*/ ref){ 10666 // summary: 10667 // Try to insert node after ref 10668 var parent = ref.parentNode; 10669 if(parent){ 10670 if(parent.lastChild == ref){ 10671 parent.appendChild(node); 10672 }else{ 10673 parent.insertBefore(node, ref.nextSibling); 10674 } 10675 } 10676 } 10677 10678 exports.toDom = function toDom(frag, doc){ 10679 // summary: 10680 // instantiates an HTML fragment returning the corresponding DOM. 10681 // frag: String 10682 // the HTML fragment 10683 // doc: DocumentNode? 10684 // optional document to use when creating DOM nodes, defaults to 10685 // dojo/_base/window.doc if not specified. 10686 // returns: 10687 // Document fragment, unless it's a single node in which case it returns the node itself 10688 // example: 10689 // Create a table row: 10690 // | require(["dojo/dom-construct"], function(domConstruct){ 10691 // | var tr = domConstruct.toDom("<tr><td>First!</td></tr>"); 10692 // | }); 10693 10694 doc = doc || win.doc; 10695 var masterId = doc[masterName]; 10696 if(!masterId){ 10697 doc[masterName] = masterId = ++masterNum + ""; 10698 masterNode[masterId] = doc.createElement("div"); 10699 } 10700 10701 if(has("ie") <= 8){ 10702 if(!doc.__dojo_html5_tested && doc.body){ 10703 html5domfix(doc); 10704 } 10705 } 10706 10707 // make sure the frag is a string. 10708 frag += ""; 10709 10710 // find the starting tag, and get node wrapper 10711 var match = frag.match(reTag), 10712 tag = match ? match[1].toLowerCase() : "", 10713 master = masterNode[masterId], 10714 wrap, i, fc, df; 10715 if(match && tagWrap[tag]){ 10716 wrap = tagWrap[tag]; 10717 master.innerHTML = wrap.pre + frag + wrap.post; 10718 for(i = wrap.length; i; --i){ 10719 master = master.firstChild; 10720 } 10721 }else{ 10722 master.innerHTML = frag; 10723 } 10724 10725 // one node shortcut => return the node itself 10726 if(master.childNodes.length == 1){ 10727 return master.removeChild(master.firstChild); // DOMNode 10728 } 10729 10730 // return multiple nodes as a document fragment 10731 df = doc.createDocumentFragment(); 10732 while((fc = master.firstChild)){ // intentional assignment 10733 df.appendChild(fc); 10734 } 10735 return df; // DocumentFragment 10736 }; 10737 10738 exports.place = function place(node, refNode, position){ 10739 // summary: 10740 // Attempt to insert node into the DOM, choosing from various positioning options. 10741 // Returns the first argument resolved to a DOM node. 10742 // node: DOMNode|DocumentFragment|String 10743 // id or node reference, or HTML fragment starting with "<" to place relative to refNode 10744 // refNode: DOMNode|String 10745 // id or node reference to use as basis for placement 10746 // position: String|Number? 10747 // string noting the position of node relative to refNode or a 10748 // number indicating the location in the childNodes collection of refNode. 10749 // Accepted string values are: 10750 // 10751 // - before 10752 // - after 10753 // - replace 10754 // - only 10755 // - first 10756 // - last 10757 // 10758 // "first" and "last" indicate positions as children of refNode, "replace" replaces refNode, 10759 // "only" replaces all children. position defaults to "last" if not specified 10760 // returns: DOMNode 10761 // Returned values is the first argument resolved to a DOM node. 10762 // 10763 // .place() is also a method of `dojo/NodeList`, allowing `dojo/query` node lookups. 10764 // example: 10765 // Place a node by string id as the last child of another node by string id: 10766 // | require(["dojo/dom-construct"], function(domConstruct){ 10767 // | domConstruct.place("someNode", "anotherNode"); 10768 // | }); 10769 // example: 10770 // Place a node by string id before another node by string id 10771 // | require(["dojo/dom-construct"], function(domConstruct){ 10772 // | domConstruct.place("someNode", "anotherNode", "before"); 10773 // | }); 10774 // example: 10775 // Create a Node, and place it in the body element (last child): 10776 // | require(["dojo/dom-construct", "dojo/_base/window" 10777 // | ], function(domConstruct, win){ 10778 // | domConstruct.place("<div></div>", win.body()); 10779 // | }); 10780 // example: 10781 // Put a new LI as the first child of a list by id: 10782 // | require(["dojo/dom-construct"], function(domConstruct){ 10783 // | domConstruct.place("<li></li>", "someUl", "first"); 10784 // | }); 10785 10786 refNode = dom.byId(refNode); 10787 if(typeof node == "string"){ // inline'd type check 10788 node = /^\s*</.test(node) ? exports.toDom(node, refNode.ownerDocument) : dom.byId(node); 10789 } 10790 if(typeof position == "number"){ // inline'd type check 10791 var cn = refNode.childNodes; 10792 if(!cn.length || cn.length <= position){ 10793 refNode.appendChild(node); 10794 }else{ 10795 _insertBefore(node, cn[position < 0 ? 0 : position]); 10796 } 10797 }else{ 10798 switch(position){ 10799 case "before": 10800 _insertBefore(node, refNode); 10801 break; 10802 case "after": 10803 _insertAfter(node, refNode); 10804 break; 10805 case "replace": 10806 refNode.parentNode.replaceChild(node, refNode); 10807 break; 10808 case "only": 10809 exports.empty(refNode); 10810 refNode.appendChild(node); 10811 break; 10812 case "first": 10813 if(refNode.firstChild){ 10814 _insertBefore(node, refNode.firstChild); 10815 break; 10816 } 10817 // else fallthrough... 10818 default: // aka: last 10819 refNode.appendChild(node); 10820 } 10821 } 10822 return node; // DomNode 10823 }; 10824 10825 var create = exports.create = function create(/*DOMNode|String*/ tag, /*Object*/ attrs, /*DOMNode|String?*/ refNode, /*String?*/ pos){ 10826 // summary: 10827 // Create an element, allowing for optional attribute decoration 10828 // and placement. 10829 // description: 10830 // A DOM Element creation function. A shorthand method for creating a node or 10831 // a fragment, and allowing for a convenient optional attribute setting step, 10832 // as well as an optional DOM placement reference. 10833 // 10834 // Attributes are set by passing the optional object through `dojo/dom-attr.set`. 10835 // See `dojo/dom-attr.set` for noted caveats and nuances, and API if applicable. 10836 // 10837 // Placement is done via `dojo/dom-construct.place`, assuming the new node to be 10838 // the action node, passing along the optional reference node and position. 10839 // tag: DOMNode|String 10840 // A string of the element to create (eg: "div", "a", "p", "li", "script", "br"), 10841 // or an existing DOM node to process. 10842 // attrs: Object 10843 // An object-hash of attributes to set on the newly created node. 10844 // Can be null, if you don't want to set any attributes/styles. 10845 // See: `dojo/dom-attr.set` for a description of available attributes. 10846 // refNode: DOMNode|String? 10847 // Optional reference node. Used by `dojo/dom-construct.place` to place the newly created 10848 // node somewhere in the dom relative to refNode. Can be a DomNode reference 10849 // or String ID of a node. 10850 // pos: String? 10851 // Optional positional reference. Defaults to "last" by way of `dojo/domConstruct.place`, 10852 // though can be set to "first","after","before","last", "replace" or "only" 10853 // to further control the placement of the new node relative to the refNode.
10854 // 'refNode' is required if a 'pos' is specified. 10855 // example: 10856 // Create a DIV: 10857 // | require(["dojo/dom-construct"], function(domConstruct){ 10858 // | var n = domConstruct.create("div"); 10859 // | }); 10860 // 10861 // example: 10862 // Create a DIV with content: 10863 // | require(["dojo/dom-construct"], function(domConstruct){ 10864 // | var n = domConstruct.create("div", { innerHTML:"<p>hi</p>" }); 10865 // | }); 10866 // 10867 // example: 10868 // Place a new DIV in the BODY, with no attributes set 10869 // | require(["dojo/dom-construct", "dojo/_base/window"], function(domConstruct, win){ 10870 // | var n = domConstruct.create("div", null, win.body()); 10871 // | }); 10872 // 10873 // example: 10874 // Create an UL, and populate it with LI's. Place the list as the first-child of a 10875 // node with id="someId": 10876 // | require(["dojo/dom-construct", "dojo/_base/array"], 10877 // | function(domConstruct, arrayUtil){ 10878 // | var ul = domConstruct.create("ul", null, "someId", "first"); 10879 // | var items = ["one", "two", "three", "four"]; 10880 // | arrayUtil.forEach(items, function(data){ 10881 // | domConstruct.create("li", { innerHTML: data }, ul); 10882 // | }); 10883 // | }); 10884 // 10885 // example: 10886 // Create an anchor, with an href. Place in BODY: 10887 // | require(["dojo/dom-construct", "dojo/_base/window"], function(domConstruct, win){ 10888 // | domConstruct.create("a", { href:"foo.html", title:"Goto FOO!" }, win.body()); 10889 // | }); 10890 10891 var doc = win.doc; 10892 if(refNode){
10893 refNode = dom.byId(refNode); 10894 doc = refNode.ownerDocument; 10895 } 10896 if(typeof tag == "string"){ // inline'd type check 10897 tag = doc.createElement(tag); 10898 } 10899 if(attrs){ attr.set(tag, attrs); } 10900 if(refNode){ exports.place(tag, refNode, pos); } 10901 return tag; // DomNode 10902 }; 10903 10904 function _empty(/*DomNode*/ node){ 10905 // TODO: remove this if() block in 2.0 when we no longer have to worry about IE memory leaks, 10906 // and then uncomment the emptyGrandchildren() test case from html.html. 10907 // Note that besides fixing #16957, using removeChild() is actually faster than setting node.innerHTML, 10908 // see http://jsperf.com/clear-dom-node. 10909 if("innerHTML" in node){ 10910 try{ 10911 // fast path 10912 node.innerHTML = ""; 10913 return; 10914 }catch(e){ 10915 // innerHTML is readOnly (e.g. TABLE (sub)elements in quirks mode) 10916 // Fall through (saves bytes) 10917 } 10918 } 10919 10920 // SVG/strict elements don't support innerHTML 10921 for(var c; c = node.lastChild;){ // intentional assignment 10922 node.removeChild(c); 10923 } 10924 } 10925 10926 exports.empty = function empty(/*DOMNode|String*/ node){ 10927 // summary: 10928 // safely removes all children of the node. 10929 // node: DOMNode|String 10930 // a reference to a DOM node or an id. 10931 // example: 10932 // Destroy node's children byId: 10933 // | require(["dojo/dom-construct"], function(domConstruct){ 10934 // | domConstruct.empty("someId"); 10935 // | }); 10936 10937 _empty(dom.byId(node)); 10938 }; 10939 10940 10941 function _destroy(/*DomNode*/ node, /*DomNode*/ parent){ 10942 // in IE quirks, node.canHaveChildren can be false but firstChild can be non-null (OBJECT/APPLET) 10943 if(node.firstChild){ 10944 _empty(node); 10945 } 10946 if(parent){ 10947 // removeNode(false) doesn't leak in IE 6+, but removeChild() and removeNode(true) are known to leak under IE 8- while 9+ is TBD. 10948 // In IE quirks mode, PARAM nodes as children of OBJECT/APPLET nodes have a removeNode method that does nothing and 10949 // the parent node has canHaveChildren=false even though removeChild correctly removes the PARAM children. 10950 // In IE, SVG/strict nodes don't have a removeNode method nor a canHaveChildren boolean. 10951 has("ie") && parent.canHaveChildren && "removeNode" in node ? node.removeNode(false) : parent.removeChild(node); 10952 } 10953 } 10954 var destroy = exports.destroy = function destroy(/*DOMNode|String*/ node){ 10955 // summary: 10956 // Removes a node from its parent, clobbering it and all of its 10957 // children. 10958 // 10959 // description: 10960 // Removes a node from its parent, clobbering it and all of its 10961 // children. Function only works with DomNodes, and returns nothing. 10962 // 10963 // node: DOMNode|String 10964 // A String ID or DomNode reference of the element to be destroyed 10965 // 10966 // example: 10967 // Destroy a node byId: 10968 // | require(["dojo/dom-construct"], function(domConstruct){ 10969 // | domConstruct.destroy("someId"); 10970 // | }); 10971 10972 node = dom.byId(node); 10973 if(!node){ return; } 10974 _destroy(node, node.parentNode); 10975 }; 10976}); 10977 10978}, 10979'dojo/dom-class':function(){ 10980define(["./_base/lang", "./_base/array", "./dom"], function(lang, array, dom){ 10981 // module: 10982 // dojo/dom-class 10983 10984 var className = "className"; 10985 10986 /* Part I of classList-based implementation is preserved here for posterity 10987 var classList = "classList"; 10988 has.add("dom-classList", function(){ 10989 return classList in document.createElement("p"); 10990 }); 10991 */ 10992 10993 // ============================= 10994 // (CSS) Class Functions 10995 // ============================= 10996 10997 var cls, // exports object 10998 spaces = /\s+/, a1 = [""]; 10999 11000 function str2array(s){ 11001 if(typeof s == "string" || s instanceof String){ 11002 if(s && !spaces.test(s)){ 11003 a1[0] = s; 11004 return a1; 11005 } 11006 var a = s.split(spaces); 11007 if(a.length && !a[0]){ 11008 a.shift(); 11009 } 11010 if(a.length && !a[a.length - 1]){ 11011 a.pop(); 11012 } 11013 return a; 11014 } 11015 // assumed to be an array 11016 if(!s){ 11017 return []; 11018 } 11019 return array.filter(s, function(x){ return x; }); 11020 } 11021 11022 /* Part II of classList-based implementation is preserved here for posterity 11023 if(has("dom-classList")){ 11024 // new classList version 11025 cls = { 11026 contains: function containsClass(node, classStr){ 11027 var clslst = classStr && dom.byId(node)[classList]; 11028 return clslst && clslst.contains(classStr); // Boolean 11029 }, 11030 11031 add: function addClass(node, classStr){ 11032 node = dom.byId(node); 11033 classStr = str2array(classStr); 11034 for(var i = 0, len = classStr.length; i < len; ++i){ 11035 node[classList].add(classStr[i]); 11036 } 11037 }, 11038 11039 remove: function removeClass(node, classStr){ 11040 node = dom.byId(node); 11041 if(classStr === undefined){ 11042 node[className] = ""; 11043 }else{ 11044 classStr = str2array(classStr); 11045 for(var i = 0, len = classStr.length; i < len; ++i){ 11046 node[classList].remove(classStr[i]); 11047 } 11048 } 11049 }, 11050 11051 replace: function replaceClass(node, addClassStr, removeClassStr){ 11052 node = dom.byId(node); 11053 if(removeClassStr === undefined){ 11054 node[className] = ""; 11055 }else{ 11056 removeClassStr = str2array(removeClassStr); 11057 for(var i = 0, len = removeClassStr.length; i < len; ++i){ 11058 node[classList].remove(removeClassStr[i]); 11059 } 11060 } 11061 addClassStr = str2array(addClassStr); 11062 for(i = 0, len = addClassStr.length; i < len; ++i){ 11063 node[classList].add(addClassStr[i]); 11064 } 11065 }, 11066 11067 toggle: function toggleClass(node, classStr, condition){ 11068 node = dom.byId(node); 11069 if(condition === undefined){ 11070 classStr = str2array(classStr); 11071 for(var i = 0, len = classStr.length; i < len; ++i){ 11072 node[classList].toggle(classStr[i]); 11073 } 11074 }else{ 11075 cls[condition ? "add" : "remove"](node, classStr); 11076 } 11077 return condition; // Boolean 11078 } 11079 } 11080 } 11081 */ 11082
vendor: 4,359 bytes, lines 11083-11213
11083 // regular DOM version 11084 var fakeNode = {}; // for effective replacement 11085 cls = { 11086 // summary: 11087 // This module defines the core dojo DOM class API. 11088 11089 contains: function containsClass(/*DomNode|String*/ node, /*String*/ classStr){ 11090 // summary: 11091 // Returns whether or not the specified classes are a portion of the 11092 // class list currently applied to the node. 11093 // node: String|DOMNode 11094 // String ID or DomNode reference to check the class for. 11095 // classStr: String 11096 // A string class name to look for. 11097 // example: 11098 // Do something if a node with id="someNode" has class="aSillyClassName" present 11099 // | if(dojo.hasClass("someNode","aSillyClassName")){ ... } 11100 11101 return ((" " + dom.byId(node)[className] + " ").indexOf(" " + classStr + " ") >= 0); // Boolean 11102 }, 11103 11104 add: function addClass(/*DomNode|String*/ node, /*String|Array*/ classStr){ 11105 // summary: 11106 // Adds the specified classes to the end of the class list on the 11107 // passed node. Will not re-apply duplicate classes. 11108 // 11109 // node: String|DOMNode 11110 // String ID or DomNode reference to add a class string too 11111 // 11112 // classStr: String|Array 11113 // A String class name to add, or several space-separated class names, 11114 // or an array of class names. 11115 // 11116 // example: 11117 // Add a class to some node: 11118 // | require(["dojo/dom-class"], function(domClass){ 11119 // | domClass.add("someNode", "anewClass"); 11120 // | }); 11121 // 11122 // example: 11123 // Add two classes at once: 11124 // | require(["dojo/dom-class"], function(domClass){ 11125 // | domClass.add("someNode", "firstClass secondClass"); 11126 // | }); 11127 // 11128 // example: 11129 // Add two classes at once (using array): 11130 // | require(["dojo/dom-class"], function(domClass){ 11131 // | domClass.add("someNode", ["firstClass", "secondClass"]); 11132 // | }); 11133 // 11134 // example: 11135 // Available in `dojo/NodeList` for multiple additions 11136 // | require(["dojo/query"], function(query){ 11137 // | query("ul > li").addClass("firstLevel"); 11138 // | }); 11139 11140 node = dom.byId(node); 11141 classStr = str2array(classStr); 11142 var cls = node[className], oldLen; 11143 cls = cls ? " " + cls + " " : " "; 11144 oldLen = cls.length; 11145 for(var i = 0, len = classStr.length, c; i < len; ++i){ 11146 c = classStr[i]; 11147 if(c && cls.indexOf(" " + c + " ") < 0){ 11148 cls += c + " "; 11149 } 11150 } 11151 if(oldLen < cls.length){ 11152 node[className] = cls.substr(1, cls.length - 2); 11153 } 11154 }, 11155 11156 remove: function removeClass(/*DomNode|String*/ node, /*String|Array?*/ classStr){ 11157 // summary: 11158 // Removes the specified classes from node. No `contains()` 11159 // check is required. 11160 // 11161 // node: String|DOMNode 11162 // String ID or DomNode reference to remove the class from. 11163 // 11164 // classStr: String|Array 11165 // An optional String class name to remove, or several space-separated 11166 // class names, or an array of class names. If omitted, all class names 11167 // will be deleted. 11168 // 11169 // example: 11170 // Remove a class from some node: 11171 // | require(["dojo/dom-class"], function(domClass){ 11172 // | domClass.remove("someNode", "firstClass"); 11173 // | }); 11174 // 11175 // example: 11176 // Remove two classes from some node: 11177 // | require(["dojo/dom-class"], function(domClass){ 11178 // | domClass.remove("someNode", "firstClass secondClass"); 11179 // | }); 11180 // 11181 // example: 11182 // Remove two classes from some node (using array): 11183 // | require(["dojo/dom-class"], function(domClass){ 11184 // | domClass.remove("someNode", ["firstClass", "secondClass"]); 11185 // | }); 11186 // 11187 // example: 11188 // Remove all classes from some node: 11189 // | require(["dojo/dom-class"], function(domClass){ 11190 // | domClass.remove("someNode"); 11191 // | }); 11192 // 11193 // example: 11194 // Available in `dojo/NodeList` for multiple removal 11195 // | require(["dojo/query"], function(query){ 11196 // | query("ul > li").removeClass("foo"); 11197 // | }); 11198 11199 node = dom.byId(node); 11200 var cls; 11201 if(classStr !== undefined){ 11202 classStr = str2array(classStr); 11203 cls = " " + node[className] + " "; 11204 for(var i = 0, len = classStr.length; i < len; ++i){ 11205 cls = cls.replace(" " + classStr[i] + " ", " "); 11206 } 11207 cls = lang.trim(cls); 11208 }else{ 11209 cls = ""; 11210 } 11211 if(node[className] != cls){ node[className] = cls; } 11212 }, 11213
11214 replace: function replaceClass(/*DomNode|String*/ node, /*String|Array*/ addClassStr, /*String|Array?*/ removeClassStr){ 11215 // summary: 11216 // Replaces one or more classes on a node if not present. 11217 // Operates more quickly than calling dojo.removeClass and dojo.addClass 11218 // 11219 // node: String|DOMNode 11220 // String ID or DomNode reference to remove the class from. 11221 // 11222 // addClassStr: String|Array 11223 // A String class name to add, or several space-separated class names, 11224 // or an array of class names. 11225 // 11226 // removeClassStr: String|Array? 11227 // A String class name to remove, or several space-separated class names, 11228 // or an array of class names. 11229 // 11230 // example: 11231 // | require(["dojo/dom-class"], function(domClass){ 11232 // | domClass.replace("someNode", "add1 add2", "remove1 remove2"); 11233 // | }); 11234 // 11235 // example: 11236 // Replace all classes with addMe 11237 // | require(["dojo/dom-class"], function(domClass){ 11238 // | domClass.replace("someNode", "addMe"); 11239 // | }); 11240 // 11241 // example: 11242 // Available in `dojo/NodeList` for multiple toggles 11243 // | require(["dojo/query"], function(query){ 11244 // | query(".findMe").replaceClass("addMe", "removeMe"); 11245 // | }); 11246 11247 node = dom.byId(node); 11248 fakeNode[className] = node[className]; 11249 cls.remove(fakeNode, removeClassStr); 11250 cls.add(fakeNode, addClassStr); 11251 if(node[className] !== fakeNode[className]){ 11252 node[className] = fakeNode[className]; 11253 } 11254 }, 11255 11256 toggle: function toggleClass(/*DomNode|String*/ node, /*String|Array*/ classStr, /*Boolean?*/ condition){ 11257 // summary: 11258 // Adds a class to node if not present, or removes if present. 11259 // Pass a boolean condition if you want to explicitly add or remove. 11260 // Returns the condition that was specified directly or indirectly. 11261 // 11262 // node: String|DOMNode 11263 // String ID or DomNode reference to toggle a class string 11264 // 11265 // classStr: String|Array 11266 // A String class name to toggle, or several space-separated class names, 11267 // or an array of class names. 11268 // 11269 // condition: 11270 // If passed, true means to add the class, false means to remove. 11271 // Otherwise dojo.hasClass(node, classStr) is used to detect the class presence. 11272 // 11273 // example: 11274 // | require(["dojo/dom-class"], function(domClass){ 11275 // | domClass.toggle("someNode", "hovered"); 11276 // | }); 11277 // 11278 // example: 11279 // Forcefully add a class 11280 // | require(["dojo/dom-class"], function(domClass){ 11281 // | domClass.toggle("someNode", "hovered", true); 11282 // | }); 11283 // 11284 // example: 11285 // Available in `dojo/NodeList` for multiple toggles 11286 // | require(["dojo/query"], function(query){ 11287 // | query(".toggleMe").toggleClass("toggleMe"); 11288 // | }); 11289 11290 node = dom.byId(node); 11291 if(condition === undefined){ 11292 classStr = str2array(classStr); 11293 for(var i = 0, len = classStr.length, c; i < len; ++i){ 11294 c = classStr[i]; 11295 cls[cls.contains(node, c) ? "remove" : "add"](node, c); 11296 } 11297 }else{ 11298 cls[condition ? "add" : "remove"](node, classStr); 11299 } 11300 return condition; // Boolean 11301 } 11302 }; 11303 11304 return cls; 11305}); 11306 11307}, 11308'dojo/_base/NodeList':function(){ 11309define(["./kernel", "../query", "./array", "./html", "../NodeList-dom"], function(dojo, query, array){ 11310 // module: 11311 // dojo/_base/NodeList 11312 11313 /*===== 11314 return { 11315 // summary: 11316 // This module extends dojo/NodeList with the legacy connect(), coords(), 11317 // blur(), focus(), change(), click(), error(), keydown(), keypress(), 11318 // keyup(), load(), mousedown(), mouseenter(), mouseleave(), mousemove(), 11319 // mouseout(), mouseover(), mouseup(), and submit() methods. 11320 }; 11321 =====*/ 11322 11323 var NodeList = query.NodeList, 11324 nlp = NodeList.prototype; 11325 11326 nlp.connect = NodeList._adaptAsForEach(function(){ 11327 // don't bind early to dojo.connect since we no longer explicitly depend on it 11328 return dojo.connect.apply(this, arguments); 11329 }); 11330 /*===== 11331 nlp.connect = function(methodName, objOrFunc, funcName){ 11332 // summary: 11333 // Attach event handlers to every item of the NodeList. Uses dojo.connect() 11334 // so event properties are normalized. 11335 // 11336 // Application must manually require() "dojo/_base/connect" before using this method. 11337 // methodName: String 11338 // the name of the method to attach to. For DOM events, this should be 11339 // the lower-case name of the event 11340 // objOrFunc: Object|Function|String 11341 // if 2 arguments are passed (methodName, objOrFunc), objOrFunc
11341should 11342 // reference a function or be the name of the function in the global 11343 // namespace to attach. If 3 arguments are provided 11344 // (methodName, objOrFunc, funcName), objOrFunc must be the scope to 11345 // locate the bound function in 11346 // funcName: String? 11347 // optional. A string naming the function in objOrFunc to bind to the 11348 // event. May also be a function reference. 11349 // example: 11350 // add an onclick handler to every button on the page 11351 // | query("div:nth-child(odd)").connect("onclick", function(e){ 11352 // | console.log("clicked!"); 11353 // | }); 11354 // example: 11355 // attach foo.bar() to every odd div's onmouseover 11356 // | query("div:nth-child(odd)").connect("onmouseover", foo, "bar"); 11357 11358 return null; // NodeList 11359 }; 11360 =====*/ 11361 11362 nlp.coords = NodeList._adaptAsMap(dojo.coords); 11363 /*===== 11364 nlp.coords = function(){ 11365 // summary: 11366 // Deprecated: Use position() for border-box x/y/w/h 11367 // or marginBox() for margin-box w/h/l/t. 11368 // Returns the box objects of all elements in a node list as 11369 // an Array (*not* a NodeList). Acts like `domGeom.coords`, though assumes 11370 // the node passed is each node in this list. 11371 11372 return []; // Array 11373 }; 11374 =====*/ 11375 11376 NodeList.events = [ 11377 // summary: 11378 // list of all DOM events used in NodeList 11379 "blur", "focus", "change", "click", "error", "keydown", "keypress", 11380 "keyup", "load", "mousedown", "mouseenter", "mouseleave", "mousemove", 11381 "mouseout", "mouseover", "mouseup", "submit" 11382 ]; 11383 11384 // FIXME: pseudo-doc the above automatically generated on-event functions 11385 11386 // syntactic sugar for DOM events 11387 array.forEach(NodeList.events, function(evt){ 11388 var _oe = "on" + evt; 11389 nlp[_oe] = function(a, b){ 11390 return this.connect(_oe, a, b); 11391 }; 11392 // FIXME: should these events trigger publishes? 11393 /* 11394 return (a ? this.connect(_oe, a, b) : 11395 this.forEach(function(n){ 11396 // FIXME: 11397 // listeners get buried by 11398 // addEventListener and can't be dug back 11399 // out to be triggered externally. 11400 // see: 11401 // http://developer.mozilla.org/en/docs/DOM:element 11402 11403 console.log(n, evt, _oe); 11404 11405 // FIXME: need synthetic event support! 11406 var _e = { target: n, faux: true, type: evt }; 11407 // dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt }); 11408 try{ n[evt](_e); }catch(e){ console.log(e); } 11409 try{ n[_oe](_e); }catch(e){ console.log(e); } 11410 }) 11411 ); 11412 */ 11413 } 11414 ); 11415 11416 dojo.NodeList = NodeList; 11417 return NodeList; 11418}); 11419 11420}, 11421'dojo/query':function(){ 11422define(["./_base/kernel", "./has", "./dom", "./on", "./_base/array", "./_base/lang", "./selector/_loader", "./selector/_loader!default"], 11423 function(dojo, has, dom, on, array, lang, loader, defaultEngine){ 11424 11425 "use strict"; 11426 11427 has.add("array-extensible", function(){ 11428 // test to see if we can extend an array (not supported in old IE) 11429 return lang.delegate([], {length: 1}).length == 1 && !has("bug-for-in-skips-shadowed"); 11430 }); 11431 11432 var ap = Array.prototype, aps = ap.slice, apc = ap.concat, forEach = array.forEach; 11433 11434 var tnl = function(/*Array*/ a, /*dojo/NodeList?*/ parent, /*Function?*/ NodeListCtor){ 11435 // summary: 11436 // decorate an array to make it look like a `dojo/NodeList`. 11437 // a: 11438 // Array of nodes to decorate. 11439 // parent: 11440 // An optional parent NodeList that generated the current 11441 // list of nodes. Used to call _stash() so the parent NodeList 11442 // can be accessed via end() later. 11443 // NodeListCtor: 11444 // An optional constructor function to use for any 11445 // new NodeList calls. This allows a certain chain of 11446 // NodeList calls to use a different object than dojo/NodeList. 11447 var nodeList = new (NodeListCtor || this._NodeListCtor || nl)(a); 11448 return parent ? nodeList._stash(parent) : nodeList; 11449 }; 11450 11451 var loopBody = function(f, a, o){ 11452 a = [0].concat(aps.call(a, 0)); 11453 o = o || dojo.global; 11454 return function(node){ 11455 a[0] = node; 11456 return f.apply(o, a); 11457 }; 11458 }; 11459 11460 // adapters 11461 11462 var adaptAsForEach = function(f, o){ 11463 // summary: 11464 // adapts a single node function to be used in the forEach-type 11465 // actions. The initial object is returned from the specialized 11466 // function. 11467 // f: Function 11468 // a function to adapt 11469 // o: Object? 11470 // an optional context for f 11471 return function(){ 11472 this.forEach(loopBody(f, arguments, o)); 11473 return this; // Object 11474 }; 11475 }; 11476 11477 var adaptAsMap = function(f, o){ 11478 // summary: 11479 // adapts a single node function to be used in the map-type 11480 // actions. The return is a new array of values, as via `dojo/_base/array.map` 11481 // f: Function 11482 // a function to adapt 11483 // o: Object? 11484 // an optional context for f 11485 return function(){ 11486 return this.map(loopBody(f, arguments, o)); 11487 }; 11488 }; 11489 11490 var adaptAsFilter = function(f, o){ 11491 // summary: 11492 // adapts a single node function to be used in the filter-type actions 11493 // f: Function 11494 // a function to adapt 11495 // o: Object? 11496 // an optional context for f 11497 return function(){
vendor: 18,780 bytes, lines 11498-11972
11498 return this.filter(loopBody(f, arguments, o)); 11499 }; 11500 }; 11501 11502 var adaptWithCondition = function(f, g, o){ 11503 // summary: 11504 // adapts a single node function to be used in the map-type 11505 // actions, behaves like forEach() or map() depending on arguments 11506 // f: Function 11507 // a function to adapt 11508 // g: Function 11509 // a condition function, if true runs as map(), otherwise runs as forEach() 11510 // o: Object? 11511 // an optional context for f and g 11512 return function(){ 11513 var a = arguments, body = loopBody(f, a, o); 11514 if(g.call(o || dojo.global, a)){ 11515 return this.map(body); // self 11516 } 11517 this.forEach(body); 11518 return this; // self 11519 }; 11520 }; 11521 11522 var NodeList = function(array){ 11523 // summary: 11524 // Array-like object which adds syntactic 11525 // sugar for chaining, common iteration operations, animation, and 11526 // node manipulation. NodeLists are most often returned as the 11527 // result of dojo/query() calls. 11528 // description: 11529 // NodeList instances provide many utilities that reflect 11530 // core Dojo APIs for Array iteration and manipulation, DOM 11531 // manipulation, and event handling. Instead of needing to dig up 11532 // functions in the dojo package, NodeLists generally make the 11533 // full power of Dojo available for DOM manipulation tasks in a 11534 // simple, chainable way. 11535 // example: 11536 // create a node list from a node 11537 // | require(["dojo/query", "dojo/dom" 11538 // | ], function(query, dom){ 11539 // | query.NodeList(dom.byId("foo")); 11540 // | }); 11541 // example: 11542 // get a NodeList from a CSS query and iterate on it 11543 // | require(["dojo/on", "dojo/dom" 11544 // | ], function(on, dom){ 11545 // | var l = query(".thinger"); 11546 // | l.forEach(function(node, index, nodeList){ 11547 // | console.log(index, node.innerHTML); 11548 // | }); 11549 // | }); 11550 // example: 11551 // use native and Dojo-provided array methods to manipulate a 11552 // NodeList without needing to use dojo.* functions explicitly: 11553 // | require(["dojo/query", "dojo/dom-construct", "dojo/dom" 11554 // | ], function(query, domConstruct, dom){ 11555 // | var l = query(".thinger"); 11556 // | // since NodeLists are real arrays, they have a length 11557 // | // property that is both readable and writable and 11558 // | // push/pop/shift/unshift methods 11559 // | console.log(l.length); 11560 // | l.push(domConstruct.create("span")); 11561 // | 11562 // | // dojo's normalized array methods work too: 11563 // | console.log( l.indexOf(dom.byId("foo")) ); 11564 // | // ...including the special "function as string" shorthand 11565 // | console.log( l.every("item.nodeType == 1") ); 11566 // | 11567 // | // NodeLists can be [..] indexed, or you can use the at() 11568 // | // function to get specific items wrapped in a new NodeList: 11569 // | var node = l[3]; // the 4th element 11570 // | var newList = l.at(1, 3); // the 2nd and 4th elements 11571 // | }); 11572 // example: 11573 // chainability is a key advantage of NodeLists: 11574 // | require(["dojo/query", "dojo/NodeList-dom" 11575 // | ], function(query){ 11576 // | query(".thinger") 11577 // | .onclick(function(e){ /* ... */ }) 11578 // | .at(1, 3, 8) // get a subset 11579 // | .style("padding", "5px") 11580 // | .forEach(console.log); 11581 // | }); 11582 11583 var isNew = this instanceof nl && has("array-extensible"); 11584 if(typeof array == "number"){ 11585 array = Array(array); 11586 } 11587 var nodeArray = (array && "length" in array) ? array : arguments; 11588 if(isNew || !nodeArray.sort){ 11589 // make sure it's a real array before we pass it on to be wrapped 11590 var target = isNew ? this : [], 11591 l = target.length = nodeArray.length; 11592 for(var i = 0; i < l; i++){ 11593 target[i] = nodeArray[i]; 11594 } 11595 if(isNew){ 11596 // called with new operator, this means we are going to use this instance and push 11597 // the nodes on to it. This is usually much faster since the NodeList properties 11598 // don't need to be copied (unless the list of nodes is extremely large). 11599 return target; 11600 } 11601 nodeArray = target; 11602 } 11603 // called without new operator, use a real array and copy prototype properties, 11604 // this is slower and exists for back-compat. Should be removed in 2.0. 11605 lang._mixin(nodeArray, nlp); 11606 nodeArray._NodeListCtor = function(array){ 11607 // call without new operator to preserve back-compat behavior 11608 return nl(array); 11609 }; 11610 return nodeArray; 11611 }; 11612 11613 var nl = NodeList, nlp = nl.prototype = 11614 has("array-extensible") ? [] : {};// extend an array if it is extensible 11615 11616 // expose adapters and the wrapper as private functions 11617 11618 nl._wrap = nlp._wrap = tnl; 11619 nl._adaptAsMap = adaptAsMap; 11620 nl._adaptAsForEach = adaptAsForEach; 11621 nl._adaptAsFilter = adaptAsFilter; 11622 nl._adaptWithCondition = adaptWithCondition; 11623 11624 // mass assignment 11625 11626 // add array redirectors 11627 forEach(["slice", "splice"], function(name){ 11628 var f = ap[name]; 11629 //Use a copy of the this array via this.slice() to allow .end() to work right in the splice case. 11630 // CANNOT apply ._stash()/end() to splice since it currently modifies 11631 // the existing this array -- it would break backward compatibility if we copy the array before 11632 // the splice so that we can use .end(). So only doing the stash option to this._wrap for slice. 11633 nlp[name] = function(){ return this._wrap(f.apply(this, arguments), name == "slice" ? this : null); }; 11634 }); 11635 // concat should be here but some browsers with native NodeList have problems with it 11636 11637 // add array.js redirectors 11638 forEach(["indexOf", "lastIndexOf", "every", "some"], function(name){ 11639 var f = array[name]; 11640 nlp[name] = function(){ return f.apply(dojo, [this].concat(aps.call(arguments, 0))); }; 11641 }); 11642 11643 lang.extend(NodeList, { 11644 // copy the constructors 11645 constructor: nl, 11646 _NodeListCtor: nl, 11647 toString: function(){ 11648 // Array.prototype.toString can't be applied to objects, so we use join 11649 return this.join(","); 11650 }, 11651 _stash: function(parent){ 11652 // summary: 11653 // private function to hold to a parent NodeList. end() to return the parent NodeList. 11654 // 11655 // example: 11656 // How to make a `dojo/NodeList` method that only returns the third node in 11657 // the dojo/NodeList but allows access to the original NodeList by using this._stash: 11658 // | require(["dojo/query", "dojo/_base/lang", "dojo/NodeList", "dojo/NodeList-dom" 11659 // | ], function(query, lang){ 11660 // | lang.extend(NodeList, { 11661 // | third: function(){ 11662 // | var newNodeList = NodeList(this[2]); 11663 // | return newNodeList._stash(this); 11664 // | } 11665 // | }); 11666 // | // then see how _stash applies a sub-list, to be .end()'ed out of 11667 // | query(".foo") 11668 // | .third() 11669 // | .addClass("thirdFoo") 11670 // | .end() 11671 // | // access to the orig .foo list 11672 // | .removeClass("foo") 11673 // | }); 11674 // 11675 this._parent = parent; 11676 return this; // dojo/NodeList 11677 }, 11678 11679 on: function(eventName, listener){ 11680 // summary: 11681 // Listen for events on the nodes in the NodeList. Basic usage is: 11682 // 11683 // example: 11684 // | require(["dojo/query" 11685 // | ], function(query){ 11686 // | query(".my-class").on("click", listener); 11687 // This supports event delegation by using selectors as the first argument with the event names as 11688 // pseudo selectors. For example: 11689 // | query("#my-list").on("li:click", listener); 11690 // This will listen for click events within `<li>` elements that are inside the `#my-list` element. 11691 // Because on supports CSS selector syntax, we can use comma-delimited events as well: 11692 // | query("#my-list").on("li button:mouseover, li:click", listener); 11693 // | }); 11694 var handles = this.map(function(node){ 11695 return on(node, eventName, listener); // TODO: apply to the NodeList so the same selector engine is used for matches 11696 }); 11697 handles.remove = function(){ 11698 for(var i = 0; i < handles.length; i++){ 11699 handles[i].remove(); 11700 } 11701 }; 11702 return handles; 11703 }, 11704 11705 end: function(){ 11706 // summary: 11707 // Ends use of the current `NodeList` by returning the previous NodeList 11708 // that generated the current NodeList. 11709 // description: 11710 // Returns the `NodeList` that generated the current `NodeList`. If there 11711 // is no parent NodeList, an empty NodeList is returned. 11712 // example: 11713 // | require(["dojo/query", "dojo/NodeList-dom" 11714 // | ], function(query){ 11715 // | query("a") 11716 // | .filter(".disabled") 11717 // | // operate on the anchors that only have a disabled class 11718 // | .style("color", "grey") 11719 // | .end() 11720 // | // jump back to the list of anchors 11721 // | .style(...) 11722 // | }); 11723 // 11724 if(this._parent){ 11725 return this._parent; 11726 }else{ 11727 //Just return empty list. 11728 return new this._NodeListCtor(0); 11729 } 11730 }, 11731 11732 // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods 11733 11734 // FIXME: handle return values for #3244 11735 // http://trac.dojotoolkit.org/ticket/3244 11736 11737 // FIXME: 11738 // need to wrap or implement: 11739 // join (perhaps w/ innerHTML/outerHTML overload for toString() of items?) 11740 // reduce 11741 // reduceRight 11742 11743 /*===== 11744 slice: function(begin, end){ 11745 // summary: 11746 // Returns a new NodeList, maintaining this one in place 11747 // description: 11748 // This method behaves exactly like the Array.slice method 11749 // with the caveat that it returns a `dojo/NodeList` and not a 11750 // raw Array. For more details, see Mozilla's [slice 11751 // documentation](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/slice) 11752 // begin: Integer 11753 // Can be a positive or negative integer, with positive 11754 // integers noting the offset to begin at, and negative 11755 // integers denoting an offset from the end (i.e., to the left 11756 // of the end) 11757 // end: Integer? 11758 // Optional parameter to describe what position relative to 11759 // the NodeList's zero index to end the slice at. Like begin, 11760 // can be positive or negative. 11761 return this._wrap(a.slice.apply(this, arguments)); 11762 }, 11763 11764 splice: function(index, howmany, item){ 11765 // summary: 11766 // Returns a new NodeList, manipulating this NodeList based on 11767 // the arguments passed, potentially splicing in new elements 11768 // at an offset, optionally deleting elements 11769 // description: 11770 // This method behaves exactly like the Array.splice method 11771 // with the caveat that it returns a `dojo/NodeList` and not a 11772 // raw Array. For more details, see Mozilla's [splice 11773 // documentation](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) 11774 // For backwards compatibility, calling .end() on the spliced NodeList 11775 // does not return the original NodeList -- splice alters the NodeList in place. 11776 // index: Integer 11777 // begin can be a positive or negative integer, with positive 11778 // integers noting the offset to begin at, and negative 11779 // integers denoting an offset from the end (i.e., to the left 11780 // of the end) 11781 // howmany: Integer? 11782 // Optional parameter to describe what position relative to 11783 // the NodeList's zero index to end the slice at. Like begin, 11784 // can be positive or negative. 11785 // item: Object...? 11786 // Any number of optional parameters may be passed in to be 11787 // spliced into the NodeList 11788 return this._wrap(a.splice.apply(this, arguments)); // dojo/NodeList 11789 }, 11790 11791 indexOf: function(value, fromIndex){ 11792 // summary: 11793 // see `dojo/_base/array.indexOf()`. The primary difference is that the acted-on 11794 // array is implicitly this NodeList 11795 // value: Object 11796 // The value to search for. 11797 // fromIndex: Integer? 11798 // The location to start searching from. Optional. Defaults to 0. 11799 // description: 11800 // For more details on the behavior of indexOf, see Mozilla's 11801 // [indexOf 11802 // docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) 11803 // returns: 11804 // Positive Integer or 0 for a match, -1 of not found. 11805 return d.indexOf(this, value, fromIndex); // Integer 11806 }, 11807 11808 lastIndexOf: function(value, fromIndex){ 11809 // summary: 11810 // see `dojo/_base/array.lastIndexOf()`. The primary difference is that the 11811 // acted-on array is implicitly this NodeList 11812 // description: 11813 // For more details on the behavior of lastIndexOf, see 11814 // Mozilla's [lastIndexOf 11815 // docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf) 11816 // value: Object 11817 // The value to search for. 11818 // fromIndex: Integer? 11819 // The location to start searching from. Optional. Defaults to 0. 11820 // returns: 11821 // Positive Integer or 0 for a match, -1 of not found. 11822 return d.lastIndexOf(this, value, fromIndex); // Integer 11823 }, 11824 11825 every: function(callback, thisObject){ 11826 // summary: 11827 // see `dojo/_base/array.every()` and the [Array.every 11828 // docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every). 11829 // Takes the same structure of arguments and returns as 11830 // dojo/_base/array.every() with the caveat that the passed array is 11831 // implicitly this NodeList 11832 // callback: Function 11833 // the callback 11834 // thisObject: Object? 11835 // the context 11836 return d.every(this, callback, thisObject); // Boolean 11837 }, 11838 11839 some: function(callback, thisObject){ 11840 // summary: 11841 // Takes the same structure of arguments and returns as 11842 // `dojo/_base/array.some()` with the caveat that the passed array is 11843 // implicitly this NodeList. See `dojo/_base/array.some()` and Mozilla's 11844 // [Array.some 11845 // documentation](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some). 11846 // callback: Function 11847 // the callback 11848 // thisObject: Object? 11849 // the context 11850 return d.some(this, callback, thisObject); // Boolean 11851 }, 11852 =====*/ 11853 11854 concat: function(item){ 11855 // summary: 11856 // Returns a new NodeList comprised of items in this NodeList 11857 // as well as items passed in as parameters 11858 // description: 11859 // This method behaves exactly like the Array.concat method 11860 // with the caveat that it returns a `NodeList` and not a 11861 // raw Array. For more details, see the [Array.concat 11862 // docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/concat) 11863 // item: Object? 11864 // Any number of optional parameters may be passed in to be 11865 // spliced into the NodeList 11866 11867 //return this._wrap(apc.apply(this, arguments)); 11868 // the line above won't work for the native NodeList, or for Dojo NodeLists either :-( 11869 11870 // implementation notes: 11871 // Array.concat() doesn't recognize native NodeLists or Dojo NodeLists 11872 // as arrays, and so does not inline them into a unioned array, but 11873 // appends them as single entities. Both the original NodeList and the 11874 // items passed in as parameters must be converted to raw Arrays 11875 // and then the concatenation result may be re-_wrap()ed as a Dojo NodeList. 11876 11877 var t = aps.call(this, 0), 11878 m = array.map(arguments, function(a){ 11879 return aps.call(a, 0); 11880 }); 11881 return this._wrap(apc.apply(t, m), this); // dojo/NodeList 11882 }, 11883 11884 map: function(/*Function*/ func, /*Function?*/ obj){ 11885 // summary: 11886 // see `dojo/_base/array.map()`. The primary difference is that the acted-on 11887 // array is implicitly this NodeList and the return is a 11888 // NodeList (a subclass of Array) 11889 return this._wrap(array.map(this, func, obj), this); // dojo/NodeList 11890 }, 11891 11892 forEach: function(callback, thisObj){ 11893 // summary: 11894 // see `dojo/_base/array.forEach()`. The primary difference is that the acted-on 11895 // array is implicitly this NodeList. If you want the option to break out 11896 // of the forEach loop, use every() or some() instead. 11897 forEach(this, callback, thisObj); 11898 // non-standard return to allow easier chaining 11899 return this; // dojo/NodeList 11900 }, 11901 filter: function(/*String|Function*/ filter){ 11902 // summary: 11903 // "masks" the built-in javascript filter() method (supported 11904 // in Dojo via `dojo/_base/array.filter`) to support passing a simple 11905 // string filter in addition to supporting filtering function 11906 // objects. 11907 // filter: 11908 // If a string, a CSS rule like ".thinger" or "div > span". 11909 // example: 11910 // "regular" JS filter syntax as exposed in `dojo/_base/array.filter`: 11911 // | require(["dojo/query", "dojo/NodeList-dom" 11912 // | ], function(query){ 11913 // | query("*").filter(function(item){ 11914 // | // highlight every paragraph 11915 // | return (item.nodeName == "p"); 11916 // | }).style("backgroundColor", "yellow"); 11917 // | }); 11918 // example: 11919 // the same filtering using a CSS selector 11920 // | require(["dojo/query", "dojo/NodeList-dom" 11921 // | ], function(query){ 11922 // | query("*").filter("p").styles("backgroundColor", "yellow"); 11923 // | }); 11924 11925 var a = arguments, items = this, start = 0; 11926 if(typeof filter == "string"){ // inline'd type check 11927 items = query._filterResult(this, a[0]); 11928 if(a.length == 1){ 11929 // if we only got a string query, pass back the filtered results 11930 return items._stash(this); // dojo/NodeList 11931 } 11932 // if we got a callback, run it over the filtered items 11933 start = 1; 11934 } 11935 return this._wrap(array.filter(items, a[start], a[start + 1]), this); // dojo/NodeList 11936 }, 11937 instantiate: function(/*String|Object*/ declaredClass, /*Object?*/ properties){ 11938 // summary: 11939 // Create a new instance of a specified class, using the 11940 // specified properties and each node in the NodeList as a 11941 // srcNodeRef. 11942 // example: 11943 // Grabs all buttons in the page and converts them to dijit/form/Button's. 11944 // | var buttons = query("button").instantiate(Button, {showLabel: true}); 11945 var c = lang.isFunction(declaredClass) ? declaredClass : lang.getObject(declaredClass); 11946 properties = properties || {}; 11947 return this.forEach(function(node){ 11948 new c(properties, node); 11949 }); // dojo/NodeList 11950 }, 11951 at: function(/*===== index =====*/){ 11952 // summary: 11953 // Returns a new NodeList comprised of items in this NodeList 11954 // at the given index or indices. 11955 // 11956 // index: Integer... 11957 // One or more 0-based indices of items in the current 11958 // NodeList. A negative index will start at the end of the 11959 // list and go backwards. 11960 // 11961 // example: 11962 // Shorten the list to the first, second, and third elements 11963 // | require(["dojo/query" 11964 // | ], function(query){ 11965 // | query("a").at(0, 1, 2).forEach(fn); 11966 // | }); 11967 // 11968 // example: 11969 // Retrieve the first and last elements of a unordered list: 11970 // | require(["dojo/query" 11971 // | ], function(query){ 11972 // | query("ul >
11972 li").at(0, -1).forEach(cb); 11973 // | }); 11974 // 11975 // example: 11976 // Do something for the first element only, but end() out back to 11977 // the original list and continue chaining: 11978 // | require(["dojo/query" 11979 // | ], function(query){ 11980 // | query("a").at(0).onclick(fn).end().forEach(function(n){ 11981 // | console.log(n); // all anchors on the page. 11982 // | }) 11983 // | }); 11984 11985 var t = new this._NodeListCtor(0); 11986 forEach(arguments, function(i){ 11987 if(i < 0){ i = this.length + i; } 11988 if(this[i]){ t.push(this[i]); } 11989 }, this); 11990 return t._stash(this); // dojo/NodeList 11991 } 11992 }); 11993 11994 function queryForEngine(engine, NodeList){ 11995 var query = function(/*String*/ query, /*String|DOMNode?*/ root){ 11996 // summary: 11997 // Returns nodes which match the given CSS selector, searching the 11998 // entire document by default but optionally taking a node to scope 11999 // the search by. Returns an instance of NodeList. 12000 if(typeof root == "string"){ 12001 root = dom.byId(root); 12002 if(!root){ 12003 return new NodeList([]); 12004 } 12005 } 12006 var results = typeof query == "string" ? engine(query, root) : query ? (query.end && query.on) ? query : [query] : []; 12007 if(results.end && results.on){ 12008 // already wrapped 12009 return results; 12010 } 12011 return new NodeList(results); 12012 }; 12013 query.matches = engine.match || function(node, selector, root){ 12014 // summary: 12015 // Test to see if a node matches a selector 12016 return query.filter([node], selector, root).length > 0; 12017 }; 12018 // the engine provides a filtering function, use it to for matching 12019 query.filter = engine.filter || function(nodes, selector, root){ 12020 // summary: 12021 // Filters an array of nodes. Note that this does not guarantee to return a NodeList, just an array. 12022 return query(selector, root).filter(function(node){ 12023 return array.indexOf(nodes, node) > -1; 12024 }); 12025 }; 12026 if(typeof engine != "function"){ 12027 var search = engine.search; 12028 engine = function(selector, root){ 12029 // Slick does it backwards (or everyone else does it backwards, probably the latter) 12030 return search(root || document, selector); 12031 }; 12032 } 12033 return query; 12034 } 12035 var query = queryForEngine(defaultEngine, NodeList); 12036 /*===== 12037 query = function(selector, context){ 12038 // summary: 12039 // This modules provides DOM querying functionality. The module export is a function 12040 // that can be used to query for DOM nodes by CSS selector and returns a NodeList 12041 // representing the matching nodes. 12042 // selector: String 12043 // A CSS selector to search for. 12044 // context: String|DomNode? 12045 // An optional context to limit the searching scope. Only nodes under `context` will be 12046 // scanned. 12047 // example: 12048 // add an onclick handler to every submit button in the document 12049 // which causes the form to be sent via Ajax instead: 12050 // | require(["dojo/query", "dojo/request", "dojo/dom-form", "dojo/dom-construct", "dojo/dom-style" 12051 // | ], function(query, request, domForm, domConstruct, domStyle){ 12052 // | query("input[type='submit']").on("click", function(e){ 12053 // | e.preventDefault(); // prevent sending the form 12054 // | var btn = e.target; 12055 // | request.post("http://example.com/", { 12056 // | data: domForm.toObject(btn.form) 12057 // | }).then(function(response){ 12058 // | // replace the form with the response 12059 // | domConstruct.create(div, {innerHTML: response}, btn.form, "after"); 12060 // | domStyle.set(btn.form, "display", "none"); 12061 // | }); 12062 // | }); 12063 // | }); 12064 // 12065 // description: 12066 // dojo/query is responsible for loading the appropriate query engine and wrapping 12067 // its results with a `NodeList`. You can use dojo/query with a specific selector engine 12068 // by using it as a plugin. For example, if you installed the sizzle package, you could 12069 // use it as the selector engine with: 12070 // | require(["dojo/query!sizzle"], function(query){ 12071 // | query("div")... 12072 // 12073 // The id after the ! can be a module id of the selector engine or one of the following values: 12074 // 12075 // - acme: This is the default engine used by Dojo base, and will ensure that the full 12076 // Acme engine is always loaded. 12077 // 12078 // - css2: If the browser has a native selector engine, this will be used, otherwise a 12079 // very minimal lightweight selector engine will be loaded that can do simple CSS2 selectors 12080 // (by #id, .class, tag, and [name=value] attributes, with standard child or descendant (>) 12081 // operators) and nothing more. 12082 // 12083 // - css2.1: If the browser has a native selector engine, this will be used, otherwise the 12084 // full Acme engine will be loaded. 12085 // 12086 // - css3: If the browser has a native selector engine with support for CSS3 pseudo 12087 // selectors (most modern browsers except IE8), this will be used, otherwise the 12088 // full Acme engine will be loaded. 12089 // 12090 // - Or the module id of a selector engine can be used to explicitly choose the selector engine 12091 // 12092 // For example, if you are using CSS3 pseudo selectors in module, you can specify that 12093 // you will need support them with: 12094 // | require(["dojo/query!css3"], function(query){ 12095 // | query('#t > h3:nth-child(odd)')... 12096 // 12097 // You can also choose the selector engine/load configuration by setting the query-selector: 12098 // For example: 12099 // | <script data-dojo-config="query-selector:'css3'" src="dojo.js"></script> 12100 // 12101 return new NodeList(); // dojo/NodeList 12102 }; 12103 =====*/ 12104 12105 // the query that is returned from this module is slightly different than dojo.query, 12106 // because dojo.query has to maintain backwards compatibility with returning a 12107 // true array which has performance problems. The query returned from the module 12108 // does not use true arrays, but rather inherits from Array, making it much faster to 12109 // instantiate. 12110 dojo.query = queryForEngine(defaultEngine, function(array){ 12111 // call it without the new operator to invoke the back-compat behavior that returns a true array 12112 return NodeList(array); // dojo/NodeList 12113 }); 12114 12115 query.load = function(id, parentRequire, loaded){ 12116 // summary: 12117 // can be used as AMD plugin to conditionally load new query engine 12118 // example: 12119 // | require(["dojo/query!custom"], function(qsa){ 12120 // | // loaded selector/custom.js as engine 12121 // | qsa("#foobar").forEach(...); 12122 // | }); 12123 loader.load(id, parentRequire, function(engine){ 12124 loaded(queryForEngine(engine, NodeList)); 12125 }); 12126 }; 12127 12128 dojo._filterQueryResult = query._filterResult = function(nodes, selector, root){ 12129 return new NodeList(query.filter(nodes, selector, root)); 12130 }; 12131 dojo.NodeList = query.NodeList = NodeList; 12132 return query; 12133}); 12134 12135}, 12136'dojo/selector/_loader':function(){ 12137define(["../has", "require"], 12138 function(has, require){ 12139 12140"use strict"; 12141var testDiv = document.createElement("div"); 12142has.add("dom-qsa2.1", !!testDiv.querySelectorAll); 12143has.add("dom-qsa3", function(){ 12144 // test to see if we have a reasonable native selector engine available 12145 try{ 12146 testDiv.innerHTML = "<p class='TEST'></p>"; // test kind of from sizzle 12147 // Safari can't handle uppercase or unicode characters when 12148 // in quirks mode, IE8 can't handle pseudos like :empty 12149 return testDiv.querySelectorAll(".TEST:empty").length == 1; 12150 }catch(e){} 12151 }); 12152var fullEngine; 12153var acme = "./acme", lite = "./lite"; 12154return { 12155 // summary: 12156 // This module handles loading the appropriate selector engine for the given browser 12157 12158 load: function(id, parentRequire, loaded, config){ 12159 var req = require; 12160 // here we implement the default logic for choosing a selector engine 12161 id = id == "default" ? has("config-selectorEngine") || "css3" : id; 12162 id = id == "css2" || id == "lite" ? lite : 12163 id == "css2.1" ? has("dom-qsa2.1") ? lite : acme : 12164 id == "css3" ? has("dom-qsa3") ? lite : acme : 12165 id == "acme" ? acme : (req = parentRequire) && id; 12166 if(id.charAt(id.length-1) == '?'){ 12167 id = id.substring(0,id.length - 1); 12168 var optionalLoad = true; 12169 } 12170 // the query engine is optional, only load it if a native one is not available or existing one has not been loaded 12171 if(optionalLoad && (has("dom-compliant-qsa") || fullEngine)){ 12172 return loaded(fullEngine); 12173 } 12174 // load the referenced selector engine 12175 req([id], function(engine){ 12176 if(id != "./lite"){ 12177 fullEngine = engine; 12178 } 12179 loaded(engine); 12180 }); 12181 } 12182}; 12183}); 12184 12185}, 12186'dojo/selector/lite':function(){ 12187define(["../has", "../_base/kernel"], function(has, dojo){ 12188"use strict"; 12189 12190var testDiv = document.createElement("div"); 12191var matchesSelector = testDiv.matches || testDiv.webkitMatchesSelector || testDiv.mozMatchesSelector || testDiv.msMatchesSelector || testDiv.oMatchesSelector; 12192var querySelectorAll = testDiv.querySelectorAll; 12193var unionSplit = /([^\s,](?:"(?:\\.|[^"])+"|'(?:\\.|[^'])+'|[^,])*)/g; 12194has.add("dom-matches-selector", !!matchesSelector); 12195has.add("dom-qsa", !!querySelectorAll); 12196 12197// this is a simple query engine. It has handles basic selectors, and for simple 12198// common selectors is extremely fast 12199var liteEngine = function(selector, root){ 12200 // summary: 12201 // A small lightweight query selector engine that implements CSS2.1 selectors
12202 // minus pseudo-classes and the sibling combinator, plus CSS3 attribute selectors 12203 12204 if(combine && selector.indexOf(',') > -1){ 12205 return combine(selector, root); 12206 } 12207 // use the root's ownerDocument if provided, otherwise try to use dojo.doc. Note 12208 // that we don't use dojo/_base/window's doc to reduce dependencies, and 12209 // fallback to plain document if dojo.doc hasn't been defined (by dojo/_base/window). 12210 // presumably we will have a better way to do this in 2.0 12211 var doc = root ? root.ownerDocument || root : dojo.doc || document, 12212 match = (querySelectorAll ? 12213 /^([\w]*)#([\w\-]+$)|^(\.)([\w\-\*]+$)|^(\w+$)/ : // this one only matches on simple queries where we can beat qSA with specific methods 12214 /^([\w]*)#([\w\-]+)(?:\s+(.*))?$|(?:^|(>|.+\s+))([\w\-\*]+)(\S*$)/) // this one matches parts of the query that we can use to speed up manual filtering 12215 .exec(selector); 12216 root = root || doc; 12217 if(match){ 12218 // fast path regardless of whether or not querySelectorAll exists 12219 if(match[2]){ 12220 // an #id 12221 // use dojo.byId if available as it fixes the id retrieval in IE, note that we can't use the dojo namespace in 2.0, but if there is a conditional module use, we will use that 12222 var found = dojo.byId ? dojo.byId(match[2], doc) : doc.getElementById(match[2]); 12223 if(!found || (match[1] && match[1] != found.tagName.toLowerCase())){ 12224 // if there is a tag qualifer and it doesn't match, no matches 12225 return []; 12226 } 12227 if(root != doc){ 12228 // there is a root element, make sure we are a child of it 12229 var parent = found; 12230 while(parent != root){ 12231 parent = parent.parentNode; 12232 if(!parent){ 12233 return []; 12234 } 12235 } 12236 } 12237 return match[3] ? 12238 liteEngine(match[3], found) 12239 : [found]; 12240 } 12241 if(match[3] && root.getElementsByClassName){ 12242 // a .class 12243 return root.getElementsByClassName(match[4]); 12244 } 12245 var found; 12246 if(match[5]){ 12247 // a tag 12248 found = root.getElementsByTagName(match[5]); 12249 if(match[4] || match[6]){ 12250 selector = (match[4] || "") + match[6]; 12251 }else{ 12252 // that was the entirety of the query, return results 12253 return found; 12254 } 12255 } 12256 } 12257 if(querySelectorAll){ 12258 // qSA works strangely on Element-rooted queries 12259 // We can work around this by specifying an extra ID on the root 12260 // and working up from there (Thanks to Andrew Dupont for the technique) 12261 // IE 8 doesn't work on object elements 12262 if (root.nodeType === 1 && root.nodeName.toLowerCase() !== "object"){ 12263 return useRoot(root, selector, root.querySelectorAll); 12264 }else{ 12265 // we can use the native qSA 12266 return root.querySelectorAll(selector); 12267 } 12268 }else if(!found){ 12269 // search all children and then filter 12270 found = root.getElementsByTagName("*"); 12271 } 12272 // now we filter the nodes that were found using the matchesSelector 12273 var results = []; 12274 for(var i = 0, l = found.length; i < l; i++){ 12275 var node = found[i]; 12276 if(node.nodeType == 1 && jsMatchesSelector(node, selector, root)){ 12277 // keep the nodes that match the selector 12278 results.push(node); 12279 } 12280 } 12281 return results; 12282}; 12283var useRoot = function(context, query, method){ 12284 // this function creates a temporary id so we can do rooted qSA queries, this is taken from sizzle 12285 var oldContext = context, 12286 old = context.getAttribute("id"), 12287 nid = old || "__dojo__", 12288 hasParent = context.parentNode, 12289 relativeHierarchySelector = /^\s*[+~]/.test(query); 12290 12291 if(relativeHierarchySelector && !hasParent){ 12292 return []; 12293 } 12294 if(!old){ 12295 context.setAttribute("id", nid); 12296 }else{ 12297 nid = nid.replace(/'/g, "\\$&"); 12298 } 12299 if(relativeHierarchySelector && hasParent){ 12300 context = context.parentNode; 12301 } 12302 var selectors = query.match(unionSplit); 12303 for(var i = 0; i < selectors.length; i++){ 12304 selectors[i] = "[id='" + nid + "'] " + selectors[i]; 12305 } 12306 query = selectors.join(","); 12307 12308 try{ 12309 return method.call(context, query); 12310 }finally{ 12311 if(!old){ 12312 oldContext.removeAttribute("id"); 12313 } 12314 } 12315}; 12316 12317if(!has("dom-matches-selector")){ 12318 var jsMatchesSelector = (function(){ 12319 // a JS implementation of CSS selector matching, first we start with the various handlers 12320 var caseFix = testDiv.tagName == "div" ? "toLowerCase" : "toUpperCase"; 12321 var selectorTypes = { 12322 "": function(tagName){ 12323 tagName = tagName[caseFix](); 12324 return function(node){ 12325 return node.tagName == tagName; 12326 }; 12327 }, 12328 ".": function(className){ 12329 var classNameSpaced = ' ' + className + ' '; 12330 return function(node){ 12331 return node.className.indexOf(className) > -1 && (' ' + node.className + ' ').indexOf(classNameSpaced) > -1; 12332 }; 12333 }, 12334 "#": function(id){ 12335 return function(node){ 12336 return node.id == id; 12337 }; 12338 } 12339 }; 12340 var attrComparators = { 12341 "^=": function(attrValue, value){ 12342 return attrValue.indexOf(value) == 0; 12343 }, 12344 "*=": function(attrValue, value){ 12345 return attrValue.indexOf(value) > -1; 12346 }, 12347 "$=": function(attrValue, value){ 12348 return attrValue.substring(attrValue.length - value.length, attrValue.length) == value; 12349 }, 12350 "~=": function(attrValue, value){ 12351 return (' ' + attrValue + ' ').indexOf(' ' + value + ' ') > -1; 12352 }, 12353 "|=": function(attrValue, value){ 12354 return (attrValue + '-').indexOf(value + '-') == 0; 12355 }, 12356 "=": function(attrValue, value){ 12357 return attrValue == value; 12358 }, 12359 "": function(attrValue, value){ 12360 return true; 12361 } 12362 }; 12363 function attr(name, value, type){ 12364 var firstChar = value.charAt(0);
12365 if(firstChar == '"' || firstChar == "'"){ 12366 // it is quoted, remove the quotes 12367 value = value.slice(1, -1); 12368 } 12369 value = value.replace(/\\/g,''); 12370 var comparator = attrComparators[type || ""]; 12371 return function(node){ 12372 var attrValue = node.getAttribute(name); 12373 return attrValue && comparator(attrValue, value); 12374 }; 12375 } 12376 function ancestor(matcher){ 12377 return function(node, root){ 12378 while((node = node.parentNode) != root){ 12379 if(matcher(node, root)){ 12380 return true; 12381 } 12382 } 12383 }; 12384 } 12385 function parent(matcher){ 12386 return function(node, root){ 12387 node = node.parentNode; 12388 return matcher ? 12389 node != root && matcher(node, root) 12390 : node == root; 12391 }; 12392 } 12393 var cache = {}; 12394 function and(matcher, next){ 12395 return matcher ? 12396 function(node, root){ 12397 return next(node) && matcher(node, root); 12398 } 12399 : next; 12400 } 12401 return function(node, selector, root){ 12402 // this returns true or false based on if the node matches the selector (optionally within the given root) 12403 var matcher = cache[selector]; // check to see if we have created a matcher function for the given selector 12404 if(!matcher){ 12405 // create a matcher function for the given selector 12406 // parse the selectors 12407 if(selector.replace(/(?:\s*([> ])\s*)|(#|\.)?((?:\\.|[\w-])+)|\[\s*([\w-]+)\s*(.?=)?\s*("(?:\\.|[^"])+"|'(?:\\.|[^'])+'|(?:\\.|[^\]])*)\s*\]/g, function(t, combinator, type, value, attrName, attrType, attrValue){ 12408 if(value){ 12409 matcher = and(matcher, selectorTypes[type || ""](value.replace(/\\/g, ''))); 12410 } 12411 else if(combinator){ 12412 matcher = (combinator == " " ? ancestor : parent)(matcher); 12413 } 12414 else if(attrName){ 12415 matcher = and(matcher, attr(attrName, attrValue, attrType)); 12416 } 12417 return ""; 12418 })){ 12419 throw new Error("Syntax error in query"); 12420 } 12421 if(!matcher){ 12422 return true; 12423 } 12424 cache[selector] = matcher; 12425 } 12426 // now run the matcher function on the node 12427 return matcher(node, root); 12428 }; 12429 })(); 12430} 12431if(!has("dom-qsa")){ 12432 var combine = function(selector, root){ 12433 // combined queries 12434 var selectors = selector.match(unionSplit); 12435 var indexed = []; 12436 // add all results and keep unique ones, this only runs in IE, so we take advantage 12437 // of known IE features, particularly sourceIndex which is unique and allows us to 12438 // order the results 12439 for(var i = 0; i < selectors.length; i++){ 12440 selector = new String(selectors[i].replace(/\s*$/,'')); 12441 selector.indexOf = escape; // keep it from recursively entering combine 12442 var results = liteEngine(selector, root); 12443 for(var j = 0, l = results.length; j < l; j++){ 12444 var node = results[j]; 12445 indexed[node.sourceIndex] = node; 12446 } 12447 } 12448 // now convert from a sparse array to a dense array 12449 var totalResults = []; 12450 for(i in indexed){ 12451 totalResults.push(indexed[i]); 12452 } 12453 return totalResults; 12454 }; 12455} 12456 12457liteEngine.match = matchesSelector ? function(node, selector, root){ 12458 if(root && root.nodeType != 9){ 12459 // doesn't support three args, use rooted id trick 12460 return useRoot(root, selector, function(query){ 12461 return matchesSelector.call(node, query); 12462 }); 12463 } 12464 // we have a native matchesSelector, use that 12465 return matchesSelector.call(node, selector); 12466} : jsMatchesSelector; // otherwise use the JS matches impl 12467 12468return liteEngine; 12469}); 12470 12471}, 12472'dojo/NodeList-dom':function(){ 12473define(["./_base/kernel", "./query", "./_base/array", "./_base/lang", "./dom-class", "./dom-construct", "./dom-geometry", "./dom-attr", "./dom-style"], function(dojo, query, array, lang, domCls, domCtr, domGeom, domAttr, domStyle){ 12474 12475 // module: 12476 // dojo/NodeList-dom.js 12477 12478 /*===== 12479 return function(){ 12480 // summary: 12481 // Adds DOM related methods to NodeList, and returns NodeList constructor. 12482 }; 12483 =====*/ 12484 12485 var magicGuard = function(a){ 12486 // summary: 12487 // the guard function for dojo/dom-attr() and dojo/dom-style() 12488 return a.length == 1 && (typeof a[0] == "string"); // inline'd type check 12489 }; 12490 12491 var orphan = function(node){ 12492 // summary: 12493 // function to orphan nodes 12494 var p = node.parentNode; 12495 if(p){ 12496 p.removeChild(node); 12497 } 12498 }; 12499 // FIXME: should we move orphan() to dojo/_base/html? 12500 12501 var NodeList = query.NodeList, 12502 awc = NodeList._adaptWithCondition, 12503 aafe = NodeList._adaptAsForEach, 12504 aam = NodeList._adaptAsMap; 12505 12506 function getSet(module){ 12507 return function(node, name, value){ 12508 if(arguments.length == 2){ 12509 return module[typeof name == "string" ? "get" : "set"](node, name); 12510 } 12511 // setter 12512 return module.set(node, name, value); 12513 }; 12514 } 12515 12516 lang.extend(NodeList, { 12517 _normalize: function(/*String||Element||Object||NodeList*/content, /*DOMNode?*/refNode){ 12518 // summary: 12519 // normalizes data to an array of items to insert. 12520 // description: 12521 // If content is an object, it can have special properties "template" and 12522 // "parse". If "template" is defined, then the template value is run through 12523 // dojo/string.substitute (if dojo/string.substitute() has been required elsewhere), 12524 // or if templateFunc is a function on the content, that function will be used to 12525 // transform the template into a final string to be used for for passing to dojo/dom-construct.toDom(). 12526 // If content.parse is true, then it is remembered for later, for when the content 12527 // nodes are inserted into the DOM. At that point, the nodes will be parsed for widgets 12528 // (if dojo/parser has been required elsewhere). 12529 12530 //Wanted to just use a DocumentFragment, but for the array/NodeList
vendor: 5,287 bytes, lines 12531-12675
12531 //case that meant using cloneNode, but we may not want that. 12532 //Cloning should only happen if the node operations span 12533 //multiple refNodes. Also, need a real array, not a NodeList from the 12534 //DOM since the node movements could change those NodeLists. 12535 12536 var parse = content.parse === true; 12537 12538 //Do we have an object that needs to be run through a template? 12539 if(typeof content.template == "string"){ 12540 var templateFunc = content.templateFunc || (dojo.string && dojo.string.substitute); 12541 content = templateFunc ? templateFunc(content.template, content) : content; 12542 } 12543 12544 var type = (typeof content); 12545 if(type == "string" || type == "number"){ 12546 content = domCtr.toDom(content, (refNode && refNode.ownerDocument)); 12547 if(content.nodeType == 11){ 12548 //DocumentFragment. It cannot handle cloneNode calls, so pull out the children. 12549 content = lang._toArray(content.childNodes); 12550 }else{ 12551 content = [content]; 12552 } 12553 }else if(!lang.isArrayLike(content)){ 12554 content = [content]; 12555 }else if(!lang.isArray(content)){ 12556 //To get to this point, content is array-like, but 12557 //not an array, which likely means a DOM NodeList. Convert it now. 12558 content = lang._toArray(content); 12559 } 12560 12561 //Pass around the parse info 12562 if(parse){ 12563 content._runParse = true; 12564 } 12565 return content; //Array 12566 }, 12567 12568 _cloneNode: function(/*DOMNode*/ node){ 12569 // summary: 12570 // private utility to clone a node. Not very interesting in the vanilla 12571 // dojo/NodeList case, but delegates could do interesting things like 12572 // clone event handlers if that is derivable from the node. 12573 return node.cloneNode(true); 12574 }, 12575 12576 _place: function(/*Array*/ary, /*DOMNode*/refNode, /*String*/position, /*Boolean*/useClone){ 12577 // summary: 12578 // private utility to handle placing an array of nodes relative to another node. 12579 // description: 12580 // Allows for cloning the nodes in the array, and for 12581 // optionally parsing widgets, if ary._runParse is true. 12582 12583 //Avoid a disallowed operation if trying to do an innerHTML on a non-element node. 12584 if(refNode.nodeType != 1 && position == "only"){ 12585 return; 12586 } 12587 var rNode = refNode, tempNode; 12588 12589 //Always cycle backwards in case the array is really a 12590 //DOM NodeList and the DOM operations take it out of the live collection. 12591 var length = ary.length; 12592 for(var i = length - 1; i >= 0; i--){ 12593 var node = (useClone ? this._cloneNode(ary[i]) : ary[i]); 12594 12595 //If need widget parsing, use a temp node, instead of waiting after inserting into 12596 //real DOM because we need to start widget parsing at one node up from current node, 12597 //which could cause some already parsed widgets to be parsed again. 12598 if(ary._runParse && dojo.parser && dojo.parser.parse){ 12599 if(!tempNode){ 12600 tempNode = rNode.ownerDocument.createElement("div"); 12601 } 12602 tempNode.appendChild(node); 12603 dojo.parser.parse(tempNode); 12604 node = tempNode.firstChild; 12605 while(tempNode.firstChild){ 12606 tempNode.removeChild(tempNode.firstChild); 12607 } 12608 } 12609 12610 if(i == length - 1){ 12611 domCtr.place(node, rNode, position); 12612 }else{ 12613 rNode.parentNode.insertBefore(node, rNode); 12614 } 12615 rNode = node; 12616 } 12617 }, 12618 12619 12620 position: aam(domGeom.position), 12621 /*===== 12622 position: function(){ 12623 // summary: 12624 // Returns border-box objects (x/y/w/h) of all elements in a node list 12625 // as an Array (*not* a NodeList). Acts like `dojo/dom-geometry-position`, though 12626 // assumes the node passed is each node in this list. 12627 12628 return dojo.map(this, dojo.position); // Array 12629 }, 12630 =====*/ 12631 12632 attr: awc(getSet(domAttr), magicGuard), 12633 /*===== 12634 attr: function(property, value){ 12635 // summary: 12636 // gets or sets the DOM attribute for every element in the 12637 // NodeList. See also `dojo/dom-attr` 12638 // property: String 12639 // the attribute to get/set 12640 // value: String? 12641 // optional. The value to set the property to 12642 // returns: 12643 // if no value is passed, the result is an array of attribute values 12644 // If a value is passed, the return is this NodeList 12645 // example: 12646 // Make all nodes with a particular class focusable: 12647 // | require(["dojo/query", "dojo/NodeList-dom"], function(query){ 12648 // | query(".focusable").attr("tabIndex", -1); 12649 // | }); 12650 // example: 12651 // Disable a group of buttons: 12652 // | require(["dojo/query", "dojo/NodeList-dom"], function(query){ 12653 // | query("button.group").attr("disabled", true); 12654 // | }); 12655 // example: 12656 // innerHTML can be assigned or retrieved as well: 12657 // | // get the innerHTML (as an array) for each list item 12658 // | require(["dojo/query", "dojo/NodeList-dom"], function(query){ 12659 // | var ih = query("li.replaceable").attr("innerHTML"); 12660 // | }); 12661 return; // dojo/NodeList|Array 12662 }, 12663 =====*/ 12664 12665 style: awc(getSet(domStyle), magicGuard), 12666 /*===== 12667 style: function(property, value){ 12668 // summary: 12669 // gets or sets the CSS property for every element in the NodeList 12670 // property: String 12671 // the CSS property to get/set, in JavaScript notation 12672 // ("lineHieght" instead of "line-height") 12673 // value: String? 12674 // optional. The value to set the property to 12675 // returns:
12676 // if no value is passed, the result is an array of strings. 12677 // If a value is passed, the return is this NodeList 12678 return; // dojo/NodeList 12679 return; // Array 12680 }, 12681 =====*/ 12682 12683 addClass: aafe(domCls.add), 12684 /*===== 12685 addClass: function(className){ 12686 // summary: 12687 // adds the specified class to every node in the list 12688 // className: String|Array 12689 // A String class name to add, or several space-separated class names, 12690 // or an array of class names. 12691 return; // dojo/NodeList 12692 }, 12693 =====*/ 12694 12695 removeClass: aafe(domCls.remove), 12696 /*===== 12697 removeClass: function(className){ 12698 // summary: 12699 // removes the specified class from every node in the list 12700 // className: String|Array? 12701 // An optional String class name to remove, or several space-separated 12702 // class names, or an array of class names. If omitted, all class names 12703 // will be deleted. 12704 // returns: 12705 // this list 12706 return; // dojo/NodeList 12707 }, 12708 =====*/ 12709 12710 toggleClass: aafe(domCls.toggle), 12711 /*===== 12712 toggleClass: function(className, condition){ 12713 // summary: 12714 // Adds a class to node if not present, or removes if present. 12715 // Pass a boolean condition if you want to explicitly add or remove. 12716 // condition: Boolean? 12717 // If passed, true means to add the class, false means to remove. 12718 // className: String 12719 // the CSS class to add 12720 return; // dojo/NodeList 12721 }, 12722 =====*/ 12723 12724 replaceClass: aafe(domCls.replace), 12725 /*===== 12726 replaceClass: function(addClassStr, removeClassStr){ 12727 // summary: 12728 // Replaces one or more classes on a node if not present. 12729 // Operates more quickly than calling `removeClass()` and `addClass()` 12730 // addClassStr: String|Array 12731 // A String class name to add, or several space-separated class names, 12732 // or an array of class names. 12733 // removeClassStr: String|Array? 12734 // A String class name to remove, or several space-separated class names, 12735 // or an array of class names. 12736 return; // dojo/NodeList 12737 }, 12738 =====*/ 12739 12740 empty: aafe(domCtr.empty), 12741 /*===== 12742 empty: function(){ 12743 // summary: 12744 // clears all content from each node in the list. Effectively 12745 // equivalent to removing all child nodes from every item in 12746 // the list. 12747 return this.forEach("item.innerHTML='';"); // dojo/NodeList 12748 // FIXME: should we be checking for and/or disposing of widgets below these nodes? 12749 }, 12750 =====*/ 12751 12752 removeAttr: aafe(domAttr.remove), 12753 /*===== 12754 removeAttr: function(name){ 12755 // summary: 12756 // Removes an attribute from each node in the list. 12757 // name: String 12758 // the name of the attribute to remove 12759 return; // dojo/NodeList 12760 }, 12761 =====*/ 12762 12763 marginBox: aam(domGeom.getMarginBox), 12764 /*===== 12765 marginBox: function(){ 12766 // summary: 12767 // Returns margin-box size of nodes 12768 return; // dojo/NodeList 12769 }, 12770 =====*/ 12771 12772 // FIXME: connectPublisher()? connectRunOnce()? 12773 12774 /* 12775 destroy: function(){ 12776 // summary: 12777 // destroys every item in the list. 12778 this.forEach(d.destroy); 12779 // FIXME: should we be checking for and/or disposing of widgets below these nodes? 12780 }, 12781 */ 12782 12783 place: function(/*String||Node*/ queryOrNode, /*String*/ position){ 12784 // summary: 12785 // places elements of this node list relative to the first element matched 12786 // by queryOrNode. Returns the original NodeList. See: `dojo/dom-construct.place` 12787 // queryOrNode: 12788 // may be a string representing any valid CSS3 selector or a DOM node. 12789 // In the selector case, only the first matching element will be used 12790 // for relative positioning. 12791 // position: 12792 // can be one of: 12793 // 12794 // - "last" (default) 12795 // - "first" 12796 // - "before" 12797 // - "after" 12798 // - "only" 12799 // - "replace" 12800 // 12801 // or an offset in the childNodes property 12802 var item = query(queryOrNode)[0]; 12803 return this.forEach(function(node){ domCtr.place(node, item, position); }); // dojo/NodeList 12804 }, 12805 12806 orphan: function(/*String?*/ filter){ 12807 // summary: 12808 // removes elements in this list that match the filter 12809 // from their parents and returns them as a new NodeList. 12810 // filter: 12811 // CSS selector like ".foo" or "div > span" 12812 // returns: 12813 // NodeList containing the orphaned elements 12814 return (filter ? query._filterResult(this, filter) : this).forEac
vendor: 4,788 bytes, lines 12814-12939
12814h(orphan); // dojo/NodeList 12815 }, 12816 12817 adopt: function(/*String||Array||DomNode*/ queryOrListOrNode, /*String?*/ position){ 12818 // summary: 12819 // places any/all elements in queryOrListOrNode at a 12820 // position relative to the first element in this list. 12821 // Returns a dojo/NodeList of the adopted elements. 12822 // queryOrListOrNode: 12823 // a DOM node or a query string or a query result. 12824 // Represents the nodes to be adopted relative to the 12825 // first element of this NodeList. 12826 // position: 12827 // can be one of: 12828 // 12829 // - "last" (default) 12830 // - "first" 12831 // - "before" 12832 // - "after" 12833 // - "only" 12834 // - "replace" 12835 // 12836 // or an offset in the childNodes property 12837 return query(queryOrListOrNode).place(this[0], position)._stash(this); // dojo/NodeList 12838 }, 12839 12840 // FIXME: do we need this? 12841 query: function(/*String*/ queryStr){ 12842 // summary: 12843 // Returns a new list whose members match the passed query, 12844 // assuming elements of the current NodeList as the root for 12845 // each search. 12846 // example: 12847 // assume a DOM created by this markup: 12848 // | <div id="foo"> 12849 // | <p> 12850 // | bacon is tasty, <span>dontcha think?</span> 12851 // | </p> 12852 // | </div> 12853 // | <div id="bar"> 12854 // | <p>great comedians may not be funny <span>in person</span></p> 12855 // | </div> 12856 // If we are presented with the following definition for a NodeList: 12857 // | require(["dojo/dom", "dojo/query", "dojo/NodeList-dom" 12858 // | ], function(dom, query){ 12859 // | var l = new NodeList(dom.byId("foo"), dom.byId("bar")); 12860 // it's possible to find all span elements under paragraphs 12861 // contained by these elements with this sub-query: 12862 // | var spans = l.query("p span"); 12863 // | }); 12864 12865 // FIXME: probably slow 12866 if(!queryStr){ return this; } 12867 var ret = new NodeList; 12868 this.map(function(node){ 12869 // FIXME: why would we ever get undefined here? 12870 query(queryStr, node).forEach(function(subNode){ 12871 if(subNode !== undefined){ 12872 ret.push(subNode); 12873 } 12874 }); 12875 }); 12876 return ret._stash(this); // dojo/NodeList 12877 }, 12878 12879 filter: function(/*String|Function*/ filter){ 12880 // summary: 12881 // "masks" the built-in javascript filter() method (supported 12882 // in Dojo via `dojo.filter`) to support passing a simple 12883 // string filter in addition to supporting filtering function 12884 // objects. 12885 // filter: 12886 // If a string, a CSS rule like ".thinger" or "div > span". 12887 // example: 12888 // "regular" JS filter syntax as exposed in dojo.filter: 12889 // | require(["dojo/query", "dojo/NodeList-dom" 12890 // | ], function(query){ 12891 // | query("*").filter(function(item){ 12892 // | // highlight every paragraph 12893 // | return (item.nodeName == "p"); 12894 // | }).style("backgroundColor", "yellow"); 12895 // | }); 12896 // example: 12897 // the same filtering using a CSS selector 12898 // | require(["dojo/query", "dojo/NodeList-dom" 12899 // | ], function(query){ 12900 // | query("*").filter("p").styles("backgroundColor", "yellow"); 12901 // | }); 12902 var a = arguments, items = this, start = 0; 12903 if(typeof filter == "string"){ // inline'd type check 12904 items = query._filterResult(this, a[0]); 12905 if(a.length == 1){ 12906 // if we only got a string query, pass back the filtered results 12907 return items._stash(this); // dojo/NodeList 12908 } 12909 // if we got a callback, run it over the filtered items 12910 start = 1; 12911 } 12912 return this._wrap(array.filter(items, a[start], a[start + 1]), this); // dojo/NodeList 12913 }, 12914 12915 /* 12916 // FIXME: should this be "copyTo" and include parenting info? 12917 clone: function(){ 12918 // summary: 12919 // creates node clones of each element of this list 12920 // and returns a new list containing the clones 12921 }, 12922 */ 12923 12924 addContent: function(/*String||DomNode||Object||dojo/NodeList*/ content, /*String||Integer?*/ position){ 12925 // summary: 12926 // add a node, NodeList or some HTML as a string to every item in the 12927 // list. Returns the original list. 12928 // description: 12929 // a copy of the HTML content is added to each item in the 12930 // list, with an optional position argument. If no position 12931 // argument is provided, the content is appended to the end of 12932 // each item. 12933 // content: 12934 // DOM node, HTML in string format, a NodeList or an Object. If a DOM node or 12935 // NodeList, the content will be cloned if the current NodeList has more than one 12936 // element. Only the DOM nodes are cloned, no event handlers. If it is an Object, 12937 // it should be an object with at "template" String property that has the HTML string 12938 // to insert. If dojo.string has already been dojo.required, then dojo.string.substitute 12939 // will be used on the "template" to generate the final HTML
12939string. Other allowed 12940 // properties on the object are: "parse" if the HTML 12941 // string should be parsed for widgets (dojo.require("dojo.parser") to get that 12942 // option to work), and "templateFunc" if a template function besides dojo.string.substitute 12943 // should be used to transform the "template". 12944 // position: 12945 // can be one of: 12946 // 12947 // - "last"||"end" (default) 12948 // - "first||"start" 12949 // - "before" 12950 // - "after" 12951 // - "replace" (replaces nodes in this NodeList with new content) 12952 // - "only" (removes other children of the nodes so new content is the only child) 12953 // 12954 // or an offset in the childNodes property 12955 // example: 12956 // appends content to the end if the position is omitted 12957 // | require(["dojo/query", "dojo/NodeList-dom" 12958 // | ], function(query){ 12959 // | query("h3 > p").addContent("hey there!"); 12960 // | }); 12961 // example: 12962 // add something to the front of each element that has a 12963 // "thinger" property: 12964 // | require(["dojo/query", "dojo/NodeList-dom" 12965 // | ], function(query){ 12966 // | query("[thinger]").addContent("...", "first"); 12967 // | }); 12968 // example: 12969 // adds a header before each element of the list 12970 // | require(["dojo/query", "dojo/NodeList-dom" 12971 // | ], function(query){ 12972 // | query(".note").addContent("<h4>NOTE:</h4>", "before"); 12973 // | }); 12974 // example: 12975 // add a clone of a DOM node to the end of every element in 12976 // the list, removing it from its existing parent. 12977 // | require(["dojo/dom", "dojo/query", "dojo/NodeList-dom" 12978 // | ], function(dom, query){ 12979 // | query(".note").addContent(dom.byId("foo")); 12980 // | }); 12981 // example: 12982 // Append nodes from a templatized string. 12983 // | require(["dojo/string", "dojo/query", "dojo/NodeList-dom" 12984 // | ], function(string, query){ 12985 // | query(".note").addContent({ 12986 // | template: '<b>${id}: </b><span>${name}</span>', 12987 // | id: "user332", 12988 // | name: "Mr. Anderson" 12989 // | }); 12990 // | }); 12991 // example: 12992 // Append nodes from a templatized string that also has widgets parsed. 12993 // | require(["dojo/string", "dojo/parser", "dojo/query", "dojo/NodeList-dom" 12994 // | ], function(string, parser, query){ 12995 // | var notes = query(".note").addContent({ 12996 // | template: '<button dojoType="dijit/form/Button">${text}</button>', 12997 // | parse: true, 12998 // | text: "Send" 12999 // | }); 13000 // | }); 13001 content = this._normalize(content, this[0]); 13002 for(var i = 0, node; (node = this[i]); i++){ 13003 if(content.length){ 13004 this._place(content, node, position, i > 0); 13005 }else{ 13006 // if it is an empty array, we empty the target node 13007 domCtr.empty(node); 13008 } 13009 } 13010 return this; // dojo/NodeList 13011 } 13012 }); 13013 13014 return NodeList; 13015}); 13016 13017}, 13018'dojo/_base/xhr':function(){ 13019define([ 13020 "./kernel", 13021 "./sniff", 13022 "require", 13023 "../io-query", 13024 /*===== "./declare", =====*/ 13025 "../dom", 13026 "../dom-form", 13027 "./Deferred", 13028 "./config", 13029 "./json", 13030 "./lang", 13031 "./array", 13032 "../on", 13033 "../aspect", 13034 "../request/watch", 13035 "../request/xhr", 13036 "../request/util" 13037], function(dojo, has, require, ioq, /*===== declare, =====*/ dom, domForm, Deferred, config, json, lang, array, on, aspect, watch, _xhr, util){ 13038 // module: 13039 // dojo/_base/xhr 13040 13041 /*===== 13042 dojo._xhrObj = function(){ 13043 // summary: 13044 // does the work of portably generating a new XMLHTTPRequest object. 13045 }; 13046 =====*/ 13047 dojo._xhrObj = _xhr._create; 13048 13049 var cfg = dojo.config; 13050 13051 // mix in io-query and dom-form 13052 dojo.objectToQuery = ioq.objectToQuery; 13053 dojo.queryToObject = ioq.queryToObject; 13054 dojo.fieldToObject = domForm.fieldToObject; 13055 dojo.formToObject = domForm.toObject; 13056 dojo.formToQuery = domForm.toQuery; 13057 dojo.formToJson = domForm.toJson; 13058 13059 // need to block async callbacks from snatching this thread as the result 13060 // of an async callback might call another sync XHR, this hangs khtml forever 13061 // must checked by watchInFlight() 13062 13063 dojo._blockAsync = false; 13064 13065 // MOW: remove dojo._contentHandlers alias in 2.0 13066 var handlers = dojo._contentHandlers = dojo.contentHandlers = { 13067 // summary: 13068 // A map of available XHR transport handle types. Name matches the 13069 // `handleAs` attribute passed to XHR calls. 13070 // description: 13071 // A map of available XHR transport handle types. Name matches the 13072 // `handleAs` attribute passed to XHR calls. Each contentHandler is 13073 // called, passing the xhr object for manipulation. The return value 13074 // from the contentHandler will be passed to the `load` or `handle` 13075 // functions defined in the original xhr call. 13076 // example: 13077 // Creating a custom content-handler: 13078 // | xhr.contentHandlers.makeCaps = function(xhr){ 13079 // | return xhr.responseText.toUpperCase(); 13080 // | } 13081 // | // and later: 13082 // | dojo.xhrGet({ 13083 // | url:"foo.txt", 13084 // | handleAs:"makeCaps", 13085 // | load: function(data){ /* data is a toUpper version of foo.txt */ } 13086 // | }); 13087 13088 "text": function(xhr){ 13089 // summary: 13090 // A contentHandler which simply returns the plaintext response data 13091 return xhr.responseText; 13092 }, 13093 "json": function(xhr){ 13094 // summary: 13095 // A contentHandler which returns a JavaScript object created from the response data 13096 return json.fromJson(xhr.responseText || null); 13097 }, 13098 "json-comment-filtered": function(xhr){ 13099 // summary: 13100 // A contentHandler which expects comment-filtered JSON. 13101 // description: 13102 // A contentHandler which expects comment-filtered JSON. 13103 // the json-comment-filtered option was implemented to prevent 13104 // "JavaScript Hijacking", but it is less secure than standard JSON. Use 13105 // standard JSON instead. JSON prefixing can be used to subvert hijacking. 13106 // 13107 // Will throw a notice suggesting to use application/json mimetype, as 13108 // json-commenting can introduce security issues. To decrease the chances of hijacking, 13109 // use the standard `json` contentHandler, and prefix your "JSON" with: {}&& 13110 // 13111 // use djConfig.useCommentedJson = true to turn off the notice 13112 if(!config.useCommentedJson){ 13113 console.warn("Consider using the standard mimetype:application/json." 13114 + " json-commenting can introduce security issues. To" 13115 + " decrease the chances of hijacking, use the standard the 'json' handler and" 13116 + " prefix your json with: {}&&\n" 13117 + "Use djConfig.useCommentedJson=true to turn off this message."); 13118 } 13119 13120 var value = xhr.responseText; 13121 var cStartIdx = value.indexOf("\/*"); 13122 var cEndIdx = value.lastIndexOf("*\/"); 13123 if(cStartIdx == -1 || cEndIdx == -1){ 13124 throw new Error("JSON was not comment filtered"); 13125 } 13126 return json.fromJson(value.substring(cStartIdx+2, cEndIdx)); 13127 }, 13128 "javascript": function(xhr){ 13129 // summary: 13130 // A contentHandler which evaluates the response data, expecting it to be valid JavaScript 13131 13132 // FIXME: try Moz and IE specific eval variants? 13133 return dojo.eval(xhr.responseText); 13134 }, 13135 "xml": function(xhr){ 13136 // summary: 13137 // A contentHandler returning an XML Document parsed from the response data 13138 var result = xhr.responseXML; 13139 13140 if(result && has("dom-qsa2.1") && !result.querySelectorAll && has("dom-parser")){ 13141 // http://bugs.dojotoolkit.org/ticket/15631 13142 // IE9 supports a CSS3 querySelectorAll implementation, but the DOM implementation 13143 // returned by IE9 xhr.responseXML does not. Manually create the XML DOM to gain 13144 // the fuller-featured implementation and avoid bugs caused by the inconsistency 13145 result = new DOMParser().parseFromString(xhr.responseText, "application/xml"); 13146 } 13147 13148 if(has("ie")){ 13149 if((!result || !result.documentElement)){ 13150 //WARNING: this branch used by the xml handling in dojo.io.iframe, 13151 //so be sure to test dojo.io.iframe if making changes below. 13152 var ms = function(n){ return "MSXML" + n + ".DOMDocument"; }; 13153 var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)]; 13154 array.some(dp, function(p){ 13155 try{ 13156 var dom = new ActiveXObject(p); 13157 dom.async = false; 13158 dom.loadXML(xhr.responseText); 13159 result = dom; 13160 }catch(e){ return false; } 13161 return true; 13162 });
13163 } 13164 } 13165 return result; // DOMDocument 13166 }, 13167 "json-comment-optional": function(xhr){ 13168 // summary: 13169 // A contentHandler which checks the presence of comment-filtered JSON and 13170 // alternates between the `json` and `json-comment-filtered` contentHandlers. 13171 if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){ 13172 return handlers["json-comment-filtered"](xhr); 13173 }else{ 13174 return handlers["json"](xhr); 13175 } 13176 } 13177 }; 13178 13179 /*===== 13180 13181 // kwargs function parameter definitions. Assigning to dojo namespace rather than making them local variables 13182 // because they are used by dojo/io modules too 13183 13184 dojo.__IoArgs = declare(null, { 13185 // url: String 13186 // URL to server endpoint. 13187 // content: Object? 13188 // Contains properties with string values. These 13189 // properties will be serialized as name1=value2 and 13190 // passed in the request. 13191 // timeout: Integer? 13192 // Milliseconds to wait for the response. If this time 13193 // passes, the then error callbacks are called. 13194 // form: DOMNode? 13195 // DOM node for a form. Used to extract the form values 13196 // and send to the server. 13197 // preventCache: Boolean? 13198 // Default is false. If true, then a 13199 // "dojo.preventCache" parameter is sent in the request 13200 // with a value that changes with each request 13201 // (timestamp). Useful only with GET-type requests. 13202 // handleAs: String? 13203 // Acceptable values depend on the type of IO 13204 // transport (see specific IO calls for more information). 13205 // rawBody: String? 13206 // Sets the raw body for an HTTP request. If this is used, then the content 13207 // property is ignored. This is mostly useful for HTTP methods that have 13208 // a body to their requests, like PUT or POST. This property can be used instead 13209 // of postData and putData for dojo/_base/xhr.rawXhrPost and dojo/_base/xhr.rawXhrPut respectively. 13210 // ioPublish: Boolean? 13211 // Set this explicitly to false to prevent publishing of topics related to 13212 // IO operations. Otherwise, if djConfig.ioPublish is set to true, topics 13213 // will be published via dojo/topic.publish() for different phases of an IO operation. 13214 // See dojo/main.__IoPublish for a list of topics that are published. 13215 13216 load: function(response, ioArgs){ 13217 // summary: 13218 // This function will be 13219 // called on a successful HTTP response code. 13220 // ioArgs: dojo/main.__IoCallbackArgs 13221 // Provides additional information about the request. 13222 // response: Object 13223 // The response in the format as defined with handleAs. 13224 }, 13225 13226 error: function(response, ioArgs){ 13227 // summary: 13228 // This function will 13229 // be called when the request fails due to a network or server error, the url 13230 // is invalid, etc. It will also be called if the load or handle callback throws an 13231 // exception, unless djConfig.debugAtAllCosts is true. This allows deployed applications 13232 // to continue to run even when a logic error happens in the callback, while making 13233 // it easier to troubleshoot while in debug mode. 13234 // ioArgs: dojo/main.__IoCallbackArgs 13235 // Provides additional information about the request. 13236 // response: Object 13237 // The response in the format as defined with handleAs. 13238 }, 13239 13240 handle: function(loadOrError, response, ioArgs){ 13241 // summary: 13242 // This function will 13243 // be called at the end of every request, whether or not an error occurs. 13244 // loadOrError: String 13245 // Provides a string that tells you whether this function 13246 // was called because of success (load) or failure (error). 13247 // response: Object 13248 // The response in the format as defined with handleAs. 13249 // ioArgs: dojo/main.__IoCallbackArgs 13250 // Provides additional information about the request. 13251 } 13252 }); 13253 13254 dojo.__IoCallbackArgs = declare(null, { 13255 // args: Object 13256 // the original object argument to the IO call. 13257 // xhr: XMLHttpRequest 13258 // For XMLHttpRequest calls only, the 13259 // XMLHttpRequest object that was used for the 13260 // request. 13261 // url: String 13262 // The final URL used for the call. Many times it 13263 // will be different than the original args.url 13264 // value. 13265 // query: String 13266 // For non-GET requests, the 13267 // name1=value1&name2=value2 parameters sent up in 13268 // the request. 13269 // handleAs: String 13270 // The final indicator on how the response will be 13271 // handled. 13272 // id: String 13273 // For dojo/io/script calls only, the internal 13274 // script ID used for the request. 13275 // canDelete: Boolean 13276 // For dojo/io/script calls only, indicates 13277 // whether the script tag that represents the 13278 // request can be deleted after callbacks have 13279 // been called. Used internally to know when 13280 // cleanup can happen on JSONP-type requests. 13281 // json: Object 13282 // For dojo/io/script calls only: holds the JSON 13283 // response for JSONP-type requests. Used 13284 // internally to hold on to the JSON responses. 13285 // You should not need to access it directly -- 13286 // the same object should be passed to the success 13287 // callbacks directly. 13288 }); 13289 13290 dojo.__IoPublish = declare(null, { 13291 // summary: 13292 // This is a list of IO topics that can be published 13293 // if djConfig.ioPublish is set to true. IO topics can be 13294 // published for any Input/Output, network operation. So, 13295 // dojo.xhr, dojo.io.script and dojo.io.iframe can all 13296 // trigger these topics to be published. 13297 // start: String 13298 // "/dojo/io/start" is sent when there are no outstanding IO 13299 // requests, and a new IO request is started. No arguments 13300 // are passed with this topic. 13301 // send: String 13302 // "/dojo/io/send" is sent whenever a new IO request is started. 13303 // It passes the dojo.Deferred for the request with the topic. 13304 // load: String 13305 // "/dojo/io/load" is sent whenever an IO request has loaded 13306 // successfully. It passes the response and the dojo.Deferred 13307 // for the request with the topic. 13308 // error: String 13309 // "/dojo/io/error" is sent whenever an IO request has errored. 13310 // It passes the error and the dojo.Deferred 13311 // for the request with the topic. 13312 // done: String 13313 // "/dojo/io/done" is sent whenever an IO request has completed, 13314 // either by loading or by erroring. It passes the error and 13315 // the dojo.Deferred for the request with the topic. 13316 // stop: String 13317 // "/dojo/io/stop" is sent when all outstanding IO requests have 13318 // finished. No arguments are passed with this topic. 13319 }); 13320 =====*/ 13321 13322 13323 dojo._ioSetArgs = function(/*dojo/main.__IoArgs*/args, 13324 /*Function*/canceller,
13325 /*Function*/okHandler, 13326 /*Function*/errHandler){ 13327 // summary: 13328 // sets up the Deferred and ioArgs property on the Deferred so it 13329 // can be used in an io call. 13330 // args: 13331 // The args object passed into the public io call. Recognized properties on 13332 // the args object are: 13333 // canceller: 13334 // The canceller function used for the Deferred object. The function 13335 // will receive one argument, the Deferred object that is related to the 13336 // canceller. 13337 // okHandler: 13338 // The first OK callback to be registered with Deferred. It has the opportunity 13339 // to transform the OK response. It will receive one argument -- the Deferred 13340 // object returned from this function. 13341 // errHandler: 13342 // The first error callback to be registered with Deferred. It has the opportunity 13343 // to do cleanup on an error. It will receive two arguments: error (the 13344 // Error object) and dfd, the Deferred object returned from this function. 13345 13346 var ioArgs = {args: args, url: args.url}; 13347 13348 //Get values from form if requested. 13349 var formObject = null; 13350 if(args.form){ 13351 var form = dom.byId(args.form); 13352 //IE requires going through getAttributeNode instead of just getAttribute in some form cases, 13353 //so use it for all. See #2844 13354 var actnNode = form.getAttributeNode("action"); 13355 ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null); 13356 formObject = domForm.toObject(form); 13357 } 13358 13359 // set up the query params 13360 var miArgs = [{}]; 13361 13362 if(formObject){ 13363 // potentially over-ride url-provided params w/ form values 13364 miArgs.push(formObject); 13365 } 13366 if(args.content){ 13367 // stuff in content over-rides what's set by form 13368 miArgs.push(args.content); 13369 } 13370 if(args.preventCache){ 13371 miArgs.push({"dojo.preventCache": new Date().valueOf()}); 13372 } 13373 ioArgs.query = ioq.objectToQuery(lang.mixin.apply(null, miArgs)); 13374 13375 // .. and the real work of getting the deferred in order, etc. 13376 ioArgs.handleAs = args.handleAs || "text"; 13377 var d = new Deferred(function(dfd){ 13378 dfd.canceled = true; 13379 canceller && canceller(dfd); 13380 13381 var err = dfd.ioArgs.error; 13382 if(!err){ 13383 err = new Error("request cancelled"); 13384 err.dojoType="cancel"; 13385 dfd.ioArgs.error = err; 13386 } 13387 return err; 13388 }); 13389 d.addCallback(okHandler); 13390 13391 //Support specifying load, error and handle callback functions from the args. 13392 //For those callbacks, the "this" object will be the args object. 13393 //The callbacks will get the deferred result value as the 13394 //first argument and the ioArgs object as the second argument. 13395 var ld = args.load; 13396 if(ld && lang.isFunction(ld)){ 13397 d.addCallback(function(value){ 13398 return ld.call(args, value, ioArgs); 13399 }); 13400 } 13401 var err = args.error; 13402 if(err && lang.isFunction(err)){ 13403 d.addErrback(function(value){ 13404 return err.call(args, value, ioArgs); 13405 }); 13406 } 13407 var handle = args.handle; 13408 if(handle && lang.isFunction(handle)){ 13409 d.addBoth(function(value){ 13410 return handle.call(args, value, ioArgs); 13411 }); 13412 } 13413 13414 // Attach error handler last (not including topic publishing) 13415 // to catch any errors that may have been generated from load 13416 // or handle functions. 13417 d.addErrback(function(error){ 13418 return errHandler(error, d); 13419 }); 13420 13421 //Plug in topic publishing, if dojo.publish is loaded. 13422 if(cfg.ioPublish && dojo.publish && ioArgs.args.ioPublish !== false){ 13423 d.addCallbacks( 13424 function(res){ 13425 dojo.publish("/dojo/io/load", [d, res]); 13426 return res; 13427 }, 13428 function(res){ 13429 dojo.publish("/dojo/io/error", [d, res]); 13430 return res; 13431 } 13432 ); 13433 d.addBoth(function(res){ 13434 dojo.publish("/dojo/io/done", [d, res]); 13435 return res; 13436 }); 13437 } 13438 13439 d.ioArgs = ioArgs; 13440 13441 // FIXME: need to wire up the xhr object's abort method to something 13442 // analogous in the Deferred 13443 return d; 13444 }; 13445 13446 var _deferredOk = function(/*Deferred*/dfd){ 13447 // summary: 13448 // okHandler function for dojo._ioSetArgs call. 13449 13450 var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr); 13451 return ret === undefined ? null : ret; 13452 }; 13453 var _deferError = function(/*Error*/error, /*Deferred*/dfd){ 13454 // summary: 13455 // errHandler function for dojo._ioSetArgs call. 13456 13457 if(!dfd.ioArgs.args.failOk){
13458 console.error(error); 13459 } 13460 return error; 13461 }; 13462 13463 //Use a separate count for knowing if we are starting/stopping io calls. 13464 var _checkPubCount = function(dfd){ 13465 if(_pubCount <= 0){ 13466 _pubCount = 0; 13467 if(cfg.ioPublish && dojo.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){ 13468 dojo.publish("/dojo/io/stop"); 13469 } 13470 } 13471 }; 13472 13473 var _pubCount = 0; 13474 aspect.after(watch, "_onAction", function(){ 13475 _pubCount -= 1; 13476 }); 13477 aspect.after(watch, "_onInFlight", _checkPubCount); 13478 13479 dojo._ioCancelAll = watch.cancelAll; 13480 /*===== 13481 dojo._ioCancelAll = function(){ 13482 // summary: 13483 // Cancels all pending IO requests, regardless of IO type 13484 // (xhr, script, iframe). 13485 }; 13486 =====*/ 13487 13488 dojo._ioNotifyStart = function(/*Deferred*/dfd){ 13489 // summary: 13490 // If dojo.publish is available, publish topics 13491 // about the start of a request queue and/or the 13492 // the beginning of request. 13493 // 13494 // Used by IO transports. An IO transport should 13495 // call this method before making the network connection. 13496 if(cfg.ioPublish && dojo.publish && dfd.ioArgs.args.ioPublish !== false){ 13497 if(!_pubCount){ 13498 dojo.publish("/dojo/io/start"); 13499 } 13500 _pubCount += 1; 13501 dojo.publish("/dojo/io/send", [dfd]); 13502 } 13503 }; 13504 13505 dojo._ioWatch = function(dfd, validCheck, ioCheck, resHandle){ 13506 // summary: 13507 // Watches the io request represented by dfd to see if it completes. 13508 // dfd: Deferred 13509 // The Deferred object to watch. 13510 // validCheck: Function 13511 // Function used to check if the IO request is still valid. Gets the dfd 13512 // object as its only argument. 13513 // ioCheck: Function 13514 // Function used to check if basic IO call worked. Gets the dfd 13515 // object as its only argument. 13516 // resHandle: Function 13517 // Function used to process response. Gets the dfd 13518 // object as its only argument. 13519 13520 var args = dfd.ioArgs.options = dfd.ioArgs.args; 13521 lang.mixin(dfd, { 13522 response: dfd.ioArgs, 13523 isValid: function(response){ 13524 return validCheck(dfd); 13525 }, 13526 isReady: function(response){ 13527 return ioCheck(dfd); 13528 }, 13529 handleResponse: function(response){ 13530 return resHandle(dfd); 13531 } 13532 }); 13533 watch(dfd); 13534 13535 _checkPubCount(dfd); 13536 }; 13537 13538 var _defaultContentType = "application/x-www-form-urlencoded"; 13539 13540 dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){ 13541 // summary: 13542 // Adds query params discovered by the io deferred construction to the URL. 13543 // Only use this for operations which are fundamentally GET-type operations. 13544 if(ioArgs.query.length){ 13545 ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query; 13546 ioArgs.query = null; 13547 } 13548 }; 13549 13550 /*===== 13551 dojo.__XhrArgs = declare(dojo.__IoArgs, { 13552 // summary: 13553 // In addition to the properties listed for the dojo._IoArgs type, 13554 // the following properties are allowed for dojo.xhr* methods. 13555 // handleAs: String? 13556 // Acceptable values are: text (default), json, json-comment-optional, 13557 // json-comment-filtered, javascript, xml. See `dojo/_base/xhr.contentHandlers` 13558 // sync: Boolean? 13559 // false is default. Indicates whether the request should 13560 // be a synchronous (blocking) request. 13561 // headers: Object? 13562 // Additional HTTP headers to send in the request. 13563 // failOk: Boolean? 13564 // false is default. Indicates whether a request should be 13565 // allowed to fail (and therefore no console error message in 13566 // the event of a failure) 13567 // contentType: String|Boolean 13568 // "application/x-www-form-urlencoded" is default. Set to false to 13569 // prevent a Content-Type header from being sent, or to a string 13570 // to send a different Content-Type. 13571 }); 13572 =====*/ 13573 13574 dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){ 13575 // summary: 13576 // Deprecated. Use dojo/request instead. 13577 // description: 13578 // Sends an HTTP request with the given method. 13579 // See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts 13580 // for those HTTP methods. There are also methods for "raw" PUT and POST methods 13581 // via dojo.rawXhrPut() and dojo.rawXhrPost() respectively. 13582 // method:
13583 // HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase. 13584 // hasBody: 13585 // If the request has an HTTP body, then pass true for hasBody. 13586 13587 var rDfd; 13588 //Make the Deferred object for this xhr request. 13589 var dfd = dojo._ioSetArgs(args, function(dfd){ 13590 rDfd && rDfd.cancel(); 13591 }, _deferredOk, _deferError); 13592 var ioArgs = dfd.ioArgs; 13593 13594 //Allow for specifying the HTTP body completely. 13595 if("postData" in args){ 13596 ioArgs.query = args.postData; 13597 }else if("putData" in args){ 13598 ioArgs.query = args.putData; 13599 }else if("rawBody" in args){ 13600 ioArgs.query = args.rawBody; 13601 }else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) === -1){ 13602 //Check for hasBody being passed. If no hasBody, 13603 //then only append query string if not a POST or PUT request. 13604 dojo._ioAddQueryToUrl(ioArgs); 13605 } 13606 13607 var options = { 13608 method: method, 13609 handleAs: "text", 13610 timeout: args.timeout, 13611 withCredentials: args.withCredentials, 13612 ioArgs: ioArgs 13613 }; 13614 13615 if(typeof args.headers !== 'undefined'){ 13616 options.headers = args.headers; 13617 } 13618 if(typeof args.contentType !== 'undefined'){ 13619 if(!options.headers){ 13620 options.headers = {}; 13621 } 13622 options.headers['Content-Type'] = args.contentType; 13623 } 13624 if(typeof ioArgs.query !== 'undefined'){ 13625 options.data = ioArgs.query; 13626 } 13627 if(typeof args.sync !== 'undefined'){ 13628 options.sync = args.sync; 13629 } 13630 13631 dojo._ioNotifyStart(dfd); 13632 try{ 13633 rDfd = _xhr(ioArgs.url, options, true); 13634 }catch(e){ 13635 // If XHR creation fails, dojo/request/xhr throws 13636 // When this happens, cancel the deferred 13637 dfd.cancel(); 13638 return dfd; 13639 } 13640 13641 // sync ioArgs 13642 dfd.ioArgs.xhr = rDfd.response.xhr; 13643 13644 rDfd.then(function(){ 13645 dfd.resolve(dfd); 13646 }).otherwise(function(error){ 13647 ioArgs.error = error; 13648 if(error.response){ 13649 error.status = error.response.status; 13650 error.responseText = error.response.text; 13651 error.xhr = error.response.xhr; 13652 } 13653 dfd.reject(error); 13654 }); 13655 return dfd; // dojo/_base/Deferred 13656 }; 13657 13658 dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){ 13659 // summary: 13660 // Sends an HTTP GET request to the server. 13661 return dojo.xhr("GET", args); // dojo/_base/Deferred 13662 }; 13663 13664 dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){ 13665 // summary: 13666 // Sends an HTTP POST request to the server. In addition to the properties 13667 // listed for the dojo.__XhrArgs type, the following property is allowed: 13668 // postData: 13669 // String. Send raw data in the body of the POST request. 13670 return dojo.xhr("POST", args, true); // dojo/_base/Deferred 13671 }; 13672 13673 dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){ 13674 // summary: 13675 // Sends an HTTP PUT request to the server. In addition to the properties 13676 // listed for the dojo.__XhrArgs type, the following property is allowed: 13677 // putData: 13678 // String. Send raw data in the body of the PUT request. 13679 return dojo.xhr("PUT", args, true); // dojo/_base/Deferred 13680 }; 13681 13682 dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){ 13683 // summary: 13684 // Sends an HTTP DELETE request to the server. 13685 return dojo.xhr("DELETE", args); // dojo/_base/Deferred 13686 }; 13687 13688 /* 13689 dojo.wrapForm = function(formNode){ 13690 // summary: 13691 // A replacement for FormBind, but not implemented yet. 13692 13693 // FIXME: need to think harder about what extensions to this we might 13694 // want. What should we allow folks to do w/ this? What events to 13695 // set/send? 13696 throw new Error("dojo.wrapForm not yet implemented"); 13697 } 13698 */ 13699 13700 dojo._isDocumentOk = function(x){ 13701 return util.checkStatus(x.status); 13702 }; 13703 13704 dojo._getText = function(url){ 13705 var result; 13706 dojo.xhrGet({url:url, sync:true, load:function(text){ 13707 result = text; 13708 }}); 13709 return result; 13710 }; 13711 13712 // Add aliases for static functions to dojo.xhr since dojo.xhr is what's returned from this module 13713 lang.mixin(dojo.xhr, { 13714 _xhrObj: dojo._xhrObj, 13715 fieldToObject: domForm.fieldToObject, 13716 formToObject: domForm.toObject, 13717 objectToQuery: ioq.objectToQuery, 13718 formToQuery: domForm.toQuery, 13719 formToJson: domForm.toJson, 13720 queryToObject: ioq.queryToObject, 13721 contentHandlers: handlers, 13722 _ioSetArgs: dojo._ioSetArgs, 13723 _ioCancelAll: dojo._ioCancelAll, 13724 _ioNotifyStart: dojo._ioNotifyStart, 13725 _ioWatch: dojo._ioWatch, 13726 _ioAddQueryToUrl: dojo._ioAddQueryToUrl, 13727 _isDocumentOk: dojo._isDocumentOk, 13728 _getText: dojo._getText, 13729 get: dojo.xhrGet, 13730 post: dojo.xhrPost, 13731 put: dojo.xhrPut, 13732 del: dojo.xhrDelete // because "delete" is a reserved word 13733 }); 13734 13735 return dojo.xhr; 13736}); 13737 13738}, 13739'dojo/io-query':function(){ 13740define(["./_base/lang"], function(lang){ 13741 13742// module: 13743// dojo/io-query 13744 13745var backstop = {}; 13746 13747return { 13748// summary: 13749// This module defines query string processing functions. 13750 13751 objectToQuery: function objectToQuery(/*Object*/ map){ 13752 // summary: 13753 // takes a name/value mapping object and returns a string representing 13754 // a URL-encoded version of that object. 13755 // example: 13756 // this object: 13757 // 13758 // | { 13759 // | blah: "blah", 13760 // | multi: [ 13761 // | "thud", 13762 // | "thonk" 13763 // | ] 13764 // | }; 13765 // 13766 // yields the following query string: 13767 // 13768 // | "blah=blah&multi=thud&multi=thonk" 13769 13770 // FIXME: need to implement encodeAscii!! 13771 var enc = encodeURIComponent, pairs = []; 13772 for(var name in map){ 13773 var value = map[name]; 13774 if(value != backstop[name]){ 13775 var assign = enc(name) + "="; 13776 if(lang.isArray(value)){ 13777 for(var i = 0, l = value.length; i < l; ++i){ 13778 pairs.push(assign + enc(value[i])); 13779 } 13780 }else{ 13781 pairs.push(assign + enc(value)); 13782 } 13783 } 13784 } 13785 return pairs.join("&"); // String 13786 }, 13787 13788 queryToObject: function queryToObject(/*String*/ str){ 13789 // summary: 13790 // Create an object representing a de-serialized query section of a 13791 // URL. Query keys with multiple values are returned in an array. 13792 // 13793 // example: 13794 // This string: 13795 // 13796 // | "foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&" 13797 // 13798 // results in this object structure: 13799 // 13800 // | { 13801 // | foo: [ "bar", "baz" ], 13802 // | thinger: " spaces =blah", 13803 // | zonk: "blarg" 13804 // | } 13805 // 13806 // Note that spaces and other urlencoded entities are correctly 13807 // handled. 13808 13809 // FIXME: should we grab the URL string if we're not passed one? 13810 var dec = decodeURIComponent, qp = str.split("&"), ret = {}, name, val; 13811 for(var i = 0, l = qp.length, item; i < l; ++i){ 13812 item = qp[i]; 13813 if(item.length){ 13814 var s = item.indexOf("="); 13815 if(s < 0){ 13816 name = dec(item); 13817 val = ""; 13818 }else{ 13819 name = dec(item.slice(0, s)); 13820 val = dec(item.slice(s + 1)); 13821 } 13822 if(typeof ret[name] == "string"){ // inline'd type check 13823 ret[name] = [ret[name]]; 13824 } 13825 13826 if(lang.isArray(ret[name])){ 13827 ret[name].push(val); 13828 }else{ 13829 ret[name] = val; 13830 } 13831 } 13832 } 13833 return ret; // Object 13834 } 13835}; 13836}); 13837}, 13838'dojo/dom-form':function(){ 13839define(["./_base/lang", "./dom", "./io-query", "./json"], function(lang, dom, ioq, json){ 13840 // module: 13841 // dojo/dom-form 13842 13843 function setValue(/*Object*/ obj, /*String*/ name, /*String*/ value){ 13844 // summary: 13845 // For the named property in object, set the value. If a value 13846 // already exists and it is a string, convert the value to be an 13847 // array of values. 13848 13849 // Skip it if there is no value 13850 if(value === null){ 13851 return; 13852 } 13853 13854 var val = obj[name]; 13855 if(typeof val == "string"){ // inline'd type check 13856 obj[name] = [val, value]; 13857 }else if(lang.isArray(val)){ 13858 val.push(value); 13859 }else{ 13860 obj[name] = value; 13861 } 13862 } 13863 13864 var exclude = "file|submit|image|reset|button"; 13865 13866 var form = { 13867 // summary: 13868 // This module defines form-processing functions. 13869 13870 fieldToObject: function fieldToObject(/*DOMNode|String*/ inputNode){ 13871 // summary: 13872 // Serialize a form field to a JavaScript object. 13873 // description: 13874 // Returns the value encoded in a form field as
vendor: 4,148 bytes, lines 13875-14003
13875 // as a string or an array of strings. Disabled form elements 13876 // and unchecked radio and checkboxes are skipped. Multi-select 13877 // elements are returned as an array of string values. 13878 // inputNode: DOMNode|String 13879 // returns: Object 13880 13881 var ret = null; 13882 inputNode = dom.byId(inputNode); 13883 if(inputNode){ 13884 var _in = inputNode.name, type = (inputNode.type || "").toLowerCase(); 13885 if(_in && type && !inputNode.disabled){ 13886 if(type == "radio" || type == "checkbox"){ 13887 if(inputNode.checked){ 13888 ret = inputNode.value; 13889 } 13890 }else if(inputNode.multiple){ 13891 ret = []; 13892 var nodes = [inputNode.firstChild]; 13893 while(nodes.length){ 13894 for(var node = nodes.pop(); node; node = node.nextSibling){ 13895 if(node.nodeType == 1 && node.tagName.toLowerCase() == "option"){ 13896 if(node.selected){ 13897 ret.push(node.value); 13898 } 13899 }else{ 13900 if(node.nextSibling){ 13901 nodes.push(node.nextSibling); 13902 } 13903 if(node.firstChild){ 13904 nodes.push(node.firstChild); 13905 } 13906 break; 13907 } 13908 } 13909 } 13910 }else{ 13911 ret = inputNode.value; 13912 } 13913 } 13914 } 13915 return ret; // Object 13916 }, 13917 13918 toObject: function formToObject(/*DOMNode|String*/ formNode){ 13919 // summary: 13920 // Serialize a form node to a JavaScript object. 13921 // description: 13922 // Returns the values encoded in an HTML form as 13923 // string properties in an object which it then returns. Disabled form 13924 // elements, buttons, and other non-value form elements are skipped. 13925 // Multi-select elements are returned as an array of string values. 13926 // formNode: DOMNode|String 13927 // example: 13928 // This form: 13929 // | <form id="test_form"> 13930 // | <input type="text" name="blah" value="blah"> 13931 // | <input type="text" name="no_value" value="blah" disabled> 13932 // | <input type="button" name="no_value2" value="blah"> 13933 // | <select type="select" multiple name="multi" size="5"> 13934 // | <option value="blah">blah</option> 13935 // | <option value="thud" selected>thud</option> 13936 // | <option value="thonk" selected>thonk</option> 13937 // | </select> 13938 // | </form> 13939 // 13940 // yields this object structure as the result of a call to 13941 // formToObject(): 13942 // 13943 // | { 13944 // | blah: "blah", 13945 // | multi: [ 13946 // | "thud", 13947 // | "thonk" 13948 // | ] 13949 // | }; 13950 13951 var ret = {}, elems = dom.byId(formNode).elements; 13952 for(var i = 0, l = elems.length; i < l; ++i){ 13953 var item = elems[i], _in = item.name, type = (item.type || "").toLowerCase(); 13954 if(_in && type && exclude.indexOf(type) < 0 && !item.disabled){ 13955 setValue(ret, _in, form.fieldToObject(item)); 13956 if(type == "image"){ 13957 ret[_in + ".x"] = ret[_in + ".y"] = ret[_in].x = ret[_in].y = 0; 13958 } 13959 } 13960 } 13961 return ret; // Object 13962 }, 13963 13964 toQuery: function formToQuery(/*DOMNode|String*/ formNode){ 13965 // summary: 13966 // Returns a URL-encoded string representing the form passed as either a 13967 // node or string ID identifying the form to serialize 13968 // formNode: DOMNode|String 13969 // returns: String 13970 13971 return ioq.objectToQuery(form.toObject(formNode)); // String 13972 }, 13973 13974 toJson: function formToJson(/*DOMNode|String*/ formNode, /*Boolean?*/ prettyPrint){ 13975 // summary: 13976 // Create a serialized JSON string from a form node or string 13977 // ID identifying the form to serialize 13978 // formNode: DOMNode|String 13979 // prettyPrint: Boolean? 13980 // returns: String 13981 13982 return json.stringify(form.toObject(formNode), null, prettyPrint ? 4 : 0); // String 13983 } 13984 }; 13985 13986 return form; 13987}); 13988 13989}, 13990'dojo/request/watch':function(){ 13991define([ 13992 './util', 13993 '../errors/RequestTimeoutError', 13994 '../errors/CancelError', 13995 '../_base/array', 13996 '../_base/window', 13997 '../has!host-browser?dom-addeventlistener?:../on:' 13998], function(util, RequestTimeoutError, CancelError, array, win, on){ 13999 // avoid setting a timer per request. It degrades performance on IE 14000 // something fierece if we don't use unified loops. 14001 var _inFlightIntvl = null, 14002 _inFlight = []; 14003
14004 function watchInFlight(){ 14005 // summary: 14006 // internal method that checks each inflight XMLHttpRequest to see 14007 // if it has completed or if the timeout situation applies. 14008 14009 var now = +(new Date); 14010 14011 // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating 14012 for(var i = 0, dfd; i < _inFlight.length && (dfd = _inFlight[i]); i++){ 14013 var response = dfd.response, 14014 options = response.options; 14015 if((dfd.isCanceled && dfd.isCanceled()) || (dfd.isValid && !dfd.isValid(response))){ 14016 _inFlight.splice(i--, 1); 14017 watch._onAction && watch._onAction(); 14018 }else if(dfd.isReady && dfd.isReady(response)){ 14019 _inFlight.splice(i--, 1); 14020 dfd.handleResponse(response); 14021 watch._onAction && watch._onAction(); 14022 }else if(dfd.startTime){ 14023 // did we timeout? 14024 if(dfd.startTime + (options.timeout || 0) < now){ 14025 _inFlight.splice(i--, 1); 14026 // Cancel the request so the io module can do appropriate cleanup. 14027 dfd.cancel(new RequestTimeoutError('Timeout exceeded', response)); 14028 watch._onAction && watch._onAction(); 14029 } 14030 } 14031 } 14032 14033 watch._onInFlight && watch._onInFlight(dfd); 14034 14035 if(!_inFlight.length){ 14036 clearInterval(_inFlightIntvl); 14037 _inFlightIntvl = null; 14038 } 14039 } 14040 14041 function watch(dfd){ 14042 // summary: 14043 // Watches the io request represented by dfd to see if it completes. 14044 // dfd: Deferred 14045 // The Deferred object to watch. 14046 // response: Object 14047 // The object used as the value of the request promise. 14048 // validCheck: Function 14049 // Function used to check if the IO request is still valid. Gets the dfd 14050 // object as its only argument. 14051 // ioCheck: Function 14052 // Function used to check if basic IO call worked. Gets the dfd 14053 // object as its only argument. 14054 // resHandle: Function 14055 // Function used to process response. Gets the dfd 14056 // object as its only argument. 14057 if(dfd.response.options.timeout){ 14058 dfd.startTime = +(new Date); 14059 } 14060 14061 if(dfd.isFulfilled()){ 14062 // bail out if the deferred is already fulfilled 14063 return; 14064 } 14065 14066 _inFlight.push(dfd); 14067 if(!_inFlightIntvl){ 14068 _inFlightIntvl = setInterval(watchInFlight, 50); 14069 } 14070 14071 // handle sync requests separately from async: 14072 // http://bugs.dojotoolkit.org/ticket/8467 14073 if(dfd.response.options.sync){ 14074 watchInFlight(); 14075 } 14076 } 14077 14078 watch.cancelAll = function cancelAll(){ 14079 // summary: 14080 // Cancels all pending IO requests, regardless of IO type 14081 try{ 14082 array.forEach(_inFlight, function(dfd){ 14083 try{ 14084 dfd.cancel(new CancelError('All requests canceled.')); 14085 }catch(e){} 14086 }); 14087 }catch(e){} 14088 }; 14089 14090 if(win && on && win.doc.attachEvent){ 14091 // Automatically call cancel all io calls on unload in IE 14092 // http://bugs.dojotoolkit.org/ticket/2357 14093 on(win.global, 'unload', function(){ 14094 watch.cancelAll(); 14095 }); 14096 } 14097 14098 return watch; 14099}); 14100 14101}, 14102'dojo/request/util':function(){ 14103define([ 14104 'exports', 14105 '../errors/RequestError', 14106 '../errors/CancelError', 14107 '../Deferred', 14108 '../io-query', 14109 '../_base/array', 14110 '../_base/lang', 14111 '../promise/Promise' 14112], function(exports, RequestError, CancelError, Deferred, ioQuery, array, lang, Promise){ 14113 exports.deepCopy = function deepCopy(target, source){ 14114 for(var name in source){ 14115 var tval = target[name], 14116 sval = source[name]; 14117 if(tval !== sval){ 14118 if(tval && typeof tval === 'object' && sval && typeof sval === 'object'){ 14119 exports.deepCopy(tval, sval); 14120 }else{ 14121 target[name] = sval; 14122 } 14123 } 14124 } 14125 return target; 14126 }; 14127 14128 exports.deepCreate = function deepCreate(source, properties){ 14129 properties = properties || {}; 14130 var target = lang.delegate(source), 14131 name, value; 14132 14133 for(name in source){ 14134 value = source[name]; 14135 14136 if(value && typeof value === 'object'){ 14137 target[name] = exports.deepCreate(value, properties[name]); 14138 } 14139 } 14140 return exports.deepCopy(target, properties); 14141 }; 14142 14143 var freeze = Object.freeze || function(obj){ return obj; }; 14144 function okHandler(response){ 14145 return freeze(response); 14146 } 14147 function dataHandler (response) { 14148 return response.data || response.text; 14149 } 14150 14151 exports.deferred = function deferred(response, cancel, isValid, isReady, handleResponse, last){ 14152 var def = new Deferred(function(reason){ 14153 cancel && cancel(def, response); 14154 14155 if(!reason || !(reason instanceof RequestError) && !(reason instanceof CancelError)){ 14156 return new CancelError('Request canceled', response); 14157 } 14158 return reason; 14159 }); 14160 14161 def.response = response; 14162 def.isValid = isValid; 14163 def.isReady = isReady; 14164 def.handleResponse = handleResponse; 14165 14166 function errHandler(error){ 14167 error.response = response; 14168 throw error; 14169 } 14170 var responsePromise = def.then(okHandler).otherwise(errHandler); 14171 14172 if(exports.notify){ 14173 responsePromise.then( 14174 lang.hitch(exports.notify, 'emit', 'load'), 14175 lang.hitch(exports.notify, 'emit', 'error') 14176 ); 14177 } 14178 14179 var dataPromise = responsePromise.then(dataHandler); 14180 14181 // http://bugs.dojotoolkit.org/ticket/16794
14182 // The following works around a leak in IE9 through the 14183 // prototype using lang.delegate on dataPromise and 14184 // assigning the result a property with a reference to 14185 // responsePromise. 14186 var promise = new Promise(); 14187 for (var prop in dataPromise) { 14188 if (dataPromise.hasOwnProperty(prop)) { 14189 promise[prop] = dataPromise[prop]; 14190 } 14191 } 14192 promise.response = responsePromise; 14193 freeze(promise); 14194 // End leak fix 14195 14196 14197 if(last){ 14198 def.then(function(response){ 14199 last.call(def, response); 14200 }, function(error){ 14201 last.call(def, response, error); 14202 }); 14203 } 14204 14205 def.promise = promise; 14206 def.then = promise.then; 14207 14208 return def; 14209 }; 14210 14211 exports.addCommonMethods = function addCommonMethods(provider, methods){ 14212 array.forEach(methods||['GET', 'POST', 'PUT', 'DELETE'], function(method){ 14213 provider[(method === 'DELETE' ? 'DEL' : method).toLowerCase()] = function(url, options){ 14214 options = lang.delegate(options||{}); 14215 options.method = method; 14216 return provider(url, options); 14217 }; 14218 }); 14219 }; 14220 14221 exports.parseArgs = function parseArgs(url, options, skipData){ 14222 var data = options.data, 14223 query = options.query; 14224 14225 if(data && !skipData){ 14226 if(typeof data === 'object'){ 14227 options.data = ioQuery.objectToQuery(data); 14228 } 14229 } 14230 14231 if(query){ 14232 if(typeof query === 'object'){ 14233 query = ioQuery.objectToQuery(query); 14234 } 14235 if(options.preventCache){ 14236 query += (query ? '&' : '') + 'request.preventCache=' + (+(new Date)); 14237 } 14238 }else if(options.preventCache){ 14239 query = 'request.preventCache=' + (+(new Date)); 14240 } 14241 14242 if(url && query){ 14243 url += (~url.indexOf('?') ? '&' : '?') + query; 14244 } 14245 14246 return { 14247 url: url, 14248 options: options, 14249 getHeader: function(headerName){ return null; } 14250 }; 14251 }; 14252 14253 exports.checkStatus = function(stat){ 14254 stat = stat || 0; 14255 return (stat >= 200 && stat < 300) || // allow any 2XX response code 14256 stat === 304 || // or, get it out of the cache 14257 stat === 1223 || // or, Internet Explorer mangled the status code 14258 !stat; // or, we're Titanium/browser chrome/chrome extension requesting a local file 14259 }; 14260}); 14261 14262}, 14263'dojo/errors/RequestError':function(){ 14264define(['./create'], function(create){ 14265 // module: 14266 // dojo/errors/RequestError 14267 14268 /*===== 14269 return function(){ 14270 // summary: 14271 // TODOC 14272 }; 14273 =====*/ 14274 14275 return create("RequestError", function(message, response){ 14276 this.response = response; 14277 }); 14278}); 14279 14280}, 14281'dojo/errors/RequestTimeoutError':function(){ 14282define(['./create', './RequestError'], function(create, RequestError){ 14283 // module: 14284 // dojo/errors/RequestTimeoutError 14285 14286 /*===== 14287 return function(){ 14288 // summary: 14289 // TODOC 14290 }; 14291 =====*/ 14292 14293 return create("RequestTimeoutError", null, RequestError, { 14294 dojoType: "timeout" 14295 }); 14296}); 14297 14298}, 14299'dojo/request/xhr':function(){ 14300define([ 14301 '../errors/RequestError', 14302 './watch', 14303 './handlers', 14304 './util', 14305 '../has'/*=====, 14306 '../request', 14307 '../_base/declare' =====*/ 14308], function(RequestError, watch, handlers, util, has/*=====, request, declare =====*/){ 14309 has.add('native-xhr', function(){ 14310 // if true, the environment has a native XHR implementation 14311 return typeof XMLHttpRequest !== 'undefined'; 14312 }); 14313 has.add('dojo-force-activex-xhr', function(){ 14314 return has('activex') && !document.addEventListener && window.location.protocol === 'file:'; 14315 }); 14316 14317 has.add('native-xhr2', function(){ 14318 if(!has('native-xhr')){ return; } 14319 var x = new XMLHttpRequest(); 14320 return typeof x['addEventListener'] !== 'undefined' && 14321 (typeof opera === 'undefined' || typeof x['upload'] !== 'undefined'); 14322 }); 14323 14324 has.add('native-formdata', function(){ 14325 // if true, the environment has a native FormData implementation 14326 return typeof FormData !== 'undefined'; 14327 }); 14328 14329 has.add('native-response-type', function(){ 14330 return has('native-xhr') && typeof new XMLHttpRequest().responseType !== 'undefined'; 14331 }); 14332 14333 has.add('native-xhr2-blob', function(){ 14334 if(!has('native-response-type')){ return; } 14335 var x = new XMLHttpRequest(); 14336 x.open('GET', '/', true); 14337 x.responseType = 'blob'; 14338 // will not be set if unsupported 14339 var responseType = x.responseType; 14340 x.abort(); 14341 return responseType === 'blob'; 14342 }); 14343 14344 // Google Chrome doesn't support "json" response type 14345 // up to version 30, so it's intentionally not included here 14346 var nativeResponseTypes = { 14347 'blob': has('native-xhr2-blob') ? 'blob' : 'arraybuffer', 14348 'document': 'document', 14349 'arraybuffer': 'arraybuffer' 14350 }; 14351 14352 function handleResponse(response, error){ 14353 var _xhr = response.xhr; 14354 response.status = response.xhr.status; 14355 14356 try { 14357 // Firefox throws an error when trying to access 14358 // xhr.responseText if response isn't text 14359 response.text = _xhr.responseText; 14360 } catch (e) {} 14361 14362 if(response.options.handleAs === 'xml'){ 14363 response.data = _xhr.responseXML; 14364 } 14365 14366 if(!error){ 14367 try{ 14368 handlers(response); 14369 }catch(e){ 14370 error = e; 14371 } 14372 } 14373 14374 if(error){ 14375 this.reject(error); 14376 }else if(util.checkStatus(_xhr.status)){ 14377 this.resolve(response); 14378 }else{ 14379 error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response); 14380 14381 this.reject(error); 14382 } 14383 } 14384 14385 var isValid, isReady, addListeners, cancel; 14386 if(has('native-xhr2')){ 14387 // Any platform with XHR2 will only use the watch mechanism for timeout. 14388 14389 isValid = function(response){ 14390 // summary: 14391 // Check to see if the request should be taken out of the watch queue 14392 return !this.isFulfilled(); 14393 }; 14394 cancel = function(dfd, response){ 14395 // summary: 14396 // Canceler for deferred 14397 response.xhr.abort(); 14398 }; 14399 addListeners = function(_xhr, dfd, response){ 14400 // summary: 14401 // Adds event listeners to the XMLHttpRequest object 14402 function onLoad(evt){ 14403 dfd.handleResponse(response); 14404 } 14405 function onError(evt){ 14406 var _xhr = evt.target; 14407 var error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response); 14408 dfd.handleResponse(response, error); 14409 } 14410 14411 function onProgress(evt){ 14412 if(evt.lengthComputable){ 14413 response.loaded = evt.loaded; 14414 response.total = evt.total; 14415 dfd.progress(response); 14416 } else if(response.xhr.readyState === 3){ 14417 response.loaded = evt.position; 14418 dfd.progress(response); 14419 } 14420 } 14421 14422 _xhr.addEventListener('load', onLoad, false); 14423 _xhr.addEventListener('error', onError, false); 14424 _xhr.addEventListener('progress', onProgress, false); 14425 14426 return function(){ 14427 _xhr.removeEventListener('load', onLoad, false); 14428 _xhr.removeEventListener('error', onError, false); 14429 _xhr.removeEventListener('progress', onProgress, false); 14430 _xhr = null; 14431 }; 14432 }; 14433 }else{ 14434 isValid = function(response){ 14435 return response.xhr.readyState; //boolean 14436 }; 14437 isReady = function(response){ 14438 return 4 === response.xhr.readyState; //boolean 14439 }; 14440 cancel = function(dfd, response){ 14441 // summary: 14442 // canceller function for util.deferred call. 14443 var xhr = response.xhr; 14444 var _at = typeof xhr.abort; 14445 if(_at === 'function' || _at === 'object' || _at === 'unknown'){ 14446 xhr.abort(); 14447 } 14448 }; 14449 } 14450 14451 function getHeader(headerName){ 14452 return this.xhr.getResponseHeader(headerName); 14453 } 14454 14455 var undefined, 14456 defaultOptions = { 14457 data: null, 14458 query: null, 14459 sync: false, 14460 method: 'GET' 14461 }; 14462 function xhr(url, options, returnDeferred){ 14463 var isFormData = has('native-formdata') && options && options.data && options.data instanceof FormData; 14464 var response = util.parseArgs( 14465 url, 14466 util.deepCreate(defaultOptions, options), 14467 isFormData 14468 ); 14469 url = response.url; 14470 options = response.options; 14471 14472 var remover, 14473 last = function(){ 14474 remover && remover(); 14475 }; 14476 14477 //Make the Deferred object for this xhr request. 14478 var dfd = util.deferred( 14479 response, 14480 cancel, 14481 isValid, 14482 isReady, 14483 handleResponse, 14484 last 14485 ); 14486 var _xhr = response.xhr = xhr._create(); 14487 14488 if(!_xhr){ 14489 // If XHR factory somehow returns nothings, 14490 // cancel the deferred. 14491 dfd.cancel(new RequestError('XHR was not created')); 14492 return returnDeferred ? dfd : dfd.promise; 14493 } 14494 14495 response.getHeader = getHeader; 14496 14497 if(addListeners){ 14498 remover = addListeners(_xhr, dfd, response); 14499 } 14500 14501 var data = options.data, 14502 async = !options.sync, 14503 method = options.method; 14504 14505 try{ 14506 // IE6 won't let you call apply() on the native function. 14507 _xhr.open(method, url, async, options.user || undefined, options.password || undefined); 14508 14509 if(options.withCredentials){ 14510 _xhr.withCredentials = options.withCredentials; 14511 } 14512 14513 if(has('native-response-type') && options.handleAs in nativeResponseTypes) { 14514 _xhr.responseType = nativeResponseTypes[options.handleAs]; 14515 } 14516 14517 var headers = options.headers, 14518 contentType = isFormData ? false : 'application/x-www-form-urlencoded'; 14519 if(headers){ 14520 for(var hdr in headers){ 14521 if(hdr.toLowerCase() === 'content-type'){ 14522 contentType = headers[hdr]; 14523 }else if(headers[hdr]){ 14524 //Only add header if it has a value. This allows for instance, skipping 14525 //insertion of X-Requested-With by specifying empty value. 14526 _xhr.setRequestHeader(hdr, headers[hdr]); 14527 } 14528 } 14529 } 14530 14531 if(contentType && contentType !== false){ 14532 _xhr.setRequestHeader('Content-Type', contentType); 14533 } 14534 if(!headers || !('X-Requested-With' in headers)){ 14535 _xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 14536 } 14537 14538 if(util.notify){ 14539 util.notify.emit('send', response, dfd.promise.cancel); 14540 } 14541 _xhr.send(data); 14542 }catch(e){ 14543 dfd.reject(e); 14544 } 14545 14546 watch(dfd); 14547 _xhr = null; 14548 14549 return returnDeferred ? dfd : dfd.promise; 14550 } 14551 14552 /*===== 14553 xhr = function(url, options){ 14554 // summary: 14555 // Sends a request using XMLHttpRequest with the given URL and options. 14556 // url: String 14557 // URL to request 14558 // options: dojo/request/xhr.__Options? 14559 // Options for the request. 14560 // returns: dojo/request.__Promise 14561 }; 14562 xhr.__BaseOptions = declare(request.__BaseOptions, { 14563 // sync: Boolean? 14564 // Whether to make a synchronous request or not. Default 14565 // is `false` (asynchronous). 14566 // data: String|Object|FormData?
14567 // Data to transfer. This is ignored for GET and DELETE 14568 // requests. 14569 // headers: Object? 14570 // Headers to use for the request. 14571 // user: String? 14572 // Username to use during the request. 14573 // password: String? 14574 // Password to use during the request. 14575 // withCredentials: Boolean? 14576 // For cross-site requests, whether to send credentials 14577 // or not. 14578 }); 14579 xhr.__MethodOptions = declare(null, { 14580 // method: String? 14581 // The HTTP method to use to make the request. Must be 14582 // uppercase. Default is `"GET"`. 14583 }); 14584 xhr.__Options = declare([xhr.__BaseOptions, xhr.__MethodOptions]); 14585 14586 xhr.get = function(url, options){ 14587 // summary: 14588 // Send an HTTP GET request using XMLHttpRequest with the given URL and options. 14589 // url: String 14590 // URL to request 14591 // options: dojo/request/xhr.__BaseOptions? 14592 // Options for the request. 14593 // returns: dojo/request.__Promise 14594 }; 14595 xhr.post = function(url, options){ 14596 // summary: 14597 // Send an HTTP POST request using XMLHttpRequest with the given URL and options. 14598 // url: String 14599 // URL to request 14600 // options: dojo/request/xhr.__BaseOptions? 14601 // Options for the request. 14602 // returns: dojo/request.__Promise 14603 }; 14604 xhr.put = function(url, options){ 14605 // summary: 14606 // Send an HTTP PUT request using XMLHttpRequest with the given URL and options. 14607 // url: String 14608 // URL to request 14609 // options: dojo/request/xhr.__BaseOptions? 14610 // Options for the request. 14611 // returns: dojo/request.__Promise 14612 }; 14613 xhr.del = function(url, options){ 14614 // summary: 14615 // Send an HTTP DELETE request using XMLHttpRequest with the given URL and options. 14616 // url: String 14617 // URL to request 14618 // options: dojo/request/xhr.__BaseOptions? 14619 // Options for the request. 14620 // returns: dojo/request.__Promise 14621 }; 14622 =====*/ 14623 xhr._create = function(){ 14624 // summary: 14625 // does the work of portably generating a new XMLHTTPRequest object. 14626 throw new Error('XMLHTTP not available'); 14627 }; 14628 if(has('native-xhr') && !has('dojo-force-activex-xhr')){ 14629 xhr._create = function(){ 14630 return new XMLHttpRequest(); 14631 }; 14632 }else if(has('activex')){ 14633 try{ 14634 new ActiveXObject('Msxml2.XMLHTTP'); 14635 xhr._create = function(){ 14636 return new ActiveXObject('Msxml2.XMLHTTP'); 14637 }; 14638 }catch(e){ 14639 try{ 14640 new ActiveXObject('Microsoft.XMLHTTP'); 14641 xhr._create = function(){ 14642 return new ActiveXObject('Microsoft.XMLHTTP'); 14643 }; 14644 }catch(e){} 14645 } 14646 } 14647 14648 util.addCommonMethods(xhr); 14649 14650 return xhr; 14651}); 14652 14653}, 14654'dojo/request/handlers':function(){ 14655define([ 14656 '../json', 14657 '../_base/kernel', 14658 '../_base/array', 14659 '../has', 14660 '../selector/_loader' // only included for has() qsa tests 14661], function(JSON, kernel, array, has){ 14662 has.add('activex', typeof ActiveXObject !== 'undefined'); 14663 has.add('dom-parser', function(global){ 14664 return 'DOMParser' in global; 14665 }); 14666 14667 var handleXML; 14668 if(has('activex')){ 14669 // GUIDs obtained from http://msdn.microsoft.com/en-us/library/ms757837(VS.85).aspx 14670 var dp = [ 14671 'Msxml2.DOMDocument.6.0', 14672 'Msxml2.DOMDocument.4.0', 14673 'MSXML2.DOMDocument.3.0', 14674 'MSXML.DOMDocument' // 2.0 14675 ]; 14676 var lastParser; 14677 14678 handleXML = function(response){ 14679 var result = response.data; 14680 var text = response.text; 14681 14682 if(result && has('dom-qsa2.1') && !result.querySelectorAll && has('dom-parser')){ 14683 // http://bugs.dojotoolkit.org/ticket/15631 14684 // IE9 supports a CSS3 querySelectorAll implementation, but the DOM implementation 14685 // returned by IE9 xhr.responseXML does not. Manually create the XML DOM to gain 14686 // the fuller-featured implementation and avoid bugs caused by the inconsistency 14687 result = new DOMParser().parseFromString(text, 'application/xml'); 14688 } 14689 14690 function createDocument(p) { 14691 try{ 14692 var dom = new ActiveXObject(p); 14693 dom.async = false; 14694 dom.loadXML(text); 14695 result = dom; 14696 lastParser = p; 14697 }catch(e){ return false; } 14698 return true; 14699 } 14700 14701 if(!result || !result.documentElement){ 14702 // The creation of an ActiveX object is expensive, so we cache the 14703 // parser type to avoid trying all parser types each time we handle a 14704 // document. There is some concern that some parser types might fail 14705 // depending on the document being parsed. If parsing using the cached 14706 // parser type fails, we do the more expensive operation of finding one 14707 // that works for the given document. 14708 // https://bugs.dojotoolkit.org/ticket/15246 14709 if(!lastParser || !createDocument(lastParser)) { 14710 array.some(dp, createDocument); 14711 } 14712 } 14713 14714 return result; 14715 }; 14716 } 14717 14718 var handleNativeResponse = function(response) { 14719 if(!has('native-xhr2-blob') && response.options.handleAs === 'blob' && typeof Blob !== 'undefined'){ 14720 return new Blob([ response.xhr.response ], { type: response.xhr.getResponseHeader('Content-Type') }); 14721 } 14722 14723 return response.xhr.response; 14724 } 14725 14726 var handlers = { 14727 'javascript': function(response){ 14728 return kernel.eval(response.text || ''); 14729 }, 14730 'json': function(response){ 14731 return JSON.parse(response.text || null); 14732 },
14733 'xml': handleXML, 14734 'blob': handleNativeResponse, 14735 'arraybuffer': handleNativeResponse, 14736 'document': handleNativeResponse 14737 }; 14738 14739 function handle(response){ 14740 var handler = handlers[response.options.handleAs]; 14741 14742 response.data = handler ? handler(response) : (response.data || response.text); 14743 14744 return response; 14745 } 14746 14747 handle.register = function(name, handler){ 14748 handlers[name] = handler; 14749 }; 14750 14751 return handle; 14752}); 14753 14754}, 14755'dojo/_base/fx':function(){ 14756define(["./kernel", "./config", /*===== "./declare", =====*/ "./lang", "../Evented", "./Color", "../aspect", "../sniff", "../dom", "../dom-style"], 14757 function(dojo, config, /*===== declare, =====*/ lang, Evented, Color, aspect, has, dom, style){ 14758 // module: 14759 // dojo/_base/fx 14760 // notes: 14761 // Animation loosely package based on Dan Pupius' work, contributed under CLA; see 14762 // http://pupius.co.uk/js/Toolkit.Drawing.js 14763 14764 var _mixin = lang.mixin; 14765 14766 // Module export 14767 var basefx = { 14768 // summary: 14769 // This module defines the base dojo/_base/fx implementation. 14770 }; 14771 14772 var _Line = basefx._Line = function(/*int*/ start, /*int*/ end){ 14773 // summary: 14774 // Object used to generate values from a start value to an end value 14775 // start: int 14776 // Beginning value for range 14777 // end: int 14778 // Ending value for range 14779 this.start = start; 14780 this.end = end; 14781 }; 14782 14783 _Line.prototype.getValue = function(/*float*/ n){ 14784 // summary: 14785 // Returns the point on the line 14786 // n: 14787 // a floating point number greater than 0 and less than 1
14788 return ((this.end - this.start) * n) + this.start; // Decimal 14789 }; 14790 14791 var Animation = basefx.Animation = function(args){ 14792 // summary: 14793 // A generic animation class that fires callbacks into its handlers 14794 // object at various states. 14795 // description: 14796 // A generic animation class that fires callbacks into its handlers 14797 // object at various states. Nearly all dojo animation functions 14798 // return an instance of this method, usually without calling the 14799 // .play() method beforehand. Therefore, you will likely need to 14800 // call .play() on instances of `Animation` when one is 14801 // returned. 14802 // args: Object 14803 // The 'magic argument', mixing all the properties into this 14804 // animation instance. 14805 14806 _mixin(this, args); 14807 if(lang.isArray(this.curve)){ 14808 this.curve = new _Line(this.curve[0], this.curve[1]); 14809 } 14810 14811 }; 14812 Animation.prototype = new Evented(); 14813 14814 lang.extend(Animation, { 14815 // duration: Integer 14816 // The time in milliseconds the animation will take to run 14817 duration: 350, 14818 14819 /*===== 14820 // curve: _Line|Array 14821 // A two element array of start and end values, or a `_Line` instance to be 14822 // used in the Animation. 14823 curve: null, 14824 14825 // easing: Function? 14826 // A Function to adjust the acceleration (or deceleration) of the progress 14827 // across a _Line 14828 easing: null, 14829 =====*/ 14830 14831 // repeat: Integer? 14832 // The number of times to loop the animation 14833 repeat: 0, 14834 14835 // rate: Integer? 14836 // the time in milliseconds to wait before advancing to next frame 14837 // (used as a fps timer: 1000/rate = fps) 14838 rate: 20 /* 50 fps */, 14839 14840 /*===== 14841 // delay: Integer? 14842 // The time in milliseconds to wait before starting animation after it 14843 // has been .play()'ed 14844 delay: null, 14845 14846 // beforeBegin: Event? 14847 // Synthetic event fired before a Animation begins playing (synchronous) 14848 beforeBegin: null, 14849 14850 // onBegin: Event? 14851 // Synthetic event fired as a Animation begins playing (useful?) 14852 onBegin: null, 14853 14854 // onAnimate: Event? 14855 // Synthetic event fired at each interval of the Animation 14856 onAnimate: null, 14857 14858 // onEnd: Event? 14859 // Synthetic event fired after the final frame of the Animation 14860 onEnd: null, 14861 14862 // onPlay: Event? 14863 // Synthetic event fired any time the Animation is play()'ed 14864 onPlay: null, 14865 14866 // onPause: Event? 14867 // Synthetic event fired when the Animation is paused 14868 onPause: null, 14869 14870 // onStop: Event 14871 // Synthetic event fires when the Animation is stopped 14872 onStop: null, 14873 14874 =====*/ 14875 14876 _percent: 0, 14877 _startRepeatCount: 0, 14878 14879 _getStep: function(){ 14880 var _p = this._percent, 14881 _e = this.easing 14882 ; 14883 return _e ? _e(_p) : _p; 14884 }, 14885 _fire: function(/*Event*/ evt, /*Array?*/ args){ 14886 // summary: 14887 // Convenience function. Fire event "evt" and pass it the 14888 // arguments specified in "args". 14889 // description: 14890 // Convenience function. Fire event "evt" and pass it the 14891 // arguments specified in "args". 14892 // Fires the callback in the scope of this Animation 14893 // instance. 14894 // evt: 14895 // The event to fire. 14896 // args: 14897 // The arguments to pass to the event. 14898 var a = args||[]; 14899 if(this[evt]){ 14900 if(config.debugAtAllCosts){ 14901 this[evt].apply(this, a); 14902 }else{ 14903 try{ 14904 this[evt].apply(this, a); 14905 }catch(e){ 14906 // squelch and log because we shouldn't allow exceptions in 14907 // synthetic event handlers to cause the internal timer to run 14908 // amuck, potentially pegging the CPU. I'm not a fan of this 14909 // squelch, but hopefully logging will make it clear what's 14910 // going on 14911 console.error("exception in animation handler for:", evt); 14912 console.error(e); 14913 } 14914 } 14915 } 14916 return this; // Animation 14917 }, 14918 14919 play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ 14920 // summary: 14921 // Start the animation. 14922 // delay: 14923 // How many milliseconds to delay before starting. 14924 // gotoStart: 14925 // If true, starts the animation from the beginning; otherwise, 14926 // starts it from its current position. 14927 // returns: Animation 14928 // The instance to allow chaining. 14929 14930 var _t = this; 14931 if(_t._delayTimer){ _t._clearTimer(); } 14932 if(gotoStart){ 14933 _t._stopTimer(); 14934 _t._active = _t._paused = false; 14935 _t._percent = 0; 14936 }else if(_t._active && !_t._paused){ 14937 return _t; 14938 } 14939 14940 _t._fire("beforeBegin", [_t.node]); 14941 14942 var de = delay || _t.delay, 14943 _p = lang.hitch(_t, "_play", gotoStart); 14944 14945 if(de > 0){ 14946 _t._delayTimer = setTimeout(_p, de); 14947 return _t; 14948 } 14949 _p(); 14950 return _t; // Animation 14951 }, 14952 14953 _play: function(gotoStart){ 14954 var _t = this; 14955 if(_t._delayTimer){ _t._clearTimer(); } 14956 _t._startTime = new Date().valueOf(); 14957 if(_t._paused){ 14958 _t._startTime -= _t.duration * _t._percent; 14959 } 14960 14961 _t._active = true; 14962 _t._paused = false;
14963 var value = _t.curve.getValue(_t._getStep()); 14964 if(!_t._percent){ 14965 if(!_t._startRepeatCount){ 14966 _t._startRepeatCount = _t.repeat; 14967 } 14968 _t._fire("onBegin", [value]); 14969 } 14970 14971 _t._fire("onPlay", [value]); 14972 14973 _t._cycle(); 14974 return _t; // Animation 14975 }, 14976 14977 pause: function(){ 14978 // summary: 14979 // Pauses a running animation. 14980 var _t = this; 14981 if(_t._delayTimer){ _t._clearTimer(); } 14982 _t._stopTimer(); 14983 if(!_t._active){ return _t; /*Animation*/ } 14984 _t._paused = true; 14985 _t._fire("onPause", [_t.curve.getValue(_t._getStep())]); 14986 return _t; // Animation 14987 }, 14988 14989 gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){ 14990 // summary: 14991 // Sets the progress of the animation. 14992 // percent: 14993 // A percentage in decimal notation (between and including 0.0 and 1.0). 14994 // andPlay: 14995 // If true, play the animation after setting the progress. 14996 var _t = this; 14997 _t._stopTimer(); 14998 _t._active = _t._paused = true; 14999 _t._percent = percent; 15000 if(andPlay){ _t.play(); } 15001 return _t; // Animation 15002 }, 15003 15004 stop: function(/*boolean?*/ gotoEnd){ 15005 // summary: 15006 // Stops a running animation. 15007 // gotoEnd: 15008 // If true, the animation will end. 15009 var _t = this; 15010 if(_t._delayTimer){ _t._clearTimer(); } 15011 if(!_t._timer){ return _t; /* Animation */ } 15012 _t._stopTimer(); 15013 if(gotoEnd){ 15014 _t._percent = 1; 15015 } 15016 _t._fire("onStop", [_t.curve.getValue(_t._getStep())]); 15017 _t._active = _t._paused = false; 15018 return _t; // Animation 15019 }, 15020 15021 destroy: function(){ 15022 // summary: 15023 // cleanup the animation 15024 this.stop(); 15025 }, 15026 15027 status: function(){ 15028 // summary: 15029 // Returns a string token representation of the status of 15030 // the animation, one of: "paused", "playing", "stopped" 15031 if(this._active){ 15032 return this._paused ? "paused" : "playing"; // String 15033 } 15034 return "stopped"; // String 15035 }, 15036 15037 _cycle: function(){ 15038 var _t = this; 15039 if(_t._active){ 15040 var curr = new Date().valueOf(); 15041 // Allow durations of 0 (instant) by setting step to 1 - see #13798 15042 var step = _t.duration === 0 ? 1 : (curr - _t._startTime) / (_t.duration); 15043 15044 if(step >= 1){ 15045 step = 1; 15046 } 15047 _t._percent = step; 15048 15049 // Perform easing 15050 if(_t.easing){ 15051 step = _t.easing(step); 15052 } 15053 15054 _t._fire("onAnimate", [_t.curve.getValue(step)]); 15055 15056 if(_t._percent < 1){ 15057 _t._startTimer(); 15058 }else{ 15059 _t._active = false; 15060 15061 if(_t.repeat > 0){ 15062 _t.repeat--; 15063 _t.play(null, true); 15064 }else if(_t.repeat == -1){ 15065 _t.play(null, true); 15066 }else{ 15067 if(_t._startRepeatCount){ 15068 _t.repeat = _t._startRepeatCount; 15069 _t._startRepeatCount = 0; 15070 } 15071 } 15072 _t._percent = 0; 15073 _t._fire("onEnd", [_t.node]); 15074 !_t.repeat && _t._stopTimer(); 15075 } 15076 } 15077 return _t; // Animation 15078 }, 15079 15080 _clearTimer: function(){ 15081 // summary: 15082 // Clear the play delay timer 15083 clearTimeout(this._delayTimer); 15084 delete this._delayTimer; 15085 } 15086 15087 }); 15088 15089 // the local timer, stubbed into all Animation instances 15090 var ctr = 0, 15091 timer = null, 15092 runner = { 15093 run: function(){} 15094 }; 15095 15096 lang.extend(Animation, { 15097 15098 _startTimer: function(){ 15099 if(!this._timer){ 15100 this._timer = aspect.after(runner, "run", lang.hitch(this, "_cycle"), true); 15101 ctr++; 15102 } 15103 if(!timer){ 15104 timer = setInterval(lang.hitch(runner, "run"), this.rate); 15105 } 15106 }, 15107 15108 _stopTimer: function(){ 15109 if(this._timer){ 15110 this._timer.remove(); 15111 this._timer = null; 15112 ctr--; 15113 } 15114 if(ctr <= 0){ 15115 clearInterval(timer); 15116 timer = null; 15117 ctr = 0; 15118 } 15119 } 15120 15121 }); 15122 15123 var _makeFadeable = 15124 has("ie") ? function(node){ 15125 // only set the zoom if the "tickle" value would be the same as the 15126 // default 15127 var ns = node.style; 15128 // don't set the width to auto if it didn't already cascade that way. 15129 // We don't want to f anyones designs 15130 if(!ns.width.length && style.get(node, "width") == "auto"){ 15131 ns.width = "auto"; 15132 } 15133 } : 15134 function(){}; 15135 15136 basefx._fade = function(/*Object*/ args){ 15137 // summary: 15138 // Returns an animation that will fade the node defined by 15139 // args.node from the start to end values passed (args.start 15140 // args.end) (end is mandatory, start is optional) 15141 15142 args.node = dom.byId(args.node); 15143 var fArgs = _mixin({ properties: {} }, args), 15144 props = (fArgs.properties.opacity = {}); 15145 15146 props.start = !("start" in fArgs) ? 15147 function(){ 15148 return +style.get(fArgs.node, "opacity")||0; 15149 } : fArgs.start; 15150 props.end = fArgs.end; 15151 15152 var anim = basefx.animateProperty(fArgs); 15153 aspect.after(anim, "beforeBegin", lang.partial(_makeFadeable, fArgs.node), true); 15154 15155 return anim; // Animation 15156 }; 15157 15158 /*===== 15159 var __FadeArgs = declare(null, { 15160 // node: DOMNode|String 15161 // The node referenced in the animation 15162 // duration: Integer? 15163 // Duration of the animation in milliseconds. 15164 // easing: Function? 15165 // An easing function. 15166 }); 15167 =====*/ 15168 15169 basefx.fadeIn = function(/*__FadeArgs*/ args){ 15170 // summary: 15171 // Returns an animation that will fade node defined in 'args' from 15172 // its current opacity to fully opaque. 15173 return basefx._fade(_mixin({ end: 1 }, args)); // Animation 15174 }; 15175 15176 basefx.fadeOut = function(/*__FadeArgs*/ args){ 15177 // summary: 15178 // Returns an animation that will fade node defined in 'args' 15179 // from its current opacity to fully transparent. 15180 return basefx._fade(_mixin({ end: 0 }, args)); // Animation 15181 }; 15182 15183 basefx._defaultEasing = function(/*Decimal?*/ n){ 15184 // summary: 15185 // The default easing function for Animation(s) 15186 return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2); // Decimal 15187 }; 15188 15189 var PropLine = function(properties){
15190 // PropLine is an internal class which is used to model the values of 15191 // an a group of CSS properties across an animation lifecycle. In 15192 // particular, the "getValue" function handles getting interpolated 15193 // values between start and end for a particular CSS value. 15194 this._properties = properties; 15195 for(var p in properties){ 15196 var prop = properties[p]; 15197 if(prop.start instanceof Color){ 15198 // create a reusable temp color object to keep intermediate results 15199 prop.tempColor = new Color(); 15200 } 15201 } 15202 }; 15203 15204 PropLine.prototype.getValue = function(r){ 15205 var ret = {}; 15206 for(var p in this._properties){ 15207 var prop = this._properties[p], 15208 start = prop.start; 15209 if(start instanceof Color){ 15210 ret[p] = Color.blendColors(start, prop.end, r, prop.tempColor).toCss(); 15211 }else if(!lang.isArray(start)){ 15212 ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0); 15213 } 15214 } 15215 return ret; 15216 }; 15217 15218 /*===== 15219 var __AnimArgs = declare(__FadeArgs, { 15220 // properties: Object? 15221 // A hash map of style properties to Objects describing the transition, 15222 // such as the properties of _Line with an additional 'units' property 15223 properties: {} 15224 15225 //TODOC: add event callbacks 15226 }); 15227 =====*/ 15228 15229 basefx.animateProperty = function(/*__AnimArgs*/ args){ 15230 // summary: 15231 // Returns an animation that will transition the properties of 15232 // node defined in `args` depending how they are defined in 15233 // `args.properties` 15234 // 15235 // description: 15236 // Foundation of most `dojo/_base/fx` 15237 // animations. It takes an object of "properties" corresponding to 15238 // style properties, and animates them in parallel over a set 15239 // duration. 15240 // 15241 // example: 15242 // A simple animation that changes the width of the specified node. 15243 // | basefx.animateProperty({ 15244 // | node: "nodeId", 15245 // | properties: { width: 400 }, 15246 // | }).play(); 15247 // Dojo figures out the start value for the width and converts the 15248 // integer specified for the width to the more expressive but 15249 // verbose form `{ width: { end: '400', units: 'px' } }` which you 15250 // can also specify directly. Defaults to 'px' if omitted. 15251 // 15252 // example: 15253 // Animate width, height, and padding over 2 seconds... the 15254 // pedantic way: 15255 // | basefx.animateProperty({ node: node, duration:2000, 15256 // | properties: { 15257 // | width: { start: '200', end: '400', units:"px" }, 15258 // | height: { start:'200', end: '400', units:"px" }, 15259 // | paddingTop: { start:'5', end:'50', units:"px" } 15260 // | } 15261 // | }).play(); 15262 // Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties 15263 // are written using "mixed case", as the hyphen is illegal as an object key. 15264 // 15265 // example: 15266 // Plug in a different easing function and register a callback for 15267 // when the animation ends. Easing functions accept values between 15268 // zero and one and return a value on that basis. In this case, an 15269 // exponential-in curve. 15270 // | basefx.animateProperty({ 15271 // | node: "nodeId", 15272 // | // dojo figures out the start value 15273 // | properties: { width: { end: 400 } }, 15274 // | easing: function(n){ 15275 // | return (n==0) ? 0 : Math.pow(2, 10 * (n - 1)); 15276 // | }, 15277 // | onEnd: function(node){ 15278 // | // called when the animation finishes. The animation 15279 // | // target is passed to this function 15280 // | } 15281 // | }).play(500); // delay playing half a second 15282 // 15283 // example: 15284 // Like all `Animation`s, animateProperty returns a handle to the 15285 // Animation instance, which fires the events common to Dojo FX. Use `aspect.after` 15286 // to access these events outside of the Animation definition: 15287 // | var anim = basefx.animateProperty({ 15288 // | node:"someId", 15289 // | properties:{ 15290 // | width:400, height:500 15291 // | } 15292 // | }); 15293 // | aspect.after(anim, "onEnd", function(){ 15294 // | console.log("animation ended"); 15295 // | }, true); 15296 // | // play the animation now: 15297 // | anim.play(); 15298 // 15299 // example: 15300 // Each property can be a function whose return value is substituted along. 15301 // Additionally, each measurement (eg: start, end) can be a function. The node 15302 // reference is passed directly to callbacks. 15303 // | basefx.animateProperty({ 15304 // | node:"mine", 15305 // | properties:{ 15306 // | height:function(node){ 15307 // | // shrink this node by 50% 15308 // | return domGeom.position(node).h / 2 15309 // | }, 15310 // | width:{ 15311 // | start:function(node){ return 100; }, 15312 // | end:function(node){ return 200; } 15313 // | } 15314 // | } 15315 // | }).play(); 15316 // 15317 15318 var n = args.node = dom.byId(args.node); 15319 if(!args.easing){ args.easing = dojo._defaultEasing; } 15320 15321 var anim = new Animation(args); 15322 aspect.after(anim, "beforeBegin", lang.hitch(anim, function(){ 15323 var pm = {}; 15324 for(var p in this.properties){ 15325 // Make shallow copy of properties into pm because we overwrite 15326 // some values below. In particular if start/end are functions 15327 // we don't want to overwrite them or the functions won't be
15328 // called if the animation is reused. 15329 if(p == "width" || p == "height"){ 15330 this.node.display = "block"; 15331 } 15332 var prop = this.properties[p]; 15333 if(lang.isFunction(prop)){ 15334 prop = prop(n); 15335 } 15336 prop = pm[p] = _mixin({}, (lang.isObject(prop) ? prop: { end: prop })); 15337 15338 if(lang.isFunction(prop.start)){ 15339 prop.start = prop.start(n); 15340 } 15341 if(lang.isFunction(prop.end)){ 15342 prop.end = prop.end(n); 15343 } 15344 var isColor = (p.toLowerCase().indexOf("color") >= 0); 15345 function getStyle(node, p){ 15346 // domStyle.get(node, "height") can return "auto" or "" on IE; this is more reliable: 15347 var v = { height: node.offsetHeight, width: node.offsetWidth }[p]; 15348 if(v !== undefined){ return v; } 15349 v = style.get(node, p); 15350 return (p == "opacity") ? +v : (isColor ? v : parseFloat(v)); 15351 } 15352 if(!("end" in prop)){ 15353 prop.end = getStyle(n, p); 15354 }else if(!("start" in prop)){ 15355 prop.start = getStyle(n, p); 15356 } 15357 15358 if(isColor){ 15359 prop.start = new Color(prop.start); 15360 prop.end = new Color(prop.end); 15361 }else{ 15362 prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start); 15363 } 15364 } 15365 this.curve = new PropLine(pm); 15366 }), true); 15367 aspect.after(anim, "onAnimate", lang.hitch(style, "set", anim.node), true); 15368 return anim; // Animation 15369 }; 15370 15371 basefx.anim = function( /*DOMNode|String*/ node, 15372 /*Object*/ properties, 15373 /*Integer?*/ duration, 15374 /*Function?*/ easing, 15375 /*Function?*/ onEnd, 15376 /*Integer?*/ delay){ 15377 // summary: 15378 // A simpler interface to `animateProperty()`, also returns 15379 // an instance of `Animation` but begins the animation 15380 // immediately, unlike nearly every other Dojo animation API. 15381 // description: 15382 // Simpler (but somewhat less powerful) version 15383 // of `animateProperty`. It uses defaults for many basic properties 15384 // and allows for positional parameters to be used in place of the 15385 // packed "property bag" which is used for other Dojo animation 15386 // methods. 15387 // 15388 // The `Animation` object returned will be already playing, so 15389 // calling play() on it again is (usually) a no-op. 15390 // node: 15391 // a DOM node or the id of a node to animate CSS properties on 15392 // duration: 15393 // The number of milliseconds over which the animation 15394 // should run. Defaults to the global animation default duration 15395 // (350ms). 15396 // easing: 15397 // An easing function over which to calculate acceleration 15398 // and deceleration of the animation through its duration. 15399 // A default easing algorithm is provided, but you may 15400 // plug in any you wish. A large selection of easing algorithms 15401 // are available in `dojo/fx/easing`. 15402 // onEnd: 15403 // A function to be called when the animation finishes 15404 // running. 15405 // delay: 15406 // The number of milliseconds to delay beginning the 15407 // animation by. The default is 0. 15408 // example: 15409 // Fade out a node 15410 // | basefx.anim("id", { opacity: 0 }); 15411 // example: 15412 // Fade out a node over a full second 15413 // | basefx.anim("id", { opacity: 0 }, 1000); 15414 return basefx.animateProperty({ // Animation 15415 node: node, 15416 duration: duration || Animation.prototype.duration, 15417 properties: properties, 15418 easing: easing, 15419 onEnd: onEnd 15420 }).play(delay || 0); 15421 }; 15422 15423 15424 if( 1 ){ 15425 _mixin(dojo, basefx); 15426 // Alias to drop come 2.0: 15427 dojo._Animation = Animation; 15428 } 15429 15430 return basefx; 15431}); 15432 15433}}}); 15434require({cache:{ 15435'dpage/dpage':function(){ 15436define([], 1); 15437 15438}, 15439'dpage/modules/LegacyPlaceholder':function(){ 15440define([ 15441 "dojo/_base/declare" 15442 , "dojo/on" 15443 , "dojo/_base/event" 15444], 15445 function (declare, on, event) { 15446 var theClass = declare("dpage.modules.LegacyPlaceholder", [], { 15447 constructor: function (options) { 15448 } 15449 15450 }); 15451 15452 //static method on the class. 15453 theClass.hasNativePlaceholderSupport = function () { 15454 if (theClass._hasNativeSupport == null) { 15455 var test = document.createElement('input'); 15456 var nativeSupport = test.placeholder !== void 0; 15457 15458 theClass._hasNativeSupport = nativeSupport; 15459 } 15460 15461 return theClass._hasNativeSupport; 15462 } 15463 return theClass; 15464 } 15465); 15466}, 15467'dpage/modules/TabularModel':function(){ 15468define([ 15469 "dojo/_base/declare" 15470 , "dojo/on" 15471 , "dojo/_base/event" 15472 15473 , "dpage/modules/Model" 15474], 15475 function (declare, on, event) { 15476 /** 15477 * @namespace dpage 15478 */ 15479 /** 15480 * @namespace modules 15481 * @memberOf dpage 15482 */ 15483 /** 15484 * Class to provide controlled access to data. This class encapsulates a data structure that mirrors a flat list of columnar data (tabular data). Analogou
15484s 15485 * to a spreadsheet with rows and columns where each value corresponds to the text in each cell. If no model property and no modelProps property is passed 15486 * in, an empty model with a single column name of "default" is created. 15487 * @class TabularModel 15488 * @param {Object} [options] Optional options for the TabularModel. 15489 * @param {Object} [options.model] Object containing the TabularData. 15490 * forms of the model property object:<br> 15491 * 1) {Columns : [ {DataType : "TEXT|NUMBER|DATE|BOOL" , ColumnName : "TheName"} , {nextColDef}], 15492 * Rows : [ {TheName : "row1TheNameVal",...} , {TheName : "row2TheNameVal" , ...} , ...]<br> 15493 * <br/> 15494 * This format gives you more flexibility to provide data types and column names. 15495 * <br/><br/> 15496 * 2) [ {"Col1Name" : "Col1Row1Val" , ...} , {"Col1Name" : "Col1Row2Val" , ...} , ...]<br> 15497 * <br/> 15498 * This format cause the class to set the column names to the property names of the first object in the array. The default 15499 * DataType will be set to TEXT. 15500 * If you pass the modelProps object you can set the 15501 * DataType property for the column name to NUMBER, DATE, BOOL, or TEXT. 15502 * <br/> 15503 * for example modelProps = {c1 : {DataType:"NUMBER"}} 15504 * <br/> 15505 * would set the DataType for column "c1" to NUMBER. This drives validation and column sorting in tables. 15506 * @param {Object} [options.modelProps] Optional properties describing the model including DataType, etc. 15507 * Each property is the name of the column in the model. Each value 15508 * is an object representing a collection of meta-data about the column. 15509 * @param {Object} [options.modelProps.colName] 15510 * @param {String} [options.modelProps.colName.ColumnName] Name of the field in the model (Deprecated). 15511 * @param {String} [options.modelProps.colName.DataType] NUMBER, BOOL, DATE, or TEXT 15512 * @param {String} [options.modelProps.colName.DisplayName] Value used for display of the field to the user. 15513 * @param {String} [options.modelProps.colName.FieldName] Name of the field in the model. 15514 * @param {Number} [options.modelProps.colName.MaxLength] Maximum character length. 15515 * @param {String} [options.modelProps.colName.MaxLengthValidationMessage] Message to display for MaxLength validation failure. 15516 * @param {Number} [options.modelProps.colName.MaxValue] Maximum value for NUMBER type. 15517 * @param {Number} [options.modelProps.colName.MinValue] Minimum value for NUMBER type. 15518 * @param {String} [options.modelProps.colName.NumberValidationMessage] Message to display if the number validation fails. 15519 * @param {Number} [options.modelProps.colName.NumDecimals] Maximum number of decimals for NUMBER type. 15520 * @param {bool} [options.modelProps.colName.Required] Is a non-blank value required in this field 15521 * @param {String} [options.modelProps.colName.RequiredValidationMessage] Message to display for Required validation failure. 15522 * @param {String} [options.modelProps.colName.ValidationPattern] Javascript regular expression for input validation. 15523 * @param {String} [options.modelProps.colName.ValidationPatternMessage] Custom message to display if ValidationPattern fails. 15524 * @param {String} [options.modelProps.colName.ModificationTaintsModel] Default true. If explicitly set to false, changes to the value in this column will NOT taint the model. You can 15525 * determine if the model is tainted by calling the isDirty() method. It will return true for tainted, false for not tainted. 15526 * @memberOf dpage.modules 15527 * @extends {dpage.modules.Model} 15528 */ 15529 var theClass = declare("dpage.modules.TabularModel", [dpage.modules.Model], /** @lends dpage.modules.TabularModel.prototype */ { 15530 _model: null, 15531 _dataCallbacks: null, 15532 _lastDataCallbackId: 0, 15533 _dataCallbackRowId: 0, 15534 _modelProps: null, 15535 _colPropLookup:null, 15536 _isDirty: false, 15537 _supressSerialization : false, 15538 15539 constructor: function (options) { 15540 var self = this; 15541 15542 if (options == null || options.model == null) { 15543 if (options != null && options.defaultColName != null) { 15544 var row = {}; 15545 row[options.defaultColName] = ""; 15546 this._model = { Columns: [{ ColumnName: options.defaultColName, DataType: "TEXT" }], Rows: [] }; // an empty default model. 15547 if (options != null && options.blankDataRow) 15548 this._model.Rows.push(row); 15549 } 15550 else { 15551 this._model = { Columns: [{ ColumnName: "default", DataType: "TEXT" }], Rows: [] }; // an empty default model. 15552 if(options != null && options.blankDataRow) 15553 this._model.Rows.push({ "default": "" }); 15554 } 15555 } 15556 15557 this._dataCallbacks = []; 15558 if (options != null) 15559 { 15560 if (options.modelProps != null) 15561 this._modelProps = options.modelProps; 15562 15563 if (options.model != null) { 15564 this._model = options.model;
15565 this._validateModel(); 15566 } 15567 } 15568 15569 this._colPropLookup = {}; 15570 15571 for(var i=0 ; i<this._model.Columns.length ; i++) 15572 { 15573 this._colPropLookup[this._model.Columns[i].ColumnName] = this._model.Columns[i]; 15574 if (this._colPropLookup[this._model.Columns[i].ColumnName].ModificationTaintsModel === undefined) 15575 this._colPropLookup[this._model.Columns[i].ColumnName].ModificationTaintsModel = true; 15576 } 15577 }, 15578 /** 15579 * You can gain access to the underlying data by calling this method. Typically used for serialization routines. 15580 * Use at your own risk. 15581 * @return {Object} The raw data. 15582 */ 15583 getRawModel: function () 15584 { 15585 var hasObjectType = false; 15586 var newRows; 15587 var newRow; 15588 var oldRow; 15589 15590 for (var i = 0; i < this._model.Columns.length; i++) 15591 if (this._model.Columns[i].DataType == "OBJECT") 15592 hasObjectType = true; 15593 15594 if (hasObjectType) { 15595 newRows = []; 15596 15597 //iterate over the rows of the original model. Create a new row object for each one. 15598 for (var ri = 0 ; ri < this._model.Rows.length ; ri++) { 15599 oldRow = this._model.Rows[ri]; 15600 newRow = {}; 15601 //populate the row with data. 15602 for (var i = 0; i < this._model.Columns.length; i++){ 15603 if (this._model.Columns[i].DataType == "OBJECT") { 15604 if(oldRow[this._model.Columns[i].ColumnName] != null 15605 && 15606 oldRow[this._model.Columns[i].ColumnName].isInstanceOf != null 15607 && 15608 oldRow[this._model.Columns[i].ColumnName].isInstanceOf(dpage.modules.TabularModel)) { 15609 newRow[this._model.Columns[i].ColumnName] = oldRow[this._model.Columns[i].ColumnName].getRawModel(); 15610 } 15611 } 15612 else { 15613 newRow[this._model.Columns[i].ColumnName] = oldRow[this._model.Columns[i].ColumnName]; 15614 } 15615 }
15616 newRows.push(newRow); 15617 } 15618 return newRows; 15619 //wow, that was a lot of work! 15620 } 15621 else { 15622 //much more efficient! 15623 return this._model.Rows; 15624 } 15625 15626 }, 15627 /** 15628 * @return {Array.<Object>} An array of meta-data objects for each column. See the constructor argument options.modelProps for information 15629 * on supported properties. 15630 */ 15631 getColumns: function () 15632 { 15633 return this._model.Columns; 15634 }, 15635 /** 15636 * @param {String} columnName The column name to get info about. 15637 * @return {Object} A reference to the meta-data object for the column in this model. See the constructor argument options.modelProps for information on supported properties. 15638 * Modifying the properties of the returned object causes the properties in the model to be changed as well. Use caution. 15639 */ 15640 getColumnInfo: function (columnName) 15641 { 15642 for(var idx = 0; idx < this._model.Columns.length ; idx++) 15643 { 15644 if (this._model.Columns[idx].ColumnName == columnName) 15645 return this._model.Columns[idx]; 15646 } 15647 }, 15648 /** 15649 * Get the row of data from the TabularModel. Do NOT modify this row or its properties directly if you want things to work correctly. 15650 * @param {Number} rowIndex 15651 * @returns {Object} READ ONLY 15652 */ 15653 getRow: function(rowIndex) 15654 { 15655 return this._model.Rows[rowIndex]; 15656 }, 15657 /** 15658 * You can gain direct access to the data by calling this method. Do not use this unless you know what you are doing. 15659 * Do not modify directly. 15660 * @return {Array.<Array>} Give you back an array of rows. Each row of the array is an array of column values. 15661 */ 15662 getRows: function () 15663 { 15664 return this._model.Rows; 15665 }, 15666 /** Get a unique number identifier for the data row. This can be usefull for keeping track of the this row in lookups 15667 * @returns {Number} Unique number for the data row passed in (global to this model object). 15668 */ 15669 getDataRowId: function (rowObj) { 15670 var rowId; 15671 15672 if (rowObj._getDataRowId == null) { 15673 rowId = this._dataCallbackRowId++; 15674 rowObj._getDataRowId = function () { return rowId; } 15675 } 15676 else { 15677 rowId = rowObj._getDataRowId(); 15678 } 15679 15680 return rowId; 15681 }, 15682 /** 15683 * You can listen for changes to data by adding your callback routine here. Changes can be listened in on a row level 15684 * or global level only. 15685 * @param {function} funcRef The function to call when data is changed (added/updated/removed). The first parameter passed into the callback will be a string ("CHANGE" , "ADD" , "INS" , "DEL" , "INVALIDATE"), 15686 * The second parameter will be the rowObject that the change was made on, and the third parameter will be the dataField that was changed in the event of a CHANGE. 15687 * @param {rowObj} [rowObj] Optional reference to a particular row. If passed in, the funcRef will only 15688 * be called if that particular row is changed. 15689 * @returns {Number} The id of the callback. Can be used to remove the callback. 15690 */ 15691 addDataCallback: function (funcRef, rowObj) { 15692 var rowId; 15693 var id = ++this._lastDataCallbackId; 15694 15695 //if we are only interested in a particular row, we can pass it in here. 15696 if (rowObj != null) { 15697 //this is so that a subscriber can determine whether the row is the row they are bound to. 15698 if (rowObj._getDataRowId == null) { 15699 rowId = this._dataCallbackRowId++; 15700 rowObj._getDataRowId = function () { return rowId; } 15701 } 15702 else 15703 rowId = rowObj._getDataRowId(); 15704 } 15705 else 15706 rowId = null; 15707 15708 this._dataCallbacks.push({ id: id, func: funcRef , rowId : rowId}); 15709 15710 return id; 15711 }, 15712 /** 15713 * @param {Number} id The callback id to remove. 15714 * @returns {void} 15715 */ 15716 removeDataCallback: function (id) { 15717 for (idx = 0; idx < this._dataCallbacks.length ; idx++) 15718 { 15719 if(this._dataCallbacks[idx].id == id) 15720 this._dataCallbacks.splice(idx , 1); 15721 } 15722 }, 15723 /** 15724 * Set a value. The official way to set a value in a TabularModel. Will cause a "CHANGE" change type to be sent to registered callbacks ( callback("CHANGE" , rowObj , dataField) ) 15725 * @param {Number} row The index of the row to set the value of (zero based). 15726 * @param {String} propName The property name (column name) to set. 15727 * @param {Object}
15727 value The value to set. Must be a bool, String, or Number 15728 * @returns {void} 15729 *//** 15730 * Set a value. The official way to set a value in a TabularModel. Will cause a "CHANGE" change type to be sent to registered callbacks ( callback("CHANGE" , rowObj , dataField) ) 15731 * @param {Object} row The row object to set the value for. 15732 * @param {String} propName The property name (column name) to set. 15733 * @param {Object} value The value to set. Must be a bool, String, or Number 15734 * @returns {void} 15735 */ 15736 setValue: function (row, propName, value) { 15737 var rowObj; 15738 var modificationTaints 15739 15740 if (typeof(row) === 'number' || row instanceof Number) 15741 rowObj = this._model.Rows[row]; 15742 else 15743 rowObj = row; 15744 15745 rowObj[propName] = value; 15746 15747 //make sure that the column exists in the model properties and that we don't ignore it. 15748 if (this._colPropLookup[propName] !== undefined && this._colPropLookup[propName].ModificationTaintsModel) 15749 this._isDirty = true; 15750 15751 this.doRowCallbacks(rowObj , propName); 15752 }, 15753 /** 15754 * A caller can cause the registered callback routines to fire by calling this method directly. Not normally needed. 15755 * This will cause the callback routines to be called even if data hasn't really been changed. 15756 * Only use this method if you know what you are doing. 15757 * @param {Array} rowObj The row that we want listeners notified of changes on. 15758 * @param {String} propName The name of the property (column name) that we want to notify listeners of 15759 */ 15760 doRowCallbacks: function (rowObj, propName) { 15761 var rowHasId = rowObj._getDataRowId != null; 15762 15763 for (var x = 0; x < this._dataCallbacks.length ; x++) { 15764 var callback = this._dataCallbacks[x].func; 15765 if (this._dataCallbacks[x].rowId == null) 15766 callback("CHANGE", rowObj, propName); 15767 else if(rowHasId && rowObj._getDataRowId() == this._dataCallbacks[x].rowId) 15768 callback("CHANGE", rowObj, propName); 15769 } 15770 }, 15771 /** 15772 * The official way to get a value in a TabularModel. 15773 * @param {Number} row The zero-based row index. 15774 * @param {String} propName The property name (column name). 15775 * @returns {Object} The data. Will be String, Number, or Boolean 15776 *//** 15777 * The official way to get a value in a TabularModel. 15778 * @param {Object} row The row object to get the value of. 15779 * @param {String} propName The property name (column name). 15780 * @returns {Object} The data. Will be String, Number, or Boolean 15781 */ 15782 getValue: function (row, propName) 15783 { 15784 var rowObj; 15785 15786 if (typeof (row) === 'number' || row instanceof Number) 15787 rowObj = this._model.Rows[row]; 15788 else 15789 rowObj = row; 15790 15791 return rowObj[propName]; 15792 }, 15793 /** 15794 * The official way to set the rows. Will cause a "INVALIDATE" change type to be sent to registered callbacks ( callback("INVALIDATE") ) 15795 * @param {Array} rows The row of data to add. Make sure that the number of columns match what is currently contained 15796 * in the model. 15797 * @returns {void} 15798 */ 15799 setRows: function (rows) { 15800 this._model.Rows = rows 15801 var self = this; 15802 15803 this._isDirty = true; 15804 15805 for (var x = 0; x < this._dataCallbacks.length ; x++) { 15806 var callback = this._dataCallbacks[x].func; 15807 callback("INVALIDATE"); 15808 } 15809 }, 15810 /** 15811 * The official way to add a new row of data to a TabularModel. Adds the row to the end of the existing rows. Will cause a "ADD" change type to be sent to registered callbacks ( callback("ADD" , rowObj) ) 15812 * @param {Object} rowObj The row of data to add. Make sure that the number of columns match what is currently contained 15813 * in the model. 15814 * @returns {void} 15815 */ 15816 addRow: function (rowObj) { 15817 this._model.Rows.push(rowObj); 15818 15819 this._isDirty = true; 15820 15821 for (var x = 0; x < this._dataCallbacks.length ; x++) 15822 { 15823 var callback = this._dataCallbacks[x].func; 15824 callback("ADD", rowObj); 15825 } 15826 }, 15827 15828 /** 15829 * The official way to delete a row of data from a TabularModel. Will cause a "DEL" change type to be sent to registered callbacks ( callback("DEL" , rowObj) ) 15830 * @param {Number} row The row index to delete (zero-based) 15831 * @returns {void} 15832 *//** 15833 * The official way to delete a row of data from a TabularModel. Will cause a "DEL" change type to be sent to registered callbacks ( callback("DEL" , rowObj) ) 15834 * @param {Object} row The rowObj to delete 15835 * @returns {void} 15836 */ 15837 deleteRow: function (row) { 15838 var rowObj; 15839 var idx; 15840 15841 this._isDirty = true; 15842 15843 if (typeof (row) === 'number' || row instanceof Number) { 15844 if (row >= this._model.Rows.length || row < 0) 15845 throw new Error("Invalid row index"); 15846 idx = row; 15847 } 15848 else { 15849 idx = null 15850 for (var i = 0; i < this._model.Rows.length; i++) 15851 if (this._model.Rows[i] === row) 15852 idx = i; 15853 if (idx == null) 15854 throw new Error("Invalid row parameter of " + (row == null ? "null" : (row.toString() + " (" + typeof (row) + ")"))); 15855 } 15856 15857 rowObj = this._model.Rows[idx]; 15858 15859 this._model.Rows.splice(idx, 1); 15860 15861 for (var x = 0; x < this._dataCallbacks.length ; x++) { 15862 var callback = this._dataCallbacks[x].func; 15863 callback("DEL", rowObj); 15864 } 15865 }, 15866 /** 15867 * The official way to insert a new row of data. The row can be inserted anyw
15867here, unlike the addRow, which adds 15868 * the row to the end of the data. Will cause a "INS" change type to be sent to registered callbacks ( callback("INS" , rowObj) ) 15869 * @param {Object} rowObj The row to add. 15870 * @param {Number} idx The row index to add the row into (zero based) 15871 * @returns {void} 15872 */ 15873 insertRow: function (rowObj, idx) { 15874 this._model.Rows.splice(idx, 0, rowObj); 15875 15876 this._isDirty = true; 15877 15878 for (var x = 0; x < this._dataCallbacks.length ; x++) { 15879 var callback = this._dataCallbacks[x].func; 15880 callback("INS", rowObj); 15881 } 15882 }, 15883 /** 15884 * Has the data for the model been updated? 15885 * @returns {bool} true or false. 15886 */ 15887 isDirty : function() 15888 { 15889 return this._isDirty; 15890 }, 15891 setClean: function () { 15892 this._isDirty = false; 15893 }, 15894 /** 15895 * Deletes all of the rows. Will cause an "INVALIDATE" change type to be sent to registered callbacks ( callback("INVALIDATE") ). 15896 * @returns {void} 15897 */ 15898 clear : function() 15899 { 15900 this._model.Rows = []; 15901 15902 for (var x = 0; x < this._dataCallbacks.length ; x++) { 15903 var callback = this._dataCallbacks[x].func; 15904 callback("INVALIDATE"); 15905 } 15906 }, 15907 /** 15908 Widgets have a specific structure for a data model. 15909 @private 15910 */ 15911 _validateModel: function () { 15912 var self = this; 15913 15914 if (this._model == null) 15915 throw new Error("Model is null"); 15916 15917 //turn a model comprised of just row data into one that has Columns and Rows. 15918 if (this._model instanceof Array) 15919 { 15920 var modelRows = this._model; 15921 this._model = {}; 15922 this._model.Rows = modelRows; 15923 this._model.Columns = []; 15924 15925 for(var k in this._model.Rows[0]) 15926 { 15927 if(this._model.Rows[0].hasOwnProperty(k)) 15928 { 15929 var col = { "DataType": "TEXT", "ColumnName": k }; 15930 15931 if (this._modelProps != null && this._modelProps[k] != null) 15932 { 15933 for(var l in this._modelProps[k]) 15934 { 15935 if (this._modelProps[k].hasOwnProperty(l)) 15936 col[l] = this._modelProps[k][l]; 15937 } 15938 } 15939 15940 this._model.Columns.push(col); 15941 } 15942 } 15943 15944 //add column definitions. 15945 if(this._model.Columns.length ==0 && this._modelProps != null) 15946 { 15947 for (var k in this._modelProps) { 15948 if (this._modelProps.hasOwnProperty(k)) { 15949 this._model.Columns.push(this._modelProps[k]); 15950 } 15951 } 15952 } 15953 } 15954 15955 if (this._model.Columns == null) 15956 throw new Error("Model.Columns is null"); 15957 15958 if (!this._model.Columns instanceof Array) 15959 throw new Error("Model.Columns must be an array."); 15960 15961 for (var idx = 0; idx < this._model.Columns.length; idx++) { 15962 if (this._model.Columns[idx].DataType == null 15963 || 15964 this._model.Columns[idx].ColumnName == null) { 15965 throw new Error("Each Model.Column must contain a DataType and a ColumnName property") 15966 } 15967 15968 if (this._model.Columns[idx].DataType != "TEXT" 15969 && this._model.Columns[idx].DataType != "NUMBER" 15970 && this._model.Columns[idx].DataType != "DATE" 15971 && this._model.Columns[idx].DataType != "OBJECT" 15972 && this._model.Columns[idx].DataType != "BOOL" 15973 ) { 15974 throw new Error("Model.Columns[" + idx + "].DataType must be either TEXT or NUMBER or DATE or BOOL or OBJECT"); 15975 } 15976 15977 15978 } 15979 if (this._model.Rows == undefined) 15980 throw new Error("Model.Rows must be defined"); 15981 15982 if (this._model.Rows != null && !this._model.Rows instanceof Array) 15983 throw new Error("Model.Rows must be an array"); 15984 15985 } 15986 }); 15987 15988 theClass._currentRowId = 0; 15989 15990 /**Determine if two row references from a TabularModel are the exact same row. 15991 * @memberof dpage.modules.TabularModel 15992 * @name isSameRow 15993 * @function 15994 * @param {Object} rowObj The first row to compare 15995 * @param {Object} rowObj2 The second row to compare 15996 * @returns {bool} True if the two parameters are the same row, false if not. 15997 */ 15998 theClass.isSameRow = function (rowObj, rowObj2) { 15999 return rowObj === rowObj2; 16000 }; 16001 16002 return theClass; 16003 } 16004); 16005}, 16006'dpage/modules/Model':function(){ 16007define([ 16008 "dojo/_base/declare" 16009 , "dojo/on" 16010 , "dojo/_base/event" 16011], 16012 function (declare, on, event) { 16013 /** 16014 * @namespace dpage 16015 */ 16016 /** 16017 * @namespace modules 16018 * @memberOf dpage 16019 */ 16020 /** 16021 * Class to provide controlled access to data. This class encapsulates a single scalar value such as a string, boolean, date, or number. 16022 * @class Model 16023 * @memberOf dpage.modules 16024 */ 16025 return declare("dpage.modules.Model", [], /** @lends dpage.modules.Model.prototype */ { 16026 _suppressSerialization: false, 16027 16028 constructor: function (options) { 16029 16030 }, 16031 /** 16032 * You can gain access to the underlying data by calling this method. This is typically used by serialization routines to gain access to the raw data structure. 16033 * @return {Object} 16034 */ 16035 getRawModel: function () { 16036 throw new Error("Subclass must implement this method"); 16037 }, 16038 /** 16039 * If set to true, the model will be sent back to the server as a null value. Does not affect the data on the page. Use this if you have large 16040 * model values that you don't want sent back to the server on submit. 16041 * @param {bool} val When null, just return the current state. Otherwise, true or false. 16042 * @returns {bool} The current state. 16043 */ 16044 suppressSerialization: function (val) { 16045 if (val != null) 16046 this._suppressSerialization = val; 16047 16048 return this._suppressSerialization; 16049 }, 16050 16051 /** 16052 * Returns true if the data in the model has been modified. 16053 * @returns {bool} 16054 */ 16055 isDirty : function() 16056 { 16057 throw new Error("Subclass must implement this method"); 16058 }, 16059 16060 /** 16061 * Will cause calls to isDirty() to return false until the data in the model is updated. 16062 * @returns {void} 16063 */ 16064 setClean : function() 16065 { 16066 throw new Error("Subclass must implement this method"); 16067 } 16068 }); 16069 } 16070); 16071}, 16072'dpage/widgets/Anchor':function(){ 16073define([ 16074 "dojo/_base/event" 16075 ,"dojo/on" 16076 ,"dojo/dom-attr" 16077 ,"dojo/dom-class" 16078 ,"dojo/mouse" 16079 ,"dojo/dom-geometry" 16080 , "dojo/dom-style" 16081 , "dojo/json" 16082 16083 , "dpage/modules/Date" 16084 , "dpage/modules/TabularModel" 16085 , "dojo/request/xhr"
16086 ,"dojox/html/entities" 16087 ,"dojo/_base/declare" 16088 , "dpage/widgets/SingleValueWidget"], 16089function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 16090 /** 16091 * @namespace dpage 16092 */ 16093 /** 16094 * @namespace widgets 16095 * @memberOf dpage 16096 */ 16097 /** 16098 * Class to encapulate blocks of text on a page. The label can be bound to data which is where it makes the most sense. 16099 * If the datatype of the model is DATE, the default date formatter is used to display it (dpage.modules.Date.formatDate()) 16100 * @class Anchor 16101 * @param {Object} [options] Optional options for the widget. 16102 * @param {bool} [options.noHTMLEncode] Dont' html encode the display data if set to true (not recommended). 16103 * @param {Function} [options.formatter] Function that will be used to format the data. The raw value is passed as a single param. Return the value 16104 * to display. 16105 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. Controls the text (display) of the href. 16106 * @param {dpage.modules.SingleValueModel} [options.linkModel] Controls the href attribute of the link. 16107 * @param {function} [options.onClick] Click event. 16108 * @param {bool} [options.disableClick] Default false. If set, disables the click event so that the link will not be followed. 16109 16110 * @param {dpage.widgets.Container} [options.container] The container of the widget. 16111 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 16112 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 16113 * is created. 16114 * @param {Object} [containerNode] Optional container node to tie the widget to. The only valid node is an HREF node. 16115 * @memberOf dpage.widgets 16116 * @extends {dpage.widgets.SingleValueWidget} 16117 */ 16118 return dojo.declare("dpage.widgets.Anchor", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Anchor.prototype */ { 16119 _containerNode: null, 16120 _dataType: null, 16121 _formatter: null, 16122 _htmlEncode: true, 16123 _linkCallbackId: null, 16124 _linkModel: null, 16125 _onClick: null, 16126 _preventClick : false, 16127 16128 constructor: function (options, srcNodeRef) 16129 { 16130 var self = this; 16131 this._containerNode = srcNodeRef; 16132 16133 this._onClick = []; 16134 16135 if (this._containerNode == null) { 16136 this._containerNode = document.createElement("A"); 16137 } 16138 16139 if (this._containerNode.nodeName != "A") 16140 throw new Error("Source node for dpage.widgets.Anchor must be an A."); 16141 16142 if (options != null) 16143 { 16144 if (options.formatter != null) 16145 this._formatter = options.formatter; 16146 if (options.noHTMLEncode) 16147 this._htmlEncode = false; 16148 if(options.linkModel != null) 16149 this._linkModel = options.linkModel; 16150 if (options.onClick != null) 16151 this._onClick.push(options.onClick); 16152 if (options.disableClick != null) { 16153 this._preventClick = options.disableClick; 16154 if (this._preventClick) 16155 this._onClick.push(function (o) { o.event.preventDefault(); }); 16156 } 16157 } 16158 16159 if (options == null || options.linkModel == null) 16160 this._linkModel = new dpage.modules.SingleValueModel({ model: "#" }); 16161 16162 on(this._containerNode, "click", function (event) { self._doClick(event); }); 16163 16164 this._linkCallbackId = this._linkModel.addDataCallback(function (val) { self._linkModel_Callback(val); }); 16165 }, 16166 postCreate : function() 16167 { 16168 this._updateLink(); 16169 return this.inherited(arguments); 16170 }, 16171 _linkModel_Callback: function (val) { 16172 this._updateLink(); 16173 }, 16174 setModel : function(model) 16175 { 16176 this.inherited(arguments); 16177 16178 this._updateView(); 16179 }, 16180 /** Sets the linkModel property 16181 * @param {dpage.widgets.SingleValueModel} model 16182 * @returns {void} 16183 */ 16184 setLinkModel : function(model) 16185 { 16186 this._linkModel.removeDataCallback(this._linkCallbackId); 16187 this._linkModel = model; 16188 model.addDataCallback(function (val) { self._linkModel_Callback(val); }); 16189 this._updateLink(); 16190 }, 16191 _renderText : function(rawValue) 16192 { 16193 var dVal = this.renderText(rawValue); 16194 var eVal; 16195 16196 if (this._htmlEncode) { 16197 eVal = dojox.html.entities.encode(dVal); 16198 eVal = eVal.replace(/ /g, " "); 16199 return eVal; 16200 } 16201 else 16202 return dVal; 16203 }, 16204 /** Can be overridden by a subclass. formats the text that is displayed. 16205 * @param {String} rawValue the value to render. 16206 * @returns {String} value to display (will be html-encoded unless overridden) 16207 */ 16208 renderText : function(rawValue) 16209 { 16210 //if a formatter function is specified, use it to render the text. 16211 if (this._formatter != null) 16212 return this._formatter(rawValue); 16213 else if (this.getModel().getMetadata().DataType == "DATE") 16214 return dpage.modules.Date.formatDate(dpage.modules.Date.parseModelValue(rawValue)); 16215 else 16216 return rawValue; 16217 }, 16218 _updateView : function() 16219 { 16220 var vtd = this.getValue(); 16221 16222 if (vtd == null) 16223 vtd = ""; 16224 16225 this._containerNode.innerHTML = this._renderText(vtd.toString()); 16226 }, 16227 _updateLink : function() 16228 { 16229 this._containerNode.setAttribute("href", this._linkModel.getValue()); 16230 }, 16231 _doClick : function(evt) 16232 { 16233 //call callbacks in order. 16234 for (var i = 0; i < this._onClick.length; i++) 16235 this._onClick[i]({ event: evt, widget: self }); 16236 }, 16237 /** 16238 * Set an event handler. 16239 * @param {String} eventName The event to bind to. Only supported events are "click". 16240 * @param {function} functionRef The callback function to call. 16241 * @returns {void} 16242 */ 16243 on: function (eventName, functionRef) { 16244 var self = this; 16245 16246 if (eventName != "click") 16247 throw new Error("Supported events are: 'click'."); 16248 16249 this._onClick.push(functionRef); 16250 16251 }, 16252 destroy : function() 16253 { 16254 this._linkModel.removeDataCallback(this._linkCallbackId); 16255 return this.inherited(arguments); 16256 } 16257 }); 16258}); 16259 16260}, 16261'dpage/modules/Date':function(){ 16262define([ 16263 "dojo/date/stamp", 16264 "dojo/_base/declare", 16265 "dojo/date/locale" 16266 16267], 16268 function (stamp , declare , locale) { 16269 /** 16270 * @namespace dpage 16271 */ 16272 /** 16273 * @namespace modules 16274 * @memberOf dpage 16275 */ 16276 /** 16277 * Provides Date helper functions. Default date format is M/d/yyyy and it can be changed. 16278 * @class Date 16279 * @memberOf dpage.modules 16280 */ 16281 var theClass = declare("dpage.modules.Date", [], /** @lends dpage.modules.Date.prototype */ { 16282 16283 constructor: function (options) { 16284 var self = this; 16285 16286 } 16287 }); 16288 16289 theClass._currentRowId = 0; 16290
16291 /**Parse an ISO-8601 date string into a javascript Date Object. Only needed because the parsing of 16292 * The ISO-8601 date string is flakey depending on what version of javascript you are running. Some 16293 * assume local time, others assume GMT if the timezone info is missing on the string. This method 16294 * solves the problem. If the date string has no time zone info, localtime is assumed. 16295 * @memberof dpage.modules.Date 16296 * @name parseModelValue 16297 * @function 16298 * @param {String} dateStr The date string from the model in ISO-8601 format. 16299 * @returns {Date} Javascript Date Object or null if the date could not be parsed. 16300 */ 16301 theClass.parseModelValue = function (dateStr) { 16302 var ds; 16303 var offsetInHours; 16304 var sign; 16305 16306 if (dateStr == null) 16307 return null; 16308 16309 if (dateStr.match(/^\s*$/) != null) 16310 return null; 16311 16312 //dojo's fromISOString provides a more browser agnostic way of parsing an ISO 8601 date string reliably. 16313 return stamp.fromISOString(dateStr); 16314 }; 16315 16316 theClass._defaultDateFormat = "M/d/yyyy"; 16317 16318 /**Stringifies a date object for use in a dpage DATE type model value. Uses ISO 8601 format. 16319 * @memberof dpage.modules.Date 16320 * @name toModelValue 16321 * @function 16322 * @param {Date} jsDateObj The javascript date 16323 * @returns {String} The serialized value to store in the model. 16324 */ 16325 theClass.toModelValue = function (jsDateObj) { 16326 return jsDateObj.toISOString(); 16327 }; 16328 16329 /**Parses a date using the dpage.modules.Date.getDatePattern(), or custom pattern 16330 * @memberof dpage.modules.Date 16331 * @name parseDateString 16332 * @function 16333 * @param {String} dateStr The date string to parse 16334 * @param {String} optionalDateFormat Optional pattern to use. 16335 * @returns {Date} The parsed date or null if the date could not be parsed. 16336 */ 16337 theClass.parseDateString = function (dateStr , optionalDateFormat) { 16338 if (dateStr == null) 16339 return null; 16340 16341 return locale.parse(dateStr, { 16342 datePattern: optionalDateFormat == null ? dpage.modules.Date._defaultDateFormat : optionalDateFormat, 16343 selector : "date" 16344 }); 16345 }; 16346 16347 /**Sets the default formatter pattern used to format and parse dates in dpage. The format of the 16348 * string is defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a> 16349 * A good practice is to avoid calling this method anywere other than from the Page that contains the widgets. 16350 * @memberof dpage.modules.Date 16351 * @name setDatePattern 16352 * @function 16353 * @param {String} dateFormatStr The format string defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a> 16354 * @returns {void} 16355 */ 16356 theClass.setDatePattern = function (dateFormatStr) { 16357 dpage.modules.Date._defaultDateFormat = dateFormatStr; 16358 }; 16359 16360 /**Get the default formatter pattern used to format and parse dates in dpage. The format of the 16361 * string is defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a> 16362 * @memberof dpage.modules.Date 16363 * @name getDatePattern 16364 * @function 16365 * @returns {String} The format string defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a> 16366 */ 16367 theClass.getDatePattern = function () { 16368 return dpage.modules.Date._defaultDateFormat; 16369 }; 16370 16371 /**Formats a javascript date object according to the current default dpage date format or custom format. 16372 * The default date format can be set by calling dpage.modules.Date.setDatePattern(formatFunc); 16373 * @memberof dpage.modules.Date 16374 * @name formatDate 16375 * @function 16376 * @param {Date} jsDateObj The js date object. 16377 * @param {String} optionalDateFormat Optional pattern to use. 16378 * @returns {String} 16379 */ 16380 theClass.formatDate = function (jsDateObj , optionalDateFormat) { 16381 16382 if (jsDateObj == null) 16383 return ""; 16384 16385 return locale.format(jsDateObj, { 16386 datePattern: optionalDateFormat == null ? dpage.modules.Date._defaultDateFormat : optionalDateFormat, 16387 selector : "date" 16388 }); 16389 }; 16390 16391 return theClass; 16392 } 16393); 16394}, 16395'dojo/date/stamp':function(){ 16396define(["../_base/lang", "../_base/array"], function(lang, array){ 16397 16398// module: 16399// dojo/date/stamp 16400 16401var stamp = { 16402 // summary: 16403 // TODOC 16404}; 16405lang.setObject("dojo.date.stamp", stamp); 16406 16407// Methods to convert dates to or from a wire (string) format using well-known conventions 16408 16409stamp.fromISOString = function(/*String*/ formattedString, /*Number?*/ defaultTime){ 16410 // summary: 16411 // Returns a Date object given a string formatted according to a subset of the ISO-8601 standard. 16412 // 16413 // description: 16414 // Accepts a string formatted according to a profile of ISO8601 as defined by 16415 // [RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
16416 // Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime) 16417 // The following combinations are valid: 16418 // 16419 // - dates only 16420 // - yyyy 16421 // - yyyy-MM 16422 // - yyyy-MM-dd 16423 // - times only, with an optional time zone appended 16424 // - THH:mm 16425 // - THH:mm:ss 16426 // - THH:mm:ss.SSS 16427 // - and "datetimes" which could be any combination of the above 16428 // 16429 // timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm 16430 // Assumes the local time zone if not specified. Does not validate. Improperly formatted 16431 // input may return null. Arguments which are out of bounds will be handled 16432 // by the Date constructor (e.g. January 32nd typically gets resolved to February 1st) 16433 // Only years between 100 and 9999 are supported. 16434 // formattedString: 16435 // A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00 16436 // defaultTime: 16437 // Used for defaults for fields omitted in the formattedString. 16438 // Uses 1970-01-01T00:00:00.0Z by default. 16439 16440 if(!stamp._isoRegExp){ 16441 stamp._isoRegExp = 16442//TODO: could be more restrictive and check for 00-59, etc. 16443 /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/; 16444 } 16445 16446 var match = stamp._isoRegExp.exec(formattedString), 16447 result = null; 16448 16449 if(match){ 16450 match.shift(); 16451 if(match[1]){match[1]--;} // Javascript Date months are 0-based 16452 if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds 16453 16454 if(defaultTime){ 16455 // mix in defaultTime. Relatively expensive, so use || operators for the fast path of defaultTime === 0 16456 defaultTime = new Date(defaultTime); 16457 array.forEach(array.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){ 16458 return defaultTime["get" + prop](); 16459 }), function(value, index){ 16460 match[index] = match[index] || value; 16461 }); 16462 } 16463 result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0); //TODO: UTC defaults 16464 if(match[0] < 100){ 16465 result.setFullYear(match[0] || 1970); 16466 } 16467 16468 var offset = 0, 16469 zoneSign = match[7] && match[7].charAt(0); 16470 if(zoneSign != 'Z'){ 16471 offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0); 16472 if(zoneSign != '-'){ offset *= -1; } 16473 } 16474 if(zoneSign){ 16475 offset -= result.getTimezoneOffset(); 16476 } 16477 if(offset){ 16478 result.setTime(result.getTime() + offset * 60000); 16479 } 16480 } 16481 16482 return result; // Date or null 16483}; 16484 16485/*===== 16486var __Options = { 16487 // selector: String 16488 // "date" or "time" for partial formatting of the Date object. 16489 // Both date and time will be formatted by default. 16490 // zulu: Boolean 16491 // if true, UTC/GMT is used for a timezone 16492 // milliseconds: Boolean 16493 // if true, output milliseconds 16494}; 16495=====*/ 16496 16497stamp.toISOString = function(/*Date*/ dateObject, /*__Options?*/ options){ 16498 // summary: 16499 // Format a Date object as a string according a subset of the ISO-8601 standard 16500 // 16501 // description: 16502 // When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt) 16503 // The local time zone is included as an offset from GMT, except when selector=='time' (time without a date) 16504 // Does not check bounds. Only years between 100 and 9999 are supported. 16505 // 16506 // dateObject: 16507 // A Date object 16508 16509 var _ = function(n){ return (n < 10) ? "0" + n : n; }; 16510 options = options || {}; 16511 var formattedDate = [], 16512 getter = options.zulu ? "getUTC" : "get", 16513 date = ""; 16514 if(options.selector != "time"){ 16515 var year = dateObject[getter+"FullYear"](); 16516 date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-'); 16517 } 16518 formattedDate.push(date); 16519 if(options.selector != "date"){ 16520 var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':'); 16521 var millis = dateObject[getter+"Milliseconds"](); 16522 if(options.milliseconds){ 16523 time += "."+ (millis < 100 ? "0" : "") + _(millis); 16524 } 16525 if(options.zulu){ 16526 time += "Z"; 16527 }else if(options.selector != "time"){ 16528 var timezoneOffset = dateObject.getTimezoneOffset(); 16529 var absOffset = Math.abs(timezoneOffset); 16530 time += (timezoneOffset > 0 ? "-" : "+") + 16531 _(Math.floor(absOffset/60)) + ":" + _(absOffset%60); 16532 } 16533 formattedDate.push(time); 16534 } 16535 return formattedDate.join('T'); // String 16536}; 16537 16538return stamp; 16539}); 16540 16541}, 16542'dojo/date/locale':function(){ 16543define([ 16544 "../_base/lang", 16545 "../_base/array", 16546 "../date", 16547 /*===== "../_base/declare", =====*/ 16548 "../cldr/supplemental", 16549 "../i18n", 16550 "../regexp", 16551 "../string", 16552 "../i18n!../cldr/nls/gregorian", 16553 "module" 16554], function(lang, array, date, /*===== declare, =====*/ supplemental, i18n, regexp, string, gregorian, module){ 16555 16556// module: 16557// dojo/date/locale 16558 16559var exports = { 16560 // summary: 16561 // This modules defines dojo/date/locale, localization methods for Date. 16562};
16563lang.setObject(module.id.replace(/\//g, "."), exports); 16564 16565// Localization methods for Date. Honor local customs using locale-dependent dojo.cldr data. 16566 16567// Load the bundles containing localization information for 16568// names and formats 16569 16570//NOTE: Everything in this module assumes Gregorian calendars. 16571// Other calendars will be implemented in separate modules. 16572 16573 // Format a pattern without literals 16574 function formatPattern(dateObject, bundle, options, pattern){ 16575 return pattern.replace(/([a-z])\1*/ig, function(match){ 16576 var s, pad, 16577 c = match.charAt(0), 16578 l = match.length, 16579 widthList = ["abbr", "wide", "narrow"]; 16580 switch(c){ 16581 case 'G': 16582 s = bundle[(l < 4) ? "eraAbbr" : "eraNames"][dateObject.getFullYear() < 0 ? 0 : 1]; 16583 break; 16584 case 'y': 16585 s = dateObject.getFullYear(); 16586 switch(l){ 16587 case 1: 16588 break; 16589 case 2: 16590 if(!options.fullYear){ 16591 s = String(s); s = s.substr(s.length - 2); 16592 break; 16593 } 16594 // fallthrough 16595 default: 16596 pad = true; 16597 } 16598 break; 16599 case 'Q': 16600 case 'q': 16601 s = Math.ceil((dateObject.getMonth()+1)/3); 16602// switch(l){ 16603// case 1: case 2: 16604 pad = true; 16605// break; 16606// case 3: case 4: // unimplemented 16607// } 16608 break; 16609 case 'M': 16610 case 'L': 16611 var m = dateObject.getMonth(); 16612 if(l<3){ 16613 s = m+1; pad = true; 16614 }else{ 16615 var propM = [ 16616 "months", 16617 c == 'L' ? "standAlone" : "format", 16618 widthList[l-3] 16619 ].join("-"); 16620 s = bundle[propM][m]; 16621 } 16622 break; 16623 case 'w': 16624 var firstDay = 0; 16625 s = exports._getWeekOfYear(dateObject, firstDay); pad = true; 16626 break; 16627 case 'd': 16628 s = dateObject.getDate(); pad = true; 16629 break; 16630 case 'D': 16631 s = exports._getDayOfYear(dateObject); pad = true; 16632 break; 16633 case 'e': 16634 case 'c': 16635 var d = dateObject.getDay(); 16636 if(l<2){ 16637 s = (d - supplemental.getFirstDayOfWeek(options.locale) + 8) % 7 16638 break; 16639 } 16640 // fallthrough 16641 case 'E': 16642 d = dateObject.getDay(); 16643 if(l<3){ 16644 s = d+1; pad = true; 16645 }else{ 16646 var propD = [ 16647 "days", 16648 c == 'c' ? "standAlone" : "format", 16649 widthList[l-3] 16650 ].join("-"); 16651 s = bundle[propD][d]; 16652 } 16653 break; 16654 case 'a': 16655 var timePeriod = dateObject.getHours() < 12 ? 'am' : 'pm'; 16656 s = options[timePeriod] || bundle['dayPeriods-format-wide-' + timePeriod]; 16657 break; 16658 case 'h': 16659 case 'H': 16660 case 'K': 16661 case 'k': 16662 var h = dateObject.getHours(); 16663 // strange choices in the date format make it impossible to write this succinctly 16664 switch (c){ 16665 case 'h': // 1-12 16666 s = (h % 12) || 12; 16667 break; 16668 case 'H': // 0-23 16669 s = h; 16670 break; 16671 case 'K': // 0-11 16672 s = (h % 12); 16673 break; 16674 case 'k': // 1-24 16675 s = h || 24; 16676 break; 16677 } 16678 pad = true; 16679 break; 16680 case 'm': 16681 s = dateObject.getMinutes(); pad = true; 16682 break; 16683 case 's': 16684 s = dateObject.getSeconds(); pad = true; 16685 break; 16686 case 'S': 16687 s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); pad = true; 16688 break; 16689 case 'v': // FIXME: don't know what this is. seems to be same as z? 16690 case 'z': 16691 // We only have one timezone to offer; the one from the browser 16692 s = exports._getZone(dateObject, true, options); 16693 if(s){break;} 16694 l=4; 16695 // fallthrough... use GMT if tz not available 16696 case 'Z': 16697 var offset = exports._getZone(dateObject, false, options); 16698 var tz = [ 16699 (offset<=0 ? "+" : "-"), 16700 string.pad(Math.floor(Math.abs(offset)/60), 2), 16701 string.pad(Math.abs(offset)% 60, 2) 16702 ]; 16703 if(l==4){ 16704 tz.splice(0, 0, "GMT"); 16705 tz.splice(3, 0, ":"); 16706 } 16707 s = tz.join(""); 16708 break; 16709// case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A': 16710// console.log(match+" modifier unimplemented"); 16711 default: 16712 throw new Error("dojo.date.locale.format: invalid pattern char: "+pattern); 16713 } 16714 if(pad){ s = string.pad(s, l); } 16715 return s; 16716 }); 16717 } 16718 16719/*===== 16720var __FormatOptions = exports.__FormatOptions = declare(null, { 16721 // selector: String
16722 // choice of 'time','date' (default: date and time) 16723 // formatLength: String 16724 // choice of long, short, medium or full (plus any custom additions). Defaults to 'short' 16725 // datePattern:String 16726 // override pattern with this string 16727 // timePattern:String 16728 // override pattern with this string 16729 // am: String 16730 // override strings for am in times 16731 // pm: String 16732 // override strings for pm in times 16733 // locale: String 16734 // override the locale used to determine formatting rules 16735 // fullYear: Boolean 16736 // (format only) use 4 digit years whenever 2 digit years are called for 16737 // strict: Boolean 16738 // (parse only) strict parsing, off by default 16739}); 16740=====*/ 16741 16742exports._getZone = function(/*Date*/ dateObject, /*boolean*/ getName, /*__FormatOptions?*/ options){ 16743 // summary: 16744 // Returns the zone (or offset) for the given date and options. This 16745 // is broken out into a separate function so that it can be overridden 16746 // by timezone-aware code. 16747 // 16748 // dateObject: 16749 // the date and/or time being formatted. 16750 // 16751 // getName: 16752 // Whether to return the timezone string (if true), or the offset (if false) 16753 // 16754 // options: 16755 // The options being used for formatting 16756 if(getName){ 16757 return date.getTimezoneName(dateObject); 16758 }else{ 16759 return dateObject.getTimezoneOffset(); 16760 } 16761}; 16762 16763 16764exports.format = function(/*Date*/ dateObject, /*__FormatOptions?*/ options){ 16765 // summary: 16766 // Format a Date object as a String, using locale-specific settings. 16767 // 16768 // description: 16769 // Create a string from a Date object using a known localized pattern. 16770 // By default, this method formats both date and time from dateObject. 16771 // Formatting patterns are chosen appropriate to the locale. Different 16772 // formatting lengths may be chosen, with "full" used by default. 16773 // Custom patterns may be used or registered with translations using 16774 // the dojo/date/locale.addCustomFormats() method. 16775 // Formatting patterns are implemented using [the syntax described at 16776 // unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns) 16777 // 16778 // dateObject: 16779 // the date and/or time to be formatted. If a time only is formatted, 16780 // the values in the year, month, and day fields are irrelevant. The 16781 // opposite is true when formatting only dates. 16782 16783 options = options || {}; 16784 16785 var locale = i18n.normalizeLocale(options.locale), 16786 formatLength = options.formatLength || 'short', 16787 bundle = exports._getGregorianBundle(locale), 16788 str = [], 16789 sauce = lang.hitch(this, formatPattern, dateObject, bundle, options); 16790 if(options.selector == "year"){ 16791 return _processPattern(bundle["dateFormatItem-yyyy"] || "yyyy", sauce); 16792 } 16793 var pattern; 16794 if(options.selector != "date"){ 16795 pattern = options.timePattern || bundle["timeFormat-"+formatLength]; 16796 if(pattern){str.push(_processPattern(pattern, sauce));} 16797 } 16798 if(options.selector != "time"){ 16799 pattern = options.datePattern || bundle["dateFormat-"+formatLength]; 16800 if(pattern){str.push(_processPattern(pattern, sauce));} 16801 } 16802 16803 return str.length == 1 ? str[0] : bundle["dateTimeFormat-"+formatLength].replace(/\'/g,'').replace(/\{(\d+)\}/g, 16804 function(match, key){ return str[key]; }); // String 16805}; 16806 16807exports.regexp = function(/*__FormatOptions?*/ options){ 16808 // summary: 16809 // Builds the regular needed to parse a localized date 16810 16811 return exports._parseInfo(options).regexp; // String 16812}; 16813 16814exports._parseInfo = function(/*__FormatOptions?*/ options){ 16815 options = options || {}; 16816 var locale = i18n.normalizeLocale(options.locale), 16817 bundle = exports._getGregorianBundle(locale), 16818 formatLength = options.formatLength || 'short', 16819 datePattern = options.datePattern || bundle["dateFormat-" + formatLength], 16820 timePattern = options.timePattern || bundle["timeFormat-" + formatLength], 16821 pattern; 16822 if(options.selector == 'date'){ 16823 pattern = datePattern; 16824 }else if(options.selector == 'time'){ 16825 pattern = timePattern; 16826 }else{ 16827 pattern = bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g, 16828 function(match, key){ return [timePattern, datePattern][key]; }); 16829 } 16830 16831 var tokens = [], 16832 re = _processPattern(pattern, lang.hitch(this, _buildDateTimeRE, tokens, bundle, options)); 16833 return {regexp: re, tokens: tokens, bundle: bundle}; 16834};
16835 16836exports.parse = function(/*String*/ value, /*__FormatOptions?*/ options){ 16837 // summary: 16838 // Convert a properly formatted string to a primitive Date object, 16839 // using locale-specific settings. 16840 // 16841 // description: 16842 // Create a Date object from a string using a known localized pattern. 16843 // By default, this method parses looking for both date and time in the string. 16844 // Formatting patterns are chosen appropriate to the locale. Different 16845 // formatting lengths may be chosen, with "full" used by default. 16846 // Custom patterns may be used or registered with translations using 16847 // the dojo/date/locale.addCustomFormats() method. 16848 // 16849 // Formatting patterns are implemented using [the syntax described at 16850 // unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns) 16851 // When two digit years are used, a century is chosen according to a sliding 16852 // window of 80 years before and 20 years after present year, for both `yy` and `yyyy` patterns. 16853 // year < 100CE requires strict mode. 16854 // 16855 // value: 16856 // A string representation of a date 16857 16858 // remove non-printing bidi control chars from input and pattern 16859 var controlChars = /[\u200E\u200F\u202A\u202E]/g, 16860 info = exports._parseInfo(options), 16861 tokens = info.tokens, bundle = info.bundle, 16862 re = new RegExp("^" + info.regexp.replace(controlChars, "") + "$", 16863 info.strict ? "" : "i"), 16864 match = re.exec(value && value.replace(controlChars, "")); 16865 16866 if(!match){ return null; } // null 16867 16868 var widthList = ['abbr', 'wide', 'narrow'], 16869 result = [1970,0,1,0,0,0,0], // will get converted to a Date at the end 16870 amPm = "", 16871 valid = array.every(match, function(v, i){ 16872 if(!i){return true;} 16873 var token = tokens[i-1], 16874 l = token.length, 16875 c = token.charAt(0); 16876 switch(c){ 16877 case 'y': 16878 if(l != 2 && options.strict){ 16879 //interpret year literally, so '5' would be 5 A.D. 16880 result[0] = v; 16881 }else{ 16882 if(v<100){ 16883 v = Number(v); 16884 //choose century to apply, according to a sliding window 16885 //of 80 years before and 20 years after present year 16886 var year = '' + new Date().getFullYear(), 16887 century = year.substring(0, 2) * 100, 16888 cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99); 16889 result[0] = (v < cutoff) ? century + v : century - 100 + v; 16890 }else{ 16891 //we expected 2 digits and got more... 16892 if(options.strict){ 16893 return false; 16894 } 16895 //interpret literally, so '150' would be 150 A.D. 16896 //also tolerate '1950', if 'yyyy' input passed to 'yy' format 16897 result[0] = v; 16898 } 16899 } 16900 break; 16901 case 'M': 16902 case 'L': 16903 if(l>2){ 16904 var months = bundle['months-' + 16905 (c == 'L' ? 'standAlone' : 'format') + 16906 '-' + widthList[l-3]].concat(); 16907 if(!options.strict){ 16908 //Tolerate abbreviating period in month part 16909 //Case-insensitive comparison 16910 v = v.replace(".","").toLowerCase(); 16911 months = array.map(months, function(s){ return s.replace(".","").toLowerCase(); } ); 16912 } 16913 v = array.indexOf(months, v); 16914 if(v == -1){ 16915// console.log("dojo/date/locale.parse: Could not parse month name: '" + v + "'."); 16916 return false; 16917 } 16918 }else{ 16919 v--; 16920 } 16921 result[1] = v; 16922 break; 16923 case 'E': 16924 case 'e': 16925 case 'c': 16926 var days = bundle['days-' + 16927 (c == 'c' ? 'standAlone' : 'format') + 16928 '-' + widthList[l-3]].concat(); 16929 if(!options.strict){ 16930 //Case-insensitive comparison 16931 v = v.toLowerCase(); 16932 days = array.map(days, function(d){return d.toLowerCase();}); 16933 } 16934 v = array.indexOf(days, v); 16935 if(v == -1){ 16936// console.log("dojo/date/locale.parse: Could not parse weekday name: '" + v + "'."); 16937 return false; 16938 } 16939 16940 //TODO: not sure what to actually do with this input, 16941 //in terms of setting something on the Date obj...? 16942 //without more context, can't affect the actual date 16943 //TODO: just validate? 16944 break; 16945 case 'D': 16946 result[1] = 0; 16947 // fallthrough... 16948 case 'd': 16949 result[2] = v; 16950 break; 16951 case 'a': //am/pm 16952 var am = options.am || bundle['dayPeriods-format-wide-am'], 16953 pm = options.pm || bundle['dayPeriods-format-wide-pm']; 16954 if(!options.strict){ 16955 var period = /\./g; 16956 v = v.replace(period,'').toLowerCase(); 16957 am = am.replace(period,'').toLowerCase(); 16958 pm = pm.replace(period,'').toLowerCase(); 16959 } 16960 if(options.strict && v != am && v != pm){ 16961// console.log("dojo/date/locale.parse: Could not parse am/pm part."); 16962 return false; 16963 } 16964 16965 // we might not have seen the hours field yet, so store the state and apply hour change later 16966 amPm = (v == pm) ? 'p' : (v == am) ? 'a' : ''; 16967 break; 16968 case 'K': //hour (1-24) 16969 if(v == 24){ v = 0; } 16970 // fallthrough... 16971 case 'h': //hour (1-12) 16972 case 'H': //hour (0-23) 16973 case 'k': //hour (0-11) 16974 //TODO: strict bounds checking, padding 16975 if(v > 23){ 16976// console.log("dojo/date/locale.parse: Illegal hours value"); 16977 return false; 16978 } 16979 16980 //in the 12-hour case, adjusting for am/pm requires the 'a' part 16981 //which could come before or after the hour, so we will adju
16981st later 16982 result[3] = v; 16983 break; 16984 case 'm': //minutes 16985 result[4] = v; 16986 break; 16987 case 's': //seconds 16988 result[5] = v; 16989 break; 16990 case 'S': //milliseconds 16991 result[6] = v; 16992// break; 16993// case 'w': 16994//TODO var firstDay = 0; 16995// default: 16996//TODO: throw? 16997// console.log("dojo/date/locale.parse: unsupported pattern char=" + token.charAt(0)); 16998 } 16999 return true; 17000 }); 17001 17002 var hours = +result[3]; 17003 if(amPm === 'p' && hours < 12){ 17004 result[3] = hours + 12; //e.g., 3pm -> 15 17005 }else if(amPm === 'a' && hours == 12){ 17006 result[3] = 0; //12am -> 0 17007 } 17008 17009 //TODO: implement a getWeekday() method in order to test 17010 //validity of input strings containing 'EEE' or 'EEEE'... 17011 17012 var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date 17013 if(options.strict){ 17014 dateObject.setFullYear(result[0]); 17015 } 17016 17017 // Check for overflow. The Date() constructor normalizes things like April 32nd... 17018 //TODO: why isn't this done for times as well? 17019 var allTokens = tokens.join(""), 17020 dateToken = allTokens.indexOf('d') != -1, 17021 monthToken = allTokens.indexOf('M') != -1; 17022 17023 if(!valid || 17024 (monthToken && dateObject.getMonth() > result[1]) || 17025 (dateToken && dateObject.getDate() > result[2])){ 17026 return null; 17027 } 17028 17029 // Check for underflow, due to DST shifts. See #9366 17030 // This assumes a 1 hour dst shift correction at midnight 17031 // We could compare the timezone offset after the shift and add the difference instead. 17032 if((monthToken && dateObject.getMonth() < result[1]) || 17033 (dateToken && dateObject.getDate() < result[2])){ 17034 dateObject = date.add(dateObject, "hour", 1); 17035 } 17036 17037 return dateObject; // Date 17038}; 17039 17040function _processPattern(pattern, applyPattern, applyLiteral, applyAll){ 17041 //summary: Process a pattern with literals in it 17042 17043 // Break up on single quotes, treat every other one as a literal, except '' which becomes ' 17044 var identity = function(x){return x;}; 17045 applyPattern = applyPattern || identity; 17046 applyLiteral = applyLiteral || identity; 17047 applyAll = applyAll || identity; 17048 17049 //split on single quotes (which escape literals in date format strings) 17050 //but preserve escaped single quotes (e.g., o''clock) 17051 var chunks = pattern.match(/(''|[^'])+/g), 17052 literal = pattern.charAt(0) == "'"; 17053 17054 array.forEach(chunks, function(chunk, i){ 17055 if(!chunk){ 17056 chunks[i]=''; 17057 }else{ 17058 chunks[i]=(literal ? applyLiteral : applyPattern)(chunk.replace(/''/g, "'")); 17059 literal = !literal; 17060 } 17061 }); 17062 return applyAll(chunks.join('')); 17063} 17064 17065function _buildDateTimeRE(tokens, bundle, options, pattern){ 17066 pattern = regexp.escapeString(pattern); 17067 if(!options.strict){ pattern = pattern.replace(" a", " ?a"); } // kludge to tolerate no space before am/pm 17068 return pattern.replace(/([a-z])\1*/ig, function(match){ 17069 // Build a simple regexp. Avoid captures, which would ruin the tokens list 17070 var s, 17071 c = match.charAt(0), 17072 l = match.length, 17073 p2 = '', p3 = ''; 17074 if(options.strict){ 17075 if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; } 17076 if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; } 17077 }else{ 17078 p2 = '0?'; p3 = '0{0,2}'; 17079 } 17080 switch(c){ 17081 case 'y': 17082 s = '\\d{2,4}'; 17083 break; 17084 case 'M': 17085 case 'L': 17086 s = (l>2) ? '\\S+?' : '1[0-2]|'+p2+'[1-9]'; 17087 break; 17088 case 'D': 17089 s = '[12][0-9][0-9]|3[0-5][0-9]|36[0-6]|'+p2+'[1-9][0-9]|'+p3+'[1-9]'; 17090 break; 17091 case 'd': 17092 s = '3[01]|[12]\\d|'+p2+'[1-9]'; 17093 break; 17094 case 'w': 17095 s = '[1-4][0-9]|5[0-3]|'+p2+'[1-9]'; 17096 break; 17097 case 'E': 17098 case 'e': 17099 case 'c': 17100 s = '.+?'; // match anything including spaces until the first pattern delimiter is found such as a comma or space 17101 break; 17102 case 'h': //hour (1-12) 17103 s = '1[0-2]|'+p2+'[1-9]'; 17104 break; 17105 case 'k': //hour (0-11) 17106 s = '1[01]|'+p2+'\\d'; 17107 break; 17108 case 'H': //hour (0-23) 17109 s = '1\\d|2[0-3]|'+p2+'\\d'; 17110 break; 17111 case 'K': //hour (1-24) 17112 s = '1\\d|2[0-4]|'+p2+'[1-9]'; 17113 break; 17114 case 'm': 17115 case 's': 17116 s = '[0-5]\\d'; 17117 break; 17118 case 'S': 17119 s = '\\d{'+l+'}'; 17120 break; 17121 case 'a': 17122 var am = options.am || bundle['dayPeriods-format-wide-am'], 17123 pm = options.pm || bundle['dayPeriods-format-wide-pm']; 17124 s = am + '|' + pm; 17125 if(!options.strict){ 17126 if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); } 17127 if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); } 17128 if(s.indexOf('.') != -1){ s += '|' + s.replace(/\./g, ""); } 17129 } 17130 s = s.replace(/\./g, "\\."); 17131 break; 17132 default: 17133 // case 'v': 17134 // case 'z': 17135 // case 'Z': 17136 s = ".*"; 17137// console.log("parse of date format, pattern=" + pattern); 17138 } 17139 17140 if(tokens){ tokens.push(match); } 17141 17142 return "(" + s + ")"; // add capture 17143 }).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace. Need explicit handling of \xa0 for IE. 17144} 17145 17146var _customFormats = []; 17147exports.addCustomFormats = function(/*String*/ packageName, /*String*/ bundleName){ 17148 // summary: 17149 // Add a reference to a bundle containing localized custom formats to be 17150 // used by date/time formatting and parsing routines. 17151 // 17152 // description: 17153 // The user may add custom localized formats where the bundle has properties following the 17154 // same naming convention used by dojo.cldr: `dateFormat-xxxx` / `timeFormat-xxxx` 17155 // The pattern string should match the format used by the CLDR. 17156 // See dojo/date/locale.format() for details. 17157 // The resources must be loaded by dojo.requireLocalization() prior to use 17158 17159 _customFormats.push({pkg:packageName,name:bundleName}); 17160}; 17161 17162exports._getGregorianBundle = function(/*String*/ locale){ 17163 var gregorian = {}; 17164 array.forEach(_customFormats, function(desc){ 17165 var bundle = i18n.getLocalization(desc.pkg, desc.name, locale); 17166 gregorian = lang.mixin(gregorian, bundle); 17167 }, this); 17168 return gregorian; /*Object*/ 17169}; 17170 17171exports.addCustomFormats(module.id.replace(/\/date\/locale$/, ".cldr"),"gregorian"); 17172 17173exports.getNames = function(/*String*/ item, /*String*/ type, /*String?*/ context, /*String?*/ locale){ 17174 // summary: 17175 // Used to get localized strings from dojo.cldr for day or month names. 17176 // 17177 // item: 17178 // 'months' || 'days' 17179 // type: 17180 // 'wide' || 'abbr' || 'narrow' (e.g. "Monday", "Mon", or "M" respectively, in English) 17181 // context: 17182 // 'standAlone' || 'format' (default) 17183 // locale: 17184 // override locale used to find the names 17185 17186 var label, 17187 lookup = exports._getGregorianBundle(locale), 17188 props = [item, context, type]; 17189 if(context == 'standAlone'){ 17190 var key = props.join('-'); 17191 label = lookup[key]; 17192 // Fall back to 'format' flavor of name 17193 if(label[0] == 1){ label = undefined; } // kludge, in the absence of real aliasing support in dojo.cldr 17194 } 17195 props[1] = 'format'; 17196 17197 // return by copy so changes won't be made accidentally to the in-memory model 17198 return (label || lookup[props.join('-')]).concat(); /*Array*/ 17199}; 17200 17201exports.isWeekend = function(/*Date?*/ dateObject, /*String?*/ locale){ 17202 // summary: 17203 // Determines if the date falls on a weekend, according to local custom.
17204 17205 var weekend = supplemental.getWeekend(locale), 17206 day = (dateObject || new Date()).getDay(); 17207 if(weekend.end < weekend.start){ 17208 weekend.end += 7; 17209 if(day < weekend.start){ day += 7; } 17210 } 17211 return day >= weekend.start && day <= weekend.end; // Boolean 17212}; 17213 17214// These are used only by format and strftime. Do they need to be public? Which module should they go in? 17215 17216exports._getDayOfYear = function(/*Date*/ dateObject){ 17217 // summary: 17218 // gets the day of the year as represented by dateObject 17219 return date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject) + 1; // Number 17220}; 17221 17222exports._getWeekOfYear = function(/*Date*/ dateObject, /*Number*/ firstDayOfWeek){ 17223 if(arguments.length == 1){ firstDayOfWeek = 0; } // Sunday 17224 17225 var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1).getDay(), 17226 adj = (firstDayOfYear - firstDayOfWeek + 7) % 7, 17227 week = Math.floor((exports._getDayOfYear(dateObject) + adj - 1) / 7); 17228 17229 // if year starts on the specified day, start counting weeks at 1 17230 if(firstDayOfYear == firstDayOfWeek){ week++; } 17231 17232 return week; // Number 17233}; 17234 17235return exports; 17236}); 17237 17238}, 17239'dojo/date':function(){ 17240define(["./has", "./_base/lang"], function(has, lang){ 17241// module: 17242// dojo/date 17243 17244var date = { 17245 // summary: 17246 // Date manipulation utilities 17247}; 17248 17249date.getDaysInMonth = function(/*Date*/dateObject){ 17250 // summary: 17251 // Returns the number of days in the month used by dateObject 17252 var month = dateObject.getMonth(); 17253 var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 17254 if(month == 1 && date.isLeapYear(dateObject)){ return 29; } // Number 17255 return days[month]; // Number 17256}; 17257 17258date.isLeapYear = function(/*Date*/dateObject){ 17259 // summary: 17260 // Determines if the year of the dateObject is a leap year 17261 // description: 17262 // Leap years are years with an additional day YYYY-02-29, where the 17263 // year number is a multiple of four with the following exception: If 17264 // a year is a multiple of 100, then it is only a leap year if it is 17265 // also a multiple of 400. For example, 1900 was not a leap year, but 17266 // 2000 is one. 17267 17268 var year = dateObject.getFullYear(); 17269 return !(year%400) || (!(year%4) && !!(year%100)); // Boolean 17270}; 17271 17272// FIXME: This is not localized 17273date.getTimezoneName = function(/*Date*/dateObject){ 17274 // summary: 17275 // Get the user's time zone as provided by the browser 17276 // dateObject: 17277 // Needed because the timezone may vary with time (daylight savings) 17278 // description: 17279 // Try to get time zone info from toString or toLocaleString method of 17280 // the Date object -- UTC offset is not a time zone. See 17281 // http://www.twinsun.com/tz/tz-link.htm Note: results may be 17282 // inconsistent across browsers. 17283 17284 var str = dateObject.toString(); // Start looking in toString 17285 var tz = ''; // The result -- return empty string if nothing found 17286 var match; 17287 17288 // First look for something in parentheses -- fast lookup, no regex 17289 var pos = str.indexOf('('); 17290 if(pos > -1){ 17291 tz = str.substring(++pos, str.indexOf(')')); 17292 }else{ 17293 // If at first you don't succeed ... 17294 // If IE knows about the TZ, it appears before the year 17295 // Capital letters or slash before a 4-digit year 17296 // at the end of string 17297 var pat = /([A-Z\/]+) \d{4}$/; 17298 if((match = str.match(pat))){ 17299 tz = match[1]; 17300 }else{ 17301 // Some browsers (e.g. Safari) glue the TZ on the end 17302 // of toLocaleString instead of putting it in toString 17303 str = dateObject.toLocaleString(); 17304 // Capital letters or slash -- end of string, 17305 // after space 17306 pat = / ([A-Z\/]+)$/; 17307 if((match = str.match(pat))){ 17308 tz = match[1]; 17309 } 17310 } 17311 } 17312 17313 // Make sure it doesn't somehow end up return AM or PM 17314 return (tz == 'AM' || tz == 'PM') ? '' : tz; // String 17315}; 17316 17317// Utility methods to do arithmetic calculations with Dates 17318 17319date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){ 17320 // summary: 17321 // Compare two date objects by date, time, or both. 17322 // description: 17323 // Returns 0 if equal, positive if a > b, else negative. 17324 // date1: 17325 // Date object 17326 // date2: 17327 // Date object. If not specified, the current Date is used. 17328 // portion:
vendor: 4,146 bytes, lines 17329-17466
17329 // A string indicating the "date" or "time" portion of a Date object. 17330 // Compares both "date" and "time" by default. One of the following: 17331 // "date", "time", "datetime" 17332 17333 // Extra step required in copy for IE - see #3112 17334 date1 = new Date(+date1); 17335 date2 = new Date(+(date2 || new Date())); 17336 17337 if(portion == "date"){ 17338 // Ignore times and compare dates. 17339 date1.setHours(0, 0, 0, 0); 17340 date2.setHours(0, 0, 0, 0); 17341 }else if(portion == "time"){ 17342 // Ignore dates and compare times. 17343 date1.setFullYear(0, 0, 0); 17344 date2.setFullYear(0, 0, 0); 17345 } 17346 17347 if(date1 > date2){ return 1; } // int 17348 if(date1 < date2){ return -1; } // int 17349 return 0; // int 17350}; 17351 17352date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){ 17353 // summary: 17354 // Add to a Date in intervals of different size, from milliseconds to years 17355 // date: Date 17356 // Date object to start with 17357 // interval: 17358 // A string representing the interval. One of the following: 17359 // "year", "month", "day", "hour", "minute", "second", 17360 // "millisecond", "quarter", "week", "weekday" 17361 // amount: 17362 // How much to add to the date. 17363 17364 var sum = new Date(+date); // convert to Number before copying to accommodate IE (#3112) 17365 var fixOvershoot = false; 17366 var property = "Date"; 17367 17368 switch(interval){ 17369 case "day": 17370 break; 17371 case "weekday": 17372 //i18n FIXME: assumes Saturday/Sunday weekend, but this is not always true. see dojo/cldr/supplemental 17373 17374 // Divide the increment time span into weekspans plus leftover days 17375 // e.g., 8 days is one 5-day weekspan / and two leftover days 17376 // Can't have zero leftover days, so numbers divisible by 5 get 17377 // a days value of 5, and the remaining days make up the number of weeks 17378 var days, weeks; 17379 var mod = amount % 5; 17380 if(!mod){ 17381 days = (amount > 0) ? 5 : -5; 17382 weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5); 17383 }else{ 17384 days = mod; 17385 weeks = parseInt(amount/5); 17386 } 17387 // Get weekday value for orig date param 17388 var strt = date.getDay(); 17389 // Orig date is Sat / positive incrementer 17390 // Jump over Sun 17391 var adj = 0; 17392 if(strt == 6 && amount > 0){ 17393 adj = 1; 17394 }else if(strt == 0 && amount < 0){ 17395 // Orig date is Sun / negative incrementer 17396 // Jump back over Sat 17397 adj = -1; 17398 } 17399 // Get weekday val for the new date 17400 var trgt = strt + days; 17401 // New date is on Sat or Sun 17402 if(trgt == 0 || trgt == 6){ 17403 adj = (amount > 0) ? 2 : -2; 17404 } 17405 // Increment by number of weeks plus leftover days plus 17406 // weekend adjustments 17407 amount = (7 * weeks) + days + adj; 17408 break; 17409 case "year": 17410 property = "FullYear"; 17411 // Keep increment/decrement from 2/29 out of March 17412 fixOvershoot = true; 17413 break; 17414 case "week": 17415 amount *= 7; 17416 break; 17417 case "quarter": 17418 // Naive quarter is just three months 17419 amount *= 3; 17420 // fallthrough... 17421 case "month": 17422 // Reset to last day of month if you overshoot 17423 fixOvershoot = true; 17424 property = "Month"; 17425 break; 17426// case "hour": 17427// case "minute": 17428// case "second": 17429// case "millisecond": 17430 default: 17431 property = "UTC"+interval.charAt(0).toUpperCase() + interval.substring(1) + "s"; 17432 } 17433 17434 if(property){ 17435 sum["set"+property](sum["get"+property]()+amount); 17436 } 17437 17438 if(fixOvershoot && (sum.getDate() < date.getDate())){ 17439 sum.setDate(0); 17440 } 17441 17442 return sum; // Date 17443}; 17444 17445date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){ 17446 // summary: 17447 // Get the difference in a specific unit of time (e.g., number of 17448 // months, weeks, days, etc.) between two dates, rounded to the 17449 // nearest integer. 17450 // date1: 17451 // Date object 17452 // date2: 17453 // Date object. If not specified, the current Date is used. 17454 // interval: 17455 // A string representing the interval. One of the following: 17456 // "year", "month", "day", "hour", "minute", "second", 17457 // "millisecond", "quarter", "week", "weekday" 17458 // 17459 // Defaults to "day". 17460 17461 date2 = date2 || new Date(); 17462 interval = interval || "day"; 17463 var yearDiff = date2.getFullYear() - date1.getFullYear(); 17464 var delta = 1; // Integer return value 17465 17466 switch(interval){
17467 case "quarter": 17468 var m1 = date1.getMonth(); 17469 var m2 = date2.getMonth(); 17470 // Figure out which quarter the months are in 17471 var q1 = Math.floor(m1/3) + 1; 17472 var q2 = Math.floor(m2/3) + 1; 17473 // Add quarters for any year difference between the dates 17474 q2 += (yearDiff * 4); 17475 delta = q2 - q1; 17476 break; 17477 case "weekday": 17478 var days = Math.round(date.difference(date1, date2, "day")); 17479 var weeks = parseInt(date.difference(date1, date2, "week")); 17480 var mod = days % 7; 17481 17482 // Even number of weeks 17483 if(mod == 0){ 17484 days = weeks*5; 17485 }else{ 17486 // Weeks plus spare change (< 7 days) 17487 var adj = 0; 17488 var aDay = date1.getDay(); 17489 var bDay = date2.getDay(); 17490 17491 weeks = parseInt(days/7); 17492 mod = days % 7; 17493 // Mark the date advanced by the number of 17494 // round weeks (may be zero) 17495 var dtMark = new Date(date1); 17496 dtMark.setDate(dtMark.getDate()+(weeks*7)); 17497 var dayMark = dtMark.getDay(); 17498 17499 // Spare change days -- 6 or less 17500 if(days > 0){ 17501 switch(true){ 17502 // Range starts on Sat 17503 case aDay == 6: 17504 adj = -1; 17505 break; 17506 // Range starts on Sun 17507 case aDay == 0: 17508 adj = 0; 17509 break; 17510 // Range ends on Sat 17511 case bDay == 6: 17512 adj = -1; 17513 break; 17514 // Range ends on Sun 17515 case bDay == 0: 17516 adj = -2; 17517 break; 17518 // Range contains weekend 17519 case (dayMark + mod) > 5: 17520 adj = -2; 17521 } 17522 }else if(days < 0){ 17523 switch(true){ 17524 // Range starts on Sat 17525 case aDay == 6: 17526 adj = 0; 17527 break; 17528 // Range starts on Sun 17529 case aDay == 0: 17530 adj = 1; 17531 break; 17532 // Range ends on Sat 17533 case bDay == 6: 17534 adj = 2; 17535 break; 17536 // Range ends on Sun 17537 case bDay == 0: 17538 adj = 1; 17539 break; 17540 // Range contains weekend 17541 case (dayMark + mod) < 0: 17542 adj = 2; 17543 } 17544 } 17545 days += adj; 17546 days -= (weeks*2); 17547 } 17548 delta = days; 17549 break; 17550 case "year": 17551 delta = yearDiff; 17552 break; 17553 case "month": 17554 delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12); 17555 break; 17556 case "week": 17557 // Truncate instead of rounding 17558 // Don't use Math.floor -- value may be negative 17559 delta = parseInt(date.difference(date1, date2, "day")/7); 17560 break; 17561 case "day": 17562 delta /= 24; 17563 // fallthrough 17564 case "hour": 17565 delta /= 60; 17566 // fallthrough 17567 case "minute": 17568 delta /= 60; 17569 // fallthrough 17570 case "second": 17571 delta /= 1000; 17572 // fallthrough 17573 case "millisecond": 17574 delta *= date2.getTime() - date1.getTime(); 17575 } 17576 17577 // Round for fractional values and DST leaps 17578 return Math.round(delta); // Number (integer) 17579}; 17580 17581// Don't use setObject() because it may overwrite dojo/date/stamp (if that has already been loaded) 17582 1 && lang.mixin(lang.getObject("dojo.date", true), date); 17583 17584return date; 17585}); 17586 17587}, 17588'dojo/cldr/supplemental':function(){ 17589define(["../_base/lang", "../i18n"], function(lang, i18n){ 17590 17591// module: 17592// dojo/cldr/supplemental 17593 17594 17595var supplemental = { 17596 // summary: 17597 // TODOC 17598}; 17599lang.setObject("dojo.cldr.supplemental", supplemental); 17600 17601supplemental.getFirstDayOfWeek = function(/*String?*/locale){ 17602 // summary: 17603 // Returns a zero-based index for first day of the week 17604 // description: 17605 // Returns a zero-based index for first day of the week, as used by the local (Gregorian) calendar. 17606 // e.g. Sunday (returns 0), or Monday (returns 1) 17607 17608 // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/firstDay 17609 var firstDay = {/*default is 1=Monday*/ 17610 bd:5,mv:5, 17611 ae:6,af:6,bh:6,dj:6,dz:6,eg:6,iq:6,ir:6,jo:6,kw:6, 17612 ly:6,ma:6,om:6,qa:6,sa:6,sd:6,sy:6,ye:6, 17613 ag:0,ar:0,as:0,au:0,br:0,bs:0,bt:0,bw:0,by:0,bz:0,ca:0,cn:0, 17614 co:0,dm:0,'do':0,et:0,gt:0,gu:0,hk:0,hn:0,id:0,ie:0,il:0,'in':0, 17615 jm:0,jp:0,ke:0,kh:0,kr:0,la:0,mh:0,mm:0,mo:0,mt:0,mx:0,mz:0, 17616 ni:0,np:0,nz:0,pa:0,pe:0,ph:0,pk:0,pr:0,py:0,sg:0,sv:0,th:0, 17617 tn:0,tt:0,tw:0,um:0,us:0,ve:0,vi:0,ws:0,za:0,zw:0 17618 }; 17619 17620 var country = supplemental._region(locale); 17621 var dow = firstDay[country]; 17622 return (dow === undefined) ? 1 : dow; /*Number*/ 17623}; 17624 17625supplemental._region = function(/*String?*/locale){ 17626 locale = i18n.normalizeLocale(locale); 17627 var tags = locale.split('-'); 17628 var region = tags[1]; 17629 if(!region){ 17630 // IE often gives language only (#2269) 17631 // Arbitrary mappings of language-only locales to a country: 17632 region = { 17633 aa:"et", ab:"ge", af:"za", ak:"gh", am:"et", ar:"eg", as:"in", av:"ru", ay:"bo", az:"az", ba:"ru", 17634 be:"by", bg:"bg", bi:"vu", bm:"ml", bn:"bd", bo:"cn", br:"fr", bs:"ba", ca:"es", ce:"ru", ch:"gu", 17635 co:"fr", cr:"ca", cs:"cz", cv:"ru", cy:"gb", da:"dk", de:"de", dv:"mv", dz:"bt", ee:"gh", el:"gr", 17636 en:"us", es:"es", et:"ee", eu:"es", fa:"ir", ff:"sn", fi:"fi", fj:"fj", fo:"fo", fr:"fr", fy:"nl", 17637 ga:"ie", gd:"gb", gl:"es", gn:"py", gu:"in", gv:"gb", ha:"ng", he:"il", hi:"in", ho:"pg", hr:"hr", 17638 ht:"ht", hu:"hu", hy:"am", ia:"fr", id:"id", ig:"ng", ii:"cn", ik:"us", "in":"id", is:"is", it:"it", 17639 iu:"ca", iw:"il", ja:"jp", ji:"ua", jv:"id", jw:"id", ka:"ge", kg:"cd", ki:"ke", kj:"na", kk:"kz", 17640 kl:"gl", km:"kh", kn:"in", ko:"kr", ks:"in", ku:"tr", kv:"ru", kw:"gb", ky:"kg", la:"va", lb:"lu", 17641 lg:"ug", li:"nl", ln:"cd", lo:"la", lt:"lt", lu:"cd", lv:"lv", mg:"mg", mh:"mh", mi:"nz", mk:"mk", 17642 ml:"in", mn:"mn", mo:"ro", mr:"in", ms:"my", mt:"mt", my:"mm", na:"nr", nb:"no", nd:"zw", ne:"np", 17643 ng:"na", nl:"nl", nn:"no", no:"no", nr:"za", nv:"us", ny:"mw", oc:"fr", om:"et", or:"in", os:"ge", 17644 pa:"in", pl:"pl", ps:"af", pt:"br", qu:"pe", rm:"ch", rn:"bi", ro:"ro", ru:"ru", rw:"rw", sa:"in", 17645 sd:"in", se:"no", sg:"cf", si:"lk", sk:"sk", sl:"si", sm:"ws", sn:"zw", so:"so", sq:"al", sr:"rs", 17646 ss:"za", st:"za", su:"id", sv:"se", sw:"tz", ta:"in", te:"in", tg:"tj", th:"th", ti:"et", tk:"tm", 17647 tl:"ph", tn:"za", to:"to", tr:"tr", ts:"za", tt:"ru", ty:"pf", ug:"cn", uk:"ua", ur:"pk", uz:"uz", 17648 ve:"za", vi:"vn", wa:"be", wo:"sn", xh:"za", yi:"il", yo:"ng", za:"cn", zh:"cn", zu:"za", 17649 ace:"id", ady:"ru", agq:"cm", alt:"ru", amo:"ng", asa:"tz", ast:"es", awa:"in", bal:"pk", 17650 ban:"id", bas:"cm", bax:"cm", bbc:"id", bem:"zm", bez:"tz", bfq:"in", bft:"pk", bfy:"in", 17651 bhb:"in", bho:"in", bik:"ph", bin:"ng", bjj:"in", bku:"ph", bqv:"ci", bra:"in", brx:"in", 17652 bss:"cm", btv:"pk", bua:"ru", buc:"yt", bug:"id", bya:"id", byn:"er", cch:"ng", ccp:"in", 17653 ceb:"ph", cgg:"ug", chk:"fm", chm:"ru", chp:"ca", chr:"us", cja:"kh", cjm:"vn", ckb:"iq",
17654 crk:"ca", csb:"pl", dar:"ru", dav:"ke", den:"ca", dgr:"ca", dje:"ne", doi:"in", dsb:"de", 17655 dua:"cm", dyo:"sn", dyu:"bf", ebu:"ke", efi:"ng", ewo:"cm", fan:"gq", fil:"ph", fon:"bj", 17656 fur:"it", gaa:"gh", gag:"md", gbm:"in", gcr:"gf", gez:"et", gil:"ki", gon:"in", gor:"id", 17657 grt:"in", gsw:"ch", guz:"ke", gwi:"ca", haw:"us", hil:"ph", hne:"in", hnn:"ph", hoc:"in", 17658 hoj:"in", ibb:"ng", ilo:"ph", inh:"ru", jgo:"cm", jmc:"tz", kaa:"uz", kab:"dz", kaj:"ng", 17659 kam:"ke", kbd:"ru", kcg:"ng", kde:"tz", kdt:"th", kea:"cv", ken:"cm", kfo:"ci", kfr:"in", 17660 kha:"in", khb:"cn", khq:"ml", kht:"in", kkj:"cm", kln:"ke", kmb:"ao", koi:"ru", kok:"in", 17661 kos:"fm", kpe:"lr", krc:"ru", kri:"sl", krl:"ru", kru:"in", ksb:"tz", ksf:"cm", ksh:"de", 17662 kum:"ru", lag:"tz", lah:"pk", lbe:"ru", lcp:"cn", lep:"in", lez:"ru", lif:"np", lis:"cn", 17663 lki:"ir", lmn:"in", lol:"cd", lua:"cd", luo:"ke", luy:"ke", lwl:"th", mad:"id", mag:"in", 17664 mai:"in", mak:"id", man:"gn", mas:"ke", mdf:"ru", mdh:"ph", mdr:"id", men:"sl", mer:"ke", 17665 mfe:"mu", mgh:"mz", mgo:"cm", min:"id", mni:"in", mnk:"gm", mnw:"mm", mos:"bf", mua:"cm", 17666 mwr:"in", myv:"ru", nap:"it", naq:"na", nds:"de", "new":"np", niu:"nu", nmg:"cm", nnh:"cm", 17667 nod:"th", nso:"za", nus:"sd", nym:"tz", nyn:"ug", pag:"ph", pam:"ph", pap:"bq", pau:"pw", 17668 pon:"fm", prd:"ir", raj:"in", rcf:"re", rej:"id", rjs:"np", rkt:"in", rof:"tz", rwk:"tz", 17669 saf:"gh", sah:"ru", saq:"ke", sas:"id", sat:"in", saz:"in", sbp:"tz", scn:"it", sco:"gb", 17670 sdh:"ir", seh:"mz", ses:"ml", shi:"ma", shn:"mm", sid:"et", sma:"se", smj:"se", smn:"fi", 17671 sms:"fi", snk:"ml", srn:"sr", srr:"sn", ssy:"er", suk:"tz", sus:"gn", swb:"yt", swc:"cd", 17672 syl:"bd", syr:"sy", tbw:"ph", tcy:"in", tdd:"cn", tem:"sl", teo:"ug", tet:"tl", tig:"er", 17673 tiv:"ng", tkl:"tk", tmh:"ne", tpi:"pg", trv:"tw", tsg:"ph", tts:"th", tum:"mw", tvl:"tv", 17674 twq:"ne", tyv:"ru", tzm:"ma", udm:"ru", uli:"fm", umb:"ao", unr:"in", unx:"in", vai:"lr", 17675 vun:"tz", wae:"ch", wal:"et", war:"ph", xog:"ug", xsr:"np", yao:"mz", yap:"fm", yav:"cm", zza:"tr" 17676 }[tags[0]]; 17677 }else if(region.length == 4){ 17678 // The ISO 3166 country code is usually in the second position, unless a 17679 // 4-letter script is given. See http://www.ietf.org/rfc/rfc4646.txt 17680 region = tags[2]; 17681 } 17682 return region; 17683}; 17684 17685supplemental.getWeekend = function(/*String?*/locale){ 17686 // summary: 17687 // Returns a hash containing the start and end days of the weekend 17688 // description: 17689 // Returns a hash containing the start and end days of the weekend according to local custom using locale, 17690 // or by default in the user's locale. 17691 // e.g. {start:6, end:0} 17692 17693 // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/weekend{Start,End} 17694 var weekendStart = {/*default is 6=Saturday*/ 17695 'in':0, 17696 af:4,dz:4,ir:4,om:4,sa:4,ye:4, 17697 ae:5,bh:5,eg:5,il:5,iq:5,jo:5,kw:5,ly:5,ma:5,qa:5,sd:5,sy:5,tn:5 17698 }, 17699 17700 weekendEnd = {/*default is 0=Sunday*/ 17701 af:5,dz:5,ir:5,om:5,sa:5,ye:5, 17702 ae:6,bh:5,eg:6,il:6,iq:6,jo:6,kw:6,ly:6,ma:6,qa:6,sd:6,sy:6,tn:6 17703 }, 17704 17705 country = supplemental._region(locale), 17706 start = weekendStart[country], 17707 end = weekendEnd[country]; 17708 17709 if(start === undefined){start=6;} 17710 if(end === undefined){end=0;} 17711 return {start:start, end:end}; /*Object {start,end}*/ 17712}; 17713 17714return supplemental; 17715}); 17716 17717}, 17718'dojo/i18n':function(){ 17719define(["./_base/kernel", "require", "./has", "./_base/array", "./_base/config", "./_base/lang", "./_base/xhr", "./json", "module"], 17720 function(dojo, require, has, array, config, lang, xhr, json, module){ 17721 17722 // module: 17723 // dojo/i18n 17724 17725 has.add("dojo-preload-i18n-Api", 17726 // if true, define the preload localizations machinery 17727 1 17728 ); 17729 17730 1 || has.add("dojo-v1x-i18n-Api", 17731 // if true, define the v1.x i18n functions 17732 1 17733 ); 17734 17735 var 17736 thisModule = dojo.i18n = 17737 { 17738 // summary: 17739 // This module implements the dojo/i18n! plugin and the v1.6- i18n API 17740 // description: 17741 // We choose to include our own plugin to leverage functionality already contained in dojo 17742 // and thereby reduce the size of the plugin compared to various loader implementations. Also, this 17743 // allows foreign AMD loaders to be used without their plugins. 17744 }, 17745 17746 nlsRe = 17747 // regexp for reconstructing the master bundle name from parts of the regexp match 17748 // nlsRe.exec("foo/bar/baz/nls/en-ca/foo") gives: 17749 // ["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"] 17750 // nlsRe.exec("foo/bar/baz/nls/foo") gives: 17751 // ["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""] 17752 // so, if match[5] is blank, it means this is the top bundle definition. 17753 // courtesy of http://requirejs.org 17754 /(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/, 17755 17756 getAvailableLocales = function( 17757 root, 17758 locale, 17759 bundlePath, 17760 bundleName 17761 ){ 17762 // summary: 17763 // return a vector of module ids containing all available locales with respect to the target locale 17764 // For example, assuming: 17765 // 17766 // - the root bundle indicates specific bundles for "fr" and "fr-ca", 17767 // - bundlePath is "myPackage/nls" 17768 // - bundleName is "myBundle" 17769 // 17770 // Then a locale argument of "fr-ca" would return 17771 // 17772 // ["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"] 17773 // 17774 // Notice that bundles are returned least-specific to most-specific, starting with the root. 17775 // 17776 // If root===false indicates we're working with a pre-AMD i18n bundle that doesn't tell about the available locales; 17777 // therefore, assume everything is available and get 404 errors that indicate a particular localization is not available 17778 17779 for(var result = [bundlePath + bundleName], localeParts = locale.split("-"), current = "", i = 0; i<localeParts.length; i++){ 17780 current += (current ? "-" : "") + localeParts[i];
vendor: 4,976 bytes, lines 17781-17892
17781 if(!root || root[current]){ 17782 result.push(bundlePath + current + "/" + bundleName); 17783 result.specificity = current; 17784 } 17785 } 17786 return result; 17787 }, 17788 17789 cache = {}, 17790 17791 getBundleName = function(moduleName, bundleName, locale){ 17792 locale = locale ? locale.toLowerCase() : dojo.locale; 17793 moduleName = moduleName.replace(/\./g, "/"); 17794 bundleName = bundleName.replace(/\./g, "/"); 17795 return (/root/i.test(locale)) ? 17796 (moduleName + "/nls/" + bundleName) : 17797 (moduleName + "/nls/" + locale + "/" + bundleName); 17798 }, 17799 17800 getL10nName = dojo.getL10nName = function(moduleName, bundleName, locale){ 17801 return moduleName = module.id + "!" + getBundleName(moduleName, bundleName, locale); 17802 }, 17803 17804 doLoad = function(require, bundlePathAndName, bundlePath, bundleName, locale, load){ 17805 // summary: 17806 // get the root bundle which instructs which other bundles are required to construct the localized bundle 17807 require([bundlePathAndName], function(root){ 17808 var current = lang.clone(root.root || root.ROOT),// 1.6 built bundle defined ROOT 17809 availableLocales = getAvailableLocales(!root._v1x && root, locale, bundlePath, bundleName); 17810 require(availableLocales, function(){ 17811 for (var i = 1; i<availableLocales.length; i++){ 17812 current = lang.mixin(lang.clone(current), arguments[i]); 17813 } 17814 // target may not have been resolve (e.g., maybe only "fr" exists when "fr-ca" was requested) 17815 var target = bundlePathAndName + "/" + locale; 17816 cache[target] = current; 17817 current.$locale = availableLocales.specificity; 17818 load(); 17819 }); 17820 }); 17821 }, 17822 17823 normalize = function(id, toAbsMid){ 17824 // summary: 17825 // id may be relative. 17826 // preload has form `*preload*<path>/nls/<module>*<flattened locales>` and 17827 // therefore never looks like a relative 17828 return /^\./.test(id) ? toAbsMid(id) : id; 17829 }, 17830 17831 getLocalesToLoad = function(targetLocale){ 17832 var list = config.extraLocale || []; 17833 list = lang.isArray(list) ? list : [list]; 17834 list.push(targetLocale); 17835 return list; 17836 }, 17837 17838 load = function(id, require, load){ 17839 // summary: 17840 // id is in one of the following formats 17841 // 17842 // 1. <path>/nls/<bundle> 17843 // => load the bundle, localized to config.locale; load all bundles localized to 17844 // config.extraLocale (if any); return the loaded bundle localized to config.locale. 17845 // 17846 // 2. <path>/nls/<locale>/<bundle> 17847 // => load then return the bundle localized to <locale> 17848 // 17849 // 3. *preload*<path>/nls/<module>*<JSON array of available locales> 17850 // => for config.locale and all config.extraLocale, load all bundles found 17851 // in the best-matching bundle rollup. A value of 1 is returned, which 17852 // is meaningless other than to say the plugin is executing the requested 17853 // preloads 17854 // 17855 // In cases 1 and 2, <path> is always normalized to an absolute module id upon entry; see 17856 // normalize. In case 3, it <path> is assumed to be absolute; this is arranged by the builder. 17857 // 17858 // To load a bundle means to insert the bundle into the plugin's cache and publish the bundle 17859 // value to the loader. Given <path>, <bundle>, and a particular <locale>, the cache key 17860 // 17861 // <path>/nls/<bundle>/<locale> 17862 // 17863 // will hold the value. Similarly, then plugin will publish this value to the loader by 17864 // 17865 // define("<path>/nls/<bundle>/<locale>", <bundle-value>); 17866 // 17867 // Given this algorithm, other machinery can provide fast load paths be preplacing 17868 // values in the plugin's cache, which is public. When a load is demanded the 17869 // cache is inspected before starting any loading. Explicitly placing values in the plugin 17870 // cache is an advanced/experimental feature that should not be needed; use at your own risk. 17871 // 17872 // For the normal AMD algorithm, the root bundle is loaded first, which instructs the 17873 // plugin what additional localized bundles are required for a particular locale. These 17874 // additional locales are loaded and a mix of the root and each progressively-specific 17875 // locale is returned. For example: 17876 // 17877 // 1. The client demands "dojo/i18n!some/path/nls/someBundle 17878 // 17879 // 2. The loader demands load(some/path/nls/someBundle) 17880 // 17881 // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle. 17882 // 17883 // 4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations 17884 // are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin 17885 // requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle" 17886 // 17887 // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle 17888 // ab-cd-ef as... 17889 // 17890 // mixin(mixin(mixin({}, require("some/path/nls/someBundle"), 17891 // require("some/path/nls/ab/someBundle")), 17892 // require("some/path/nls/ab-cd-ef/someBundle"));
17893 // 17894 // This value is inserted into the cache and published to the loader at the 17895 // key/module-id some/path/nls/someBundle/ab-cd-ef. 17896 // 17897 // The special preload signature (case 3) instructs the plugin to stop servicing all normal requests 17898 // (further preload requests will be serviced) until all ongoing preloading has completed. 17899 // 17900 // The preload signature instructs the plugin that a special rollup module is available that contains 17901 // one or more flattened, localized bundles. The JSON array of available locales indicates which locales 17902 // are available. Here is an example: 17903 // 17904 // *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"] 17905 // 17906 // This indicates the following rollup modules are available: 17907 // 17908 // some/path/nls/someModule_ROOT 17909 // some/path/nls/someModule_ab 17910 // some/path/nls/someModule_ab-cd-ef 17911 // 17912 // Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash. 17913 // For example, assume someModule contained the bundles some/bundle/path/someBundle and 17914 // some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as follows: 17915 // 17916 // define({ 17917 // some/bundle/path/someBundle:<value of someBundle, flattened with respect to locale ab>, 17918 // some/bundle/path/someOtherBundle:<value of someOtherBundle, flattened with respect to locale ab>, 17919 // }); 17920 // 17921 // E.g., given this design, preloading for locale=="ab" can execute the following algorithm: 17922 // 17923 // require(["some/path/nls/someModule_ab"], function(rollup){ 17924 // for(var p in rollup){ 17925 // var id = p + "/ab", 17926 // cache[id] = rollup[p]; 17927 // define(id, rollup[p]); 17928 // } 17929 // }); 17930 // 17931 // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and 17932 // load accordingly. 17933 // 17934 // The builder will write such rollups for every layer if a non-empty localeList profile property is 17935 // provided. Further, the builder will include the following cache entry in the cache associated with 17936 // any layer. 17937 // 17938 // "*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);} 17939 // 17940 // The *now special cache module instructs the loader to apply the provided function to context-require 17941 // with respect to the particular layer being defined. This causes the plugin to hold all normal service 17942 // requests until all preloading is complete. 17943 // 17944 // Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case 17945 // where the target locale has a single segment and a layer depends on a single bundle: 17946 // 17947 // Without Preloads: 17948 // 17949 // 1. Layer loads root bundle. 17950 // 2. bundle is demanded; plugin loads single localized bundle. 17951 // 17952 // With Preloads: 17953 // 17954 // 1. Layer causes preloading of target bundle. 17955 // 2. bundle is demanded; service is delayed until preloading complete; bundle is returned. 17956 // 17957 // In each case a single transaction is required to load the target bundle. In cases where multiple bundles 17958 // are required and/or the locale has multiple segments, preloads still requires a single transaction whereas 17959 // the normal path requires an additional transaction for each additional bundle/locale-segment. However all 17960 // of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading 17961 // algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false. 17962 17963 if(has("dojo-preload-i18n-Api")){ 17964 var split = id.split("*"), 17965 preloadDemand = split[1] == "preload"; 17966 if(preloadDemand){ 17967 if(!cache[id]){ 17968 // use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but 17969 // who knows what over-aggressive human optimizers may attempt 17970 cache[id] = 1; 17971 preloadL10n(split[2], json.parse(split[3]), 1, require); 17972 } 17973 // don't stall the loader! 17974 load(1); 17975 } 17976 if(preloadDemand || waitForPreloads(id, require, load)){ 17977 return; 17978 } 17979 } 17980 17981 var match = nlsRe.exec(id), 17982 bundlePath = match[1] + "/", 17983 bundleName = match[5] || match[4], 17984 bundlePathAndName = bundlePath + bundleName, 17985 localeSpecified = (match[5] && match[4]),
vendor: 7,290 bytes, lines 17986-18161
17986 targetLocale = localeSpecified || dojo.locale || "", 17987 loadTarget = bundlePathAndName + "/" + targetLocale, 17988 loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale), 17989 remaining = loadList.length, 17990 finish = function(){ 17991 if(!--remaining){ 17992 load(lang.delegate(cache[loadTarget])); 17993 } 17994 }; 17995 array.forEach(loadList, function(locale){ 17996 var target = bundlePathAndName + "/" + locale; 17997 if(has("dojo-preload-i18n-Api")){ 17998 checkForLegacyModules(target); 17999 } 18000 if(!cache[target]){ 18001 doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish); 18002 }else{ 18003 finish(); 18004 } 18005 }); 18006 }; 18007 18008 if(has("dojo-unit-tests")){ 18009 var unitTests = thisModule.unitTests = []; 18010 } 18011 18012 if(has("dojo-preload-i18n-Api") || 1 ){ 18013 var normalizeLocale = thisModule.normalizeLocale = function(locale){ 18014 var result = locale ? locale.toLowerCase() : dojo.locale; 18015 return result == "root" ? "ROOT" : result; 18016 }, 18017 18018 isXd = function(mid, contextRequire){ 18019 return ( 0 && 1 ) ? 18020 contextRequire.isXdUrl(require.toUrl(mid + ".js")) : 18021 true; 18022 }, 18023 18024 preloading = 0, 18025 18026 preloadWaitQueue = [], 18027 18028 preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean?*/ guaranteedAmdFormat, /*function?*/ contextRequire){ 18029 // summary: 18030 // Load available flattened resource bundles associated with a particular module for dojo/locale and all dojo/config.extraLocale (if any) 18031 // description: 18032 // Only called by built layer files. The entire locale hierarchy is loaded. For example, 18033 // if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6- 18034 // in that the v1.6- would only load ab-cd...which was *always* flattened. 18035 // 18036 // If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm 18037 // and the extra possible extra transaction. 18038 18039 // If this function is called from legacy code, then guaranteedAmdFormat and contextRequire will be undefined. Since the function 18040 // needs a require in order to resolve module ids, fall back to the context-require associated with this dojo/i18n module, which 18041 // itself may have been mapped. 18042 contextRequire = contextRequire || require; 18043 18044 function doRequire(mid, callback){ 18045 if(isXd(mid, contextRequire) || guaranteedAmdFormat){ 18046 contextRequire([mid], callback); 18047 }else{ 18048 syncRequire([mid], callback, contextRequire); 18049 } 18050 } 18051 18052 function forEachLocale(locale, func){ 18053 // given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy 18054 var parts = locale.split("-"); 18055 while(parts.length){ 18056 if(func(parts.join("-"))){ 18057 return; 18058 } 18059 parts.pop(); 18060 } 18061 func("ROOT"); 18062 } 18063 18064 function preloadingAddLock(){ 18065 preloading++; 18066 } 18067 18068 function preloadingRelLock(){ 18069 --preloading; 18070 while(!preloading && preloadWaitQueue.length){ 18071 load.apply(null, preloadWaitQueue.shift()); 18072 } 18073 } 18074 18075 function cacheId(path, name, loc, require){ 18076 // path is assumed to have a trailing "/" 18077 return require.toAbsMid(path + name + "/" + loc) 18078 } 18079 18080 function preload(locale){ 18081 locale = normalizeLocale(locale); 18082 forEachLocale(locale, function(loc){ 18083 if(array.indexOf(localesGenerated, loc) >= 0){ 18084 var mid = bundlePrefix.replace(/\./g, "/") + "_" + loc; 18085 preloadingAddLock(); 18086 doRequire(mid, function(rollup){ 18087 for(var p in rollup){ 18088 var bundle = rollup[p], 18089 match = p.match(/(.+)\/([^\/]+)$/), 18090 bundleName, bundlePath; 18091 18092 // If there is no match, the bundle is not a regular bundle from an AMD layer. 18093 if (!match){continue;} 18094 18095 bundleName = match[2]; 18096 bundlePath = match[1] + "/"; 18097 18098 // backcompat 18099 bundle._localized = bundle._localized || {}; 18100 18101 var localized; 18102 if(loc === "ROOT"){ 18103 var root = localized = bundle._localized; 18104 delete bundle._localized; 18105 root.root = bundle; 18106 cache[require.toAbsMid(p)] = root; 18107 }else{ 18108 localized = bundle._localized; 18109 cache[cacheId(bundlePath, bundleName, loc, require)] = bundle; 18110 } 18111 18112 if(loc !== locale){ 18113 // capture some locale variables 18114 function improveBundle(bundlePath, bundleName, bundle, localized){ 18115 // locale was not flattened and we've fallen back to a less-specific locale that was flattened 18116 // for example, we had a flattened 'fr', a 'fr-ca' is available for at least this bundle, and 18117 // locale==='fr-ca'; therefore, we must improve the bundle as retrieved from the rollup by 18118 // manually loading the fr-ca version of the bundle and mixing this into the already-retrieved 'fr' 18119 // version of the bundle. 18120 // 18121 // Remember, different bundles may have different sets of locales available. 18122 // 18123 // we are really falling back on the regular algorithm here, but--hopefully--starting with most 18124 // of the required bundles already on board as given by the rollup and we need to "manually" load 18125 // only one locale from a few bundles...or even better...we won't find anything better to load. 18126 // This algorithm ensures there is nothing better to load even when we can only load a less-specific rollup. 18127 // 18128 // note: this feature is only available in async mode 18129 18130 // inspect the loaded bundle that came from the rollup to see if something better is available 18131 // for any bundle in a rollup, more-specific available locales are given at localized. 18132 var requiredBundles = [], 18133 cacheIds = []; 18134 forEachLocale(locale, function(loc){ 18135 if(localized[loc]){ 18136 requiredBundles.push(require.toAbsMid(bundlePath + loc + "/" + bundleName)); 18137 cacheIds.push(cacheId(bundlePath, bundleName, loc, require)); 18138 } 18139 }); 18140 18141 if(requiredBundles.length){ 18142 preloadingAddLock(); 18143 contextRequire(requiredBundles, function(){ 18144 for(var i = 0; i < requiredBundles.length; i++){ 18145 bundle = lang.mixin(lang.clone(bundle), arguments[i]); 18146 cache[cacheIds[i]] = bundle; 18147 } 18148 // this is the best possible (maybe a perfect match, maybe not), accept it 18149 cache[cacheId(bundlePath, bundleName, locale, require)] = lang.clone(bundle); 18150 preloadingRelLock(); 18151 }); 18152 }else{ 18153 // this is the best possible (definitely not a perfect match), accept it 18154 cache[cacheId(bundlePath, bundleName, locale, require)] = bundle; 18155 } 18156 } 18157 improveBundle(bundlePath, bundleName, bundle, localized); 18158 } 18159 } 18160 preloadingRelLock(); 18161 });
18162 return true; 18163 } 18164 return false; 18165 }); 18166 } 18167 18168 preload(); 18169 array.forEach(dojo.config.extraLocale, preload); 18170 }, 18171 18172 waitForPreloads = function(id, require, load){ 18173 if(preloading){ 18174 preloadWaitQueue.push([id, require, load]); 18175 } 18176 return preloading; 18177 }, 18178 18179 checkForLegacyModules = function() 18180 {}; 18181 } 18182 18183 if( 1 ){ 18184 // this code path assumes the dojo loader and won't work with a standard AMD loader 18185 var amdValue = {}, 18186 evalBundle = 18187 // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary) 18188 new Function( 18189 "__bundle", // the bundle to evalutate 18190 "__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space 18191 "__mid", // the mid that __bundle is intended to define 18192 "__amdValue", 18193 18194 // returns one of: 18195 // 1 => the bundle was an AMD bundle 18196 // a legacy bundle object that is the value of __mid 18197 // instance of Error => could not figure out how to evaluate bundle 18198 18199 // used to detect when __bundle calls define 18200 "var define = function(mid, factory){define.called = 1; __amdValue.result = factory || mid;}," 18201 + " require = function(){define.called = 1;};" 18202 18203 + "try{" 18204 + "define.called = 0;" 18205 + "eval(__bundle);" 18206 + "if(define.called==1)" 18207 // bundle called define; therefore signal it's an AMD bundle 18208 + "return __amdValue;" 18209 18210 + "if((__checkForLegacyModules = __checkForLegacyModules(__mid)))" 18211 // bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space 18212 + "return __checkForLegacyModules;" 18213 18214 + "}catch(e){}" 18215 // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle 18216 // either way, re-eval *after* surrounding with parentheses 18217 18218 + "try{" 18219 + "return eval('('+__bundle+')');" 18220 + "}catch(e){" 18221 + "return e;" 18222 + "}" 18223 ), 18224 18225 syncRequire = function(deps, callback, require){ 18226 var results = []; 18227 array.forEach(deps, function(mid){ 18228 var url = require.toUrl(mid + ".js"); 18229 18230 function load(text){ 18231 var result = evalBundle(text, checkForLegacyModules, mid, amdValue); 18232 if(result===amdValue){ 18233 // the bundle was an AMD module; re-inject it through the normal AMD path 18234 // we gotta do this since it could be an anonymous module and simply evaluating 18235 // the text here won't provide the loader with the context to know what 18236 // module is being defined()'d. With browser caching, this should be free; further 18237 // this entire code path can be circumvented by using the AMD format to begin with 18238 results.push(cache[url] = amdValue.result); 18239 }else{ 18240 if(result instanceof Error){ 18241 console.error("failed to evaluate i18n bundle; url=" + url, result); 18242 result = {}; 18243 } 18244 // nls/<locale>/<bundle-name> indicates not the root. 18245 results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1})); 18246 } 18247 } 18248 18249 if(cache[url]){ 18250 results.push(cache[url]); 18251 }else{ 18252 var bundle = require.syncLoadNls(mid); 18253 // don't need to check for legacy since syncLoadNls returns a module if the module 18254 // (1) was already loaded, or (2) was in the cache. In case 1, if syncRequire is called 18255 // from getLocalization --> load, then load will have called checkForLegacyModules() before 18256 // calling syncRequire; if syncRequire is called from preloadLocalizations, then we 18257 // don't care about checkForLegacyModules() because that will be done when a particular 18258 // bundle is actually demanded. In case 2, checkForLegacyModules() is never relevant 18259 // because cached modules are always v1.7+ built modules. 18260 if(bundle){ 18261 results.push(bundle); 18262 }else{ 18263 if(!xhr){ 18264 try{ 18265 require.getText(url, true, load); 18266 }catch(e){ 18267 results.push(cache[url] = {}); 18268 } 18269 }else{ 18270 xhr.get({ 18271 url:url, 18272 sync:true, 18273 load:load, 18274 error:function(){ 18275 results.push(cache[url] = {}); 18276 } 18277 });
18278 } 18279 } 18280 } 18281 }); 18282 callback && callback.apply(null, results); 18283 }; 18284 18285 checkForLegacyModules = function(target){ 18286 // legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache 18287 for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i<names.length-1; object = object[names[i++]]){} 18288 if(object){ 18289 result = object[names[i]]; 18290 if(!result){ 18291 // fallback for incorrect bundle build of 1.6 18292 result = object[names[i].replace(/-/g,"_")]; 18293 } 18294 if(result){ 18295 cache[target] = result; 18296 } 18297 } 18298 return result; 18299 }; 18300 18301 thisModule.getLocalization = function(moduleName, bundleName, locale){ 18302 var result, 18303 l10nName = getBundleName(moduleName, bundleName, locale); 18304 load( 18305 l10nName, 18306 18307 // isXd() and syncRequire() need a context-require in order to resolve the mid with respect to a reference module. 18308 // Since this legacy function does not have the concept of a reference module, resolve with respect to this 18309 // dojo/i18n module, which, itself may have been mapped. 18310 (!isXd(l10nName, require) ? function(deps, callback){ syncRequire(deps, callback, require); } : require), 18311 18312 function(result_){ result = result_; } 18313 ); 18314 return result; 18315 }; 18316 18317 if(has("dojo-unit-tests")){ 18318 unitTests.push(function(doh){ 18319 doh.register("tests.i18n.unit", function(t){ 18320 var check; 18321 18322 check = evalBundle("{prop:1}", checkForLegacyModules, "nonsense", amdValue); 18323 t.is({prop:1}, check); t.is(undefined, check[1]); 18324 18325 check = evalBundle("({prop:1})", checkForLegacyModules, "nonsense", amdValue); 18326 t.is({prop:1}, check); t.is(undefined, check[1]); 18327 18328 check = evalBundle("{'prop-x':1}", checkForLegacyModules, "nonsense", amdValue); 18329 t.is({'prop-x':1}, check); t.is(undefined, check[1]); 18330 18331 check = evalBundle("({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue); 18332 t.is({'prop-x':1}, check); t.is(undefined, check[1]); 18333 18334 check = evalBundle("define({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue); 18335 t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result); 18336 18337 check = evalBundle("define('some/module', {'prop-x':1})", checkForLegacyModules, "nonsense", amdValue); 18338 t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result); 18339 18340 check = evalBundle("this is total nonsense and should throw an error", checkForLegacyModules, "nonsense", amdValue); 18341 t.is(check instanceof Error, true); 18342 }); 18343 }); 18344 } 18345 } 18346 18347 return lang.mixin(thisModule, { 18348 dynamic:true, 18349 normalize:normalize, 18350 load:load, 18351 cache:cache, 18352 getL10nName: getL10nName 18353 }); 18354}); 18355 18356}, 18357'dojo/regexp':function(){ 18358define(["./_base/kernel", "./_base/lang"], function(dojo, lang){ 18359 18360// module: 18361// dojo/regexp 18362 18363var regexp = { 18364 // summary: 18365 // Regular expressions and Builder resources 18366}; 18367lang.setObject("dojo.regexp", regexp); 18368 18369regexp.escapeString = function(/*String*/str, /*String?*/except){ 18370 // summary: 18371 // Adds escape sequences for special characters in regular expressions 18372 // except: 18373 // a String with special characters to be left unescaped 18374 18375 return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+\-^])/g, function(ch){ 18376 if(except && except.indexOf(ch) != -1){ 18377 return ch; 18378 } 18379 return "\\" + ch; 18380 }); // String 18381}; 18382 18383regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){ 18384 // summary: 18385 // Builds a regular expression that groups subexpressions 18386 // description: 18387 // A utility function used by some of the RE generators. The 18388 // subexpressions are constructed by the function, re, in the second 18389 // parameter. re builds one subexpression for each elem in the array 18390 // a, in the first parameter. Returns a string for a regular 18391 // expression that groups all the subexpressions. 18392 // arr: 18393 // A single value or an array of values. 18394 // re: 18395 // A function. Takes one parameter and converts it to a regular 18396 // expression. 18397 // nonCapture: 18398 // If true, uses non-capturing match, otherwise matches are retained 18399 // by regular expression. Defaults to false 18400 18401 // case 1: a is a single value. 18402 if(!(arr instanceof Array)){ 18403 return re(arr); // String 18404 } 18405 18406 // case 2: a is an array 18407 var b = []; 18408 for(var i = 0; i < arr.length; i++){ 18409 // convert each elem to a RE 18410 b.push(re(arr[i])); 18411 } 18412 18413 // join the REs as alternatives in a RE group. 18414 return regexp.group(b.join("|"), nonCapture); // String 18415}; 18416 18417regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){ 18418 // summary: 18419 // adds group match to expression 18420 // nonCapture: 18421 // If true, uses non-capturing match, otherwise matches are retained 18422 // by regular expression. 18423 return "(" + (nonCapture ? "?:":"") + expression + ")"; // String 18424}; 18425 18426return regexp; 18427}); 18428 18429}, 18430'dojo/string':function(){ 18431define([ 18432 "./_base/kernel", // kernel.global 18433 "./_base/lang" 18434], function(kernel, lang){ 18435 18436// module: 18437// dojo/string 18438var ESCAPE_REGEXP = /[&<>'"\/]/g; 18439var ESCAPE_MAP = { 18440 '&': '&', 18441 '<': '<', 18442 '>': '>', 18443 '"': '"', 18444 "'": ''', 18445 '/': '/' 18446}; 18447var string = { 18448 // summary: 18449 // String utilities for Dojo 18450}; 18451lang.setObject("dojo.string", string); 18452 18453string.escape = function(/*String*/str){ 18454 // summary: 18455 // Efficiently escape a string for insertion into HTML (innerHTML or attributes), replacing &, <, >, ", ', and / characters. 18456 // str: 18457 // the string to escape 18458 if(!str){ return ""; } 18459 return str.replace(ESCAPE_REGEXP, function(c) { 18460 return ESCAPE_MAP[c]; 18461 }); 18462}; 18463 18464string.rep = function(/*String*/str, /*Integer*/num){ 18465 // summary: 18466 // Efficiently replicate a string `n` times. 18467 // str: 18468 // the string to replicate 18469 // num: 18470 // number of times to replicate the string 18471 18472 if(num <= 0 || !str){ return ""; } 18473 18474 var buf = []; 18475 for(;;){ 18476 if(num & 1){ 18477 buf.push(str); 18478 } 18479 if(!(num >>= 1)){ break; } 18480 str += str; 18481 } 18482 return buf.join(""); // String 18483}; 18484 18485string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){ 18486 // summary: 18487 // Pad a string to guarantee that it is at least `size` length by 18488 // filling with the character `ch` at either the start or end of the 18489 // string. Pads at the start, by default. 18490 // text: 18491 // the string to pad 18492 // size: 18493 // length to provide padding 18494 // ch: 18495 // character to pad, defaults to '0' 18496 // end: 18497 // adds padding at the end if true, otherwise pads at start 18498 // example: 18499 // | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++". 18500 // | string.pad("Dojo", 10, "+", true); 18501 18502 if(!ch){ 18503 ch = '0'; 18504 } 18505 var out = String(text), 18506 pad = string.rep(ch, Math.ceil((size - out.length) / ch.length)); 18507 return end ? out + pad : pad + out; // String 18508}; 18509 18510string.substitute = function( /*String*/ template, 18511 /*Object|Array*/map, 18512 /*Function?*/ transform, 18513 /*Object?*/ thisObject){ 18514 // summary: 18515 // Performs parameterized substitutions on a string. Throws an 18516 // exception if any parameter is unmatched. 18517 // template: 18518 // a string with expressions in the form `${key}` to be replaced or 18519 // `${key:format}` which specifies a format function. keys are case-sensitive. 18520 // map: 18521 // hash to search for substitutions 18522 // transform: 18523 // a function to process all parameters before substitution takes 18524 // place, e.g. mylib.encodeXML 18525 // thisObject: 18526 // where to look for optional format function; default to the global 18527 // namespace 18528 // example: 18529 // Substitutes two expressions in a string from an Array or Object 18530 // | // returns "File 'foo.html' is not found in directory '/temp'." 18531 // | // by providing substitution data in an Array 18532 // | string.substitute( 18533 // | "File '${0}' is not found in directory '${1}'.", 18534 // | ["foo.html","/temp"] 18535 // | ); 18536 // | 18537 // | // also returns "File 'foo.html' is not found in directory '/temp'." 18538 // | // but provides substitution data in an Object structure. Dotted 18539 // | // notation may be used to traverse the structure. 18540 // | string.substitute( 18541 // | "File '${name}' is not found in directory '${info.dir}'.", 18542 // | { name: "foo.html", info: { dir: "/temp" } } 18543 // | ); 18544 // example: 18545 // Use a transform function to modify the values: 18546 // | // returns "file 'foo.html' is not found in directory '/temp'." 18547 // | string.substitute( 18548 // | "${0} is not found in ${1}.", 18549 // | ["foo.html","/temp"], 18550 // | function(str){ 18551 // | // try to figure out the type 18552 // | var prefix = (str.charAt(0) == "/") ? "directory": "file"; 18553 // | return prefix + " '" + str + "'"; 18554 // | } 18555 // | ); 18556 // example: 18557 // Use a formatter 18558 // | // returns "thinger -- howdy" 18559 // | string.substitute( 18560 // | "${0:postfix}", ["thinger"], null, { 18561 // | postfix: function(value, key){ 18562 // | return value + " -- howdy"; 18563 // | } 18564 // | } 18565 // | ); 18566 18567 thisObject = thisObject || kernel.global; 18568 transform = transform ? 18569 lang.hitch(thisObject, transform) : function(v){ return v; }; 18570 18571 return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, 18572 function(match, key, format){ 18573 var value = lang.getObject(key, false, map); 18574 if(format){ 18575 value = lang.getObject(format, false, thisObject).call(thisObject, value, key); 18576 } 18577 return transform(value, key).toString(); 18578 }); // String 18579}; 18580 18581string.trim = String.prototype.trim ? 18582 lang.trim : // aliasing to the native function 18583 function(str){ 18584 str = str.replace(/^\s+/, ''); 18585 for(var i = str.length - 1; i >= 0; i--){ 18586 if(/\S/.test(str.charAt(i))){ 18587 str = str.substring(0, i + 1); 18588 break; 18589 } 18590 } 18591 return str; 18592 }; 18593 18594/*===== 18595 string.trim = function(str){ 18596 // summary:
18597 // Trims whitespace from both sides of the string 18598 // str: String 18599 // String to be trimmed 18600 // returns: String 18601 // Returns the trimmed string 18602 // description: 18603 // This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript). 18604 // The short yet performant version of this function is dojo/_base/lang.trim(), 18605 // which is part of Dojo base. Uses String.prototype.trim instead, if available. 18606 return ""; // String 18607 }; 18608 =====*/ 18609 18610 return string; 18611}); 18612 18613}, 18614'dojo/cldr/nls/gregorian':function(){ 18615define({ root: 18616 18617//begin v1.x content 18618{ 18619 "dateFormatItem-Ehm": "E h:mm a", 18620 "days-standAlone-short": [ 18621 "Sun", 18622 "Mon", 18623 "Tue", 18624 "Wed", 18625 "Thu", 18626 "Fri", 18627 "Sat" 18628 ], 18629 "months-format-narrow": [ 18630 "1", 18631 "2", 18632 "3", 18633 "4", 18634 "5", 18635 "6", 18636 "7", 18637 "8", 18638 "9", 18639 "10", 18640 "11", 18641 "12" 18642 ], 18643 "field-second-relative+0": "now", 18644 "quarters-standAlone-narrow": [ 18645 "1", 18646 "2", 18647 "3", 18648 "4" 18649 ], 18650 "field-weekday": "Day of the Week", 18651 "dateFormatItem-yQQQ": "y QQQ", 18652 "dateFormatItem-yMEd": "y-MM-dd, E", 18653 "field-wed-relative+0": "this Wednesday", 18654 "field-wed-relative+1": "next Wednesday", 18655 "dateFormatItem-GyMMMEd": "G y MMM d, E", 18656 "dateFormatItem-MMMEd": "MMM d, E", 18657 "eraNarrow": [ 18658 "BCE", 18659 "CE" 18660 ], 18661 "field-tue-relative+-1": "last Tuesday", 18662 "days-format-short": [ 18663 "Sun", 18664 "Mon", 18665 "Tue", 18666 "Wed", 18667 "Thu", 18668 "Fri", 18669 "Sat" 18670 ], 18671 "dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}", 18672 "dateFormat-long": "y MMMM d", 18673 "field-fri-relative+-1": "last Friday", 18674 "field-wed-relative+-1": "last Wednesday", 18675 "months-format-wide": [ 18676 "M01", 18677 "M02", 18678 "M03", 18679 "M04", 18680 "M05", 18681 "M06", 18682 "M07", 18683 "M08", 18684 "M09", 18685 "M10", 18686 "M11", 18687 "M12" 18688 ], 18689 "dateTimeFormat-medium": "{1} {0}", 18690 "dayPeriods-format-wide-pm": "PM", 18691 "dateFormat-full": "y MMMM d, EEEE", 18692 "field-thu-relative+-1": "last Thursday", 18693 "dateFormatItem-Md": "MM-dd", 18694 "dayPeriods-format-abbr-am": "AM", 18695 "dateTimeFormats-appendItem-Second": "{0} ({2}: {1})", 18696 "dayPeriods-format-wide-noon": "noon", 18697 "dateFormatItem-yMd": "y-MM-dd", 18698 "field-era": "Era", 18699 "dateFormatItem-yM": "y-MM", 18700 "months-standAlone-wide": [ 18701 "M01", 18702 "M02", 18703 "M03", 18704 "M04", 18705 "M05", 18706 "M06", 18707 "M07", 18708 "M08", 18709 "M09", 18710 "M10", 18711 "M11", 18712 "M12" 18713 ], 18714 "timeFormat-short": "HH:mm", 18715 "quarters-format-wide": [ 18716 "Q1", 18717 "Q2", 18718 "Q3", 18719 "Q4" 18720 ], 18721 "dateFormatItem-yQQQQ": "y QQQQ", 18722 "timeFormat-long": "HH:mm:ss z", 18723 "field-year": "Year", 18724 "dateFormatItem-yMMM": "y MMM", 18725 "dateTimeFormats-appendItem-Era": "{1} {0}", 18726 "field-hour": "Hour", 18727 "months-format-abbr": [ 18728 "M01", 18729 "M02", 18730 "M03", 18731 "M04", 18732 "M05", 18733 "M06", 18734 "M07", 18735 "M08", 18736 "M09", 18737 "M10", 18738 "M11", 18739 "M12" 18740 ], 18741 "field-sat-relative+0": "this Saturday", 18742 "field-sat-relative+1": "next Saturday", 18743 "timeFormat-full": "HH:mm:ss zzzz", 18744 "dateTimeFormats-appendItem-Week": "{0} ({2}: {1})", 18745 "field-day-relative+0": "today", 18746 "field-thu-relative+0": "this Thursday", 18747 "field-day-relative+1": "tomorrow", 18748 "field-thu-relative+1": "next Thursday", 18749 "dateFormatItem-GyMMMd": "G y MMM d", 18750 "dateFormatItem-H": "HH", 18751 "months-standAlone-abbr": [ 18752 "M01", 18753 "M02", 18754 "M03", 18755 "M04", 18756 "M05", 18757 "M06", 18758 "M07", 18759 "M08", 18760 "M09", 18761 "M10", 18762 "M11", 18763 "M12" 18764 ], 18765 "quarters-format-abbr": [ 18766 "Q1", 18767 "Q2", 18768 "Q3", 18769 "Q4" 18770 ], 18771 "quarters-standAlone-wide": [ 18772 "Q1", 18773 "Q2", 18774 "Q3", 18775 "Q4" 18776 ], 18777 "dateFormatItem-Gy": "G y", 18778 "dateFormatItem-M": "L", 18779 "days-standAlone-wide": [ 18780 "Sun", 18781 "Mon", 18782 "Tue", 18783 "Wed", 18784 "Thu", 18785 "Fri", 18786 "Sat" 18787 ], 18788 "dayPeriods-format-abbr-noon": "noon", 18789 "timeFormat-medium": "HH:mm:ss", 18790 "field-sun-relative+0": "this Sunday", 18791 "dateFormatItem-Hm": "HH:mm", 18792 "field-sun-relative+1": "next Sunday", 18793 "quarters-standAlone-abbr": [ 18794 "Q1", 18795 "Q2", 18796 "Q3", 18797 "Q4" 18798 ], 18799 "eraAbbr": [ 18800 "BCE", 18801 "CE" 18802 ], 18803 "field-minute": "Minute", 18804 "field-dayperiod": "Dayperiod", 18805 "days-standAlone-abbr": [ 18806 "Sun", 18807 "Mon", 18808 "Tue", 18809 "Wed", 18810 "Thu", 18811 "Fri", 18812 "Sat" 18813 ], 18814 "dateFormatItem-d": "d", 18815 "dateFormatItem-ms": "mm:ss", 18816 "quarters-format-narrow": [ 18817 "1", 18818 "2", 18819 "3", 18820 "4" 18821 ], 18822 "field-day-relative+-1": "yesterday", 18823 "dateTimeFormat-long": "{1} {0}", 18824 "dayPeriods-format-narrow-am": "a", 18825 "dateFormatItem-h": "h a", 18826 "dateFormatItem-MMMd": "MMM d", 18827 "dateFormatItem-MEd": "MM-dd, E", 18828 "dateTimeFormat-full": "{1} {0}",
18829 "field-fri-relative+0": "this Friday", 18830 "field-fri-relative+1": "next Friday", 18831 "field-day": "Day", 18832 "days-format-wide": [ 18833 "Sun", 18834 "Mon", 18835 "Tue", 18836 "Wed", 18837 "Thu", 18838 "Fri", 18839 "Sat" 18840 ], 18841 "field-zone": "Zone", 18842 "months-standAlone-narrow": [ 18843 "1", 18844 "2", 18845 "3", 18846 "4", 18847 "5", 18848 "6", 18849 "7", 18850 "8", 18851 "9", 18852 "10", 18853 "11", 18854 "12" 18855 ], 18856 "dateFormatItem-y": "y", 18857 "dateTimeFormats-appendItem-Day": "{0} ({2}: {1})", 18858 "field-year-relative+-1": "last year", 18859 "field-month-relative+-1": "last month", 18860 "dateTimeFormats-appendItem-Year": "{1} {0}", 18861 "dateFormatItem-hm": "h:mm a", 18862 "dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})", 18863 "dayPeriods-format-abbr-pm": "PM", 18864 "days-format-abbr": [ 18865 "Sun", 18866 "Mon", 18867 "Tue", 18868 "Wed", 18869 "Thu", 18870 "Fri", 18871 "Sat" 18872 ], 18873 "eraNames": [ 18874 "BCE", 18875 "CE" 18876 ], 18877 "dateFormatItem-yMMMd": "y MMM d", 18878 "days-format-narrow": [ 18879 "S", 18880 "M", 18881 "T", 18882 "W", 18883 "T", 18884 "F", 18885 "S" 18886 ], 18887 "field-month": "Month", 18888 "days-standAlone-narrow": [ 18889 "S", 18890 "M", 18891 "T", 18892 "W", 18893 "T", 18894 "F", 18895 "S" 18896 ], 18897 "dateFormatItem-MMM": "LLL", 18898 "field-tue-relative+0": "this Tuesday", 18899 "dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})", 18900 "field-tue-relative+1": "next Tuesday", 18901 "dayPeriods-format-wide-am": "AM", 18902 "dateTimeFormats-appendItem-Month": "{0} ({2}: {1})", 18903 "dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})", 18904 "dateFormatItem-EHm": "E HH:mm", 18905 "field-mon-relative+0": "this Monday", 18906 "field-mon-relative+1": "next Monday", 18907 "dateFormat-short": "y-MM-dd", 18908 "dateFormatItem-EHms": "E HH:mm:ss", 18909 "dateFormatItem-Ehms": "E h:mm:ss a", 18910 "dayPeriods-format-narrow-noon": "n", 18911 "field-second": "Second", 18912 "field-sat-relative+-1": "last Saturday", 18913 "dateFormatItem-yMMMEd": "y MMM d, E", 18914 "field-sun-relative+-1": "last Sunday", 18915 "field-month-relative+0": "this month", 18916 "field-month-relative+1": "next month", 18917 "dateTimeFormats-appendItem-Timezone": "{0} {1}", 18918 "dateFormatItem-Ed": "d, E", 18919 "field-week": "Week", 18920 "dateFormat-medium": "y MMM d", 18921 "field-week-relative+-1": "last week", 18922 "field-year-relative+0": "this year", 18923 "field-year-relative+1": "next year", 18924 "dayPeriods-format-narrow-pm": "p", 18925 "dateTimeFormat-short": "{1} {0}", 18926 "dateFormatItem-Hms": "HH:mm:ss", 18927 "dateFormatItem-hms": "h:mm:ss a", 18928 "dateFormatItem-GyMMM": "G y MMM", 18929 "field-mon-relative+-1": "last Monday", 18930 "field-week-relative+0": "this week", 18931 "field-week-relative+1": "next week" 18932} 18933//end v1.x content 18934, 18935 "ar": true, 18936 "ca": true, 18937 "cs": true, 18938 "da": true, 18939 "de": true, 18940 "el": true, 18941 "en": true, 18942 "en-au": true, 18943 "en-ca": true, 18944 "en-gb": true, 18945 "es": true, 18946 "fi": true, 18947 "fr": true, 18948 "fr-ch": true, 18949 "he": true, 18950 "hu": true, 18951 "it": true, 18952 "ja": true, 18953 "ko": true, 18954 "nb": true, 18955 "nl": true, 18956 "pl": true, 18957 "pt": true, 18958 "pt-pt": true, 18959 "ro": true, 18960 "ru": true, 18961 "sk": true, 18962 "sl": true, 18963 "sv": true, 18964 "th": true, 18965 "tr": true, 18966 "zh": true, 18967 "zh-hant": true, 18968 "zh-hk": true, 18969 "zh-tw": true 18970}); 18971}, 18972'dojo/cldr/nls/en/gregorian':function(){ 18973define( 18974//begin v1.x content 18975{ 18976 "dateFormatItem-Ehm": "E h:mm a", 18977 "days-standAlone-short": [ 18978 "Su", 18979 "Mo", 18980 "Tu", 18981 "We", 18982 "Th", 18983 "Fr", 18984 "Sa" 18985 ], 18986 "months-format-narrow": [ 18987 "J", 18988 "F", 18989 "M", 18990 "A", 18991 "M", 18992 "J", 18993 "J", 18994 "A", 18995 "S", 18996 "O", 18997 "N", 18998 "D" 18999 ], 19000 "field-second-relative+0": "now", 19001 "quarters-standAlone-narrow": [ 19002 "1", 19003 "2", 19004 "3", 19005 "4" 19006 ], 19007 "field-weekday": "Day of the Week", 19008 "dateFormatItem-yQQQ": "QQQ y", 19009 "dateFormatItem-yMEd": "E, M/d/y", 19010 "field-wed-relative+0": "this Wednesday", 19011 "field-wed-relative+1": "next Wednesday", 19012 "dateFormatItem-GyMMMEd": "E, MMM d, y G", 19013 "dateFormatItem-MMMEd": "E, MMM d", 19014 "eraNarrow": [ 19015 "B", 19016 "A" 19017 ], 19018 "field-tue-relative+-1": "last Tuesday", 19019 "days-format-short": [ 19020 "Su", 19021 "Mo", 19022 "Tu", 19023 "We", 19024 "Th", 19025 "Fr", 19026 "Sa" 19027 ], 19028 "dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}", 19029 "dateFormat-long": "MMMM d, y", 19030 "field-fri-relative+-1": "last Friday", 19031 "field-wed-relative+-1": "last Wednesday", 19032 "months-format-wide": [ 19033 "January", 19034 "February", 19035 "March", 19036 "April", 19037 "May", 19038 "June", 19039 "July", 19040 "August", 19041 "September", 19042 "October", 19043 "November", 19044 "December" 19045 ], 19046 "dateTimeFormat-medium": "{1}
19046, {0}", 19047 "dayPeriods-format-wide-pm": "PM", 19048 "dateFormat-full": "EEEE, MMMM d, y", 19049 "field-thu-relative+-1": "last Thursday", 19050 "dateFormatItem-Md": "M/d", 19051 "dateTimeFormats-appendItem-Second": "{0} ({2}: {1})", 19052 "dayPeriods-format-wide-noon": "noon", 19053 "dateFormatItem-yMd": "M/d/y", 19054 "field-era": "Era", 19055 "dateFormatItem-yM": "M/y", 19056 "months-standAlone-wide": [ 19057 "January", 19058 "February", 19059 "March", 19060 "April", 19061 "May", 19062 "June", 19063 "July", 19064 "August", 19065 "September", 19066 "October", 19067 "November", 19068 "December" 19069 ], 19070 "timeFormat-short": "h:mm a", 19071 "quarters-format-wide": [ 19072 "1st quarter", 19073 "2nd quarter", 19074 "3rd quarter", 19075 "4th quarter" 19076 ], 19077 "dateFormatItem-yQQQQ": "QQQQ y", 19078 "timeFormat-long": "h:mm:ss a z", 19079 "field-year": "Year", 19080 "dateFormatItem-yMMM": "MMM y", 19081 "dateTimeFormats-appendItem-Era": "{0} {1}", 19082 "field-hour": "Hour", 19083 "months-format-abbr": [ 19084 "Jan", 19085 "Feb", 19086 "Mar", 19087 "Apr", 19088 "May", 19089 "Jun", 19090 "Jul", 19091 "Aug", 19092 "Sep", 19093 "Oct", 19094 "Nov", 19095 "Dec" 19096 ], 19097 "field-sat-relative+0": "this Saturday", 19098 "field-sat-relative+1": "next Saturday", 19099 "timeFormat-full": "h:mm:ss a zzzz", 19100 "dateTimeFormats-appendItem-Week": "{0} ({2}: {1})", 19101 "field-day-relative+0": "today", 19102 "field-thu-relative+0": "this Thursday", 19103 "field-day-relative+1": "tomorrow", 19104 "field-thu-relative+1": "next Thursday", 19105 "dateFormatItem-GyMMMd": "MMM d, y G", 19106 "dateFormatItem-H": "HH", 19107 "months-standAlone-abbr": [ 19108 "Jan", 19109 "Feb", 19110 "Mar", 19111 "Apr", 19112 "May", 19113 "Jun", 19114 "Jul", 19115 "Aug", 19116 "Sep", 19117 "Oct", 19118 "Nov", 19119 "Dec" 19120 ], 19121 "quarters-format-abbr": [ 19122 "Q1", 19123 "Q2", 19124 "Q3", 19125 "Q4" 19126 ], 19127 "quarters-standAlone-wide": [ 19128 "1st quarter", 19129 "2nd quarter", 19130 "3rd quarter", 19131 "4th quarter" 19132 ], 19133 "dateFormatItem-Gy": "y G", 19134 "dateFormatItem-M": "L", 19135 "days-standAlone-wide": [ 19136 "Sunday", 19137 "Monday", 19138 "Tuesday", 19139 "Wednesday", 19140 "Thursday", 19141 "Friday", 19142 "Saturday" 19143 ], 19144 "timeFormat-medium": "h:mm:ss a", 19145 "field-sun-relative+0": "this Sunday", 19146 "dateFormatItem-Hm": "HH:mm", 19147 "field-sun-relative+1": "next Sunday", 19148 "eraAbbr": [ 19149 "BC", 19150 "AD" 19151 ], 19152 "field-minute": "Minute", 19153 "field-dayperiod": "AM/PM", 19154 "dateFormatItem-d": "d", 19155 "dateFormatItem-ms": "mm:ss", 19156 "field-day-relative+-1": "yesterday", 19157 "dateFormatItem-h": "h a", 19158 "dateTimeFormat-long": "{1} 'at' {0}", 19159 "dayPeriods-format-narrow-am": "a", 19160 "dateFormatItem-MMMd": "MMM d", 19161 "dateFormatItem-MEd": "E, M/d", 19162 "dateTimeFormat-full": "{1} 'at' {0}", 19163 "field-fri-relative+0": "this Friday", 19164 "field-fri-relative+1": "next Friday", 19165 "field-day": "Day", 19166 "days-format-wide": [ 19167 "Sunday", 19168 "Monday", 19169 "Tuesday", 19170 "Wednesday", 19171 "Thursday", 19172 "Friday", 19173 "Saturday" 19174 ], 19175 "field-zone": "Time Zone", 19176 "dateTimeFormats-appendItem-Day": "{0} ({2}: {1})", 19177 "dateFormatItem-y": "y", 19178 "months-standAlone-narrow": [ 19179 "J", 19180 "F", 19181 "M", 19182 "A", 19183 "M", 19184 "J", 19185 "J", 19186 "A", 19187 "S", 19188 "O", 19189 "N", 19190 "D" 19191 ], 19192 "field-year-relative+-1": "last year", 19193 "field-month-relative+-1": "last month", 19194 "dateFormatItem-hm": "h:mm a", 19195 "dateTimeFormats-appendItem-Year": "{0} {1}", 19196 "dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})", 19197 "days-format-abbr": [ 19198 "Sun", 19199 "Mon", 19200 "Tue", 19201 "Wed", 19202 "Thu", 19203 "Fri", 19204 "Sat" 19205 ], 19206 "dateFormatItem-yMMMd": "MMM d, y", 19207 "eraNames": [ 19208 "Before Christ", 19209 "Anno Domini" 19210 ], 19211 "days-standAlone-narrow": [ 19212 "S", 19213 "M", 19214 "T", 19215 "W", 19216 "T", 19217 "F", 19218 "S" 19219 ], 19220 "dateFormatItem-MMM": "LLL", 19221 "field-month": "Month", 19222 "field-tue-relative+0": "this Tuesday", 19223 "dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})", 19224 "field-tue-relative+1": "next Tuesday", 19225 "dayPeriods-format-wide-am": "AM", 19226 "dateTimeFormats-appendItem-Month": "{0} ({2}: {1})", 19227 "dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})", 19228 "dateFormatItem-EHm": "E HH:mm", 19229 "field-mon-relative+0": "this Monday", 19230 "field-mon-relative+1": "next Monday", 19231 "dateFormat-short": "M/d/yy", 19232 "dateFormatItem-EHms": "E HH:mm:ss", 19233 "dateFormatItem-Ehms": "E h:mm:ss a", 19234 "dayPeriods-format-narrow-noon": "n", 19235 "field-second": "Second", 19236 "field-sat-relative+-1": "last Saturday", 19237 "dateFormatItem-yMMMEd": "E, MMM d, y", 19238 "field-sun-relative+-1": "last Sunday", 19239 "field-month-relative+0": "this month", 19240 "field-month-relative+1": "next month", 19241 "dateFormatItem-Ed": "d E", 19242 "dateTimeFormats-appendItem-Timezone": "{0} {1}", 19243 "field-week": "Week", 19244 "dateFormat-medium": "MMM d, y", 19245 "field-year-relative+0": "this year", 19246 "field-week-relative+-1": "last week", 19247 "field-year-relative+1": "next year", 19248 "dayPeriods-format-narrow-pm": "p", 19249 "dateTimeFormat-short": "{1}
19249, {0}", 19250 "dateFormatItem-Hms": "HH:mm:ss", 19251 "dateFormatItem-hms": "h:mm:ss a", 19252 "dateFormatItem-GyMMM": "MMM y G", 19253 "field-mon-relative+-1": "last Monday", 19254 "field-week-relative+0": "this week", 19255 "field-week-relative+1": "next week" 19256} 19257//end v1.x content 19258); 19259}, 19260'dojox/html/entities':function(){ 19261define(["dojo/_base/lang"], function(lang) { 19262 // dojox.html.entities.html [public] Array 19263 // Entity characters for HTML, represented as an array of 19264 // character code, entity name (minus & and ; wrapping. 19265 // The function wrapper is to fix global leking with the build tools. 19266 var dhe = lang.getObject("dojox.html.entities",true); 19267 19268 var _applyEncodingMap = function(str, map){ 19269 // summary: 19270 // Private internal function for performing encoding of entity characters. 19271 // tags: 19272 // private 19273 19274 // Check to see if we have genned and cached a regexp for this map yet 19275 // If we have, use it, if not, gen it, cache, then use. 19276 var mapper, regexp; 19277 if(map._encCache && 19278 map._encCache.regexp && 19279 map._encCache.mapper && 19280 map.length == map._encCache.length){ 19281 mapper = map._encCache.mapper; 19282 regexp = map._encCache.regexp; 19283 }else{ 19284 mapper = {}; 19285 regexp = ["["]; 19286 var i; 19287 for(i = 0; i < map.length; i++){ 19288 mapper[map[i][0]] = "&" + map[i][1] + ";"; 19289 regexp.push(map[i][0]); 19290 } 19291 regexp.push("]"); 19292 regexp = new RegExp(regexp.join(""), "g"); 19293 map._encCache = { 19294 mapper: mapper, 19295 regexp: regexp, 19296 length: map.length 19297 }; 19298 } 19299 str = str.replace(regexp, function(c){ 19300 return mapper[c]; 19301 }); 19302 return str; 19303 }; 19304 19305 var _applyDecodingMap = function(str, map){ 19306 // summary: 19307 // Private internal function for performing decoding of entity characters. 19308 // tags: 19309 // private 19310 var mapper, regexp; 19311 if(map._decCache && 19312 map._decCache.regexp && 19313 map._decCache.mapper && 19314 map.length == map._decCache.length){ 19315 mapper = map._decCache.mapper; 19316 regexp = map._decCache.regexp; 19317 }else{ 19318 mapper = {}; 19319 regexp = ["("]; 19320 var i; 19321 for(i = 0; i < map.length; i++){ 19322 var e = "&" + map[i][1] + ";"; 19323 if(i){regexp.push("|");} 19324 mapper[e] = map[i][0]; 19325 regexp.push(e); 19326 } 19327 regexp.push(")"); 19328 regexp = new RegExp(regexp.join(""), "g"); 19329 map._decCache = { 19330 mapper: mapper, 19331 regexp: regexp, 19332 length: map.length 19333 }; 19334 } 19335 str = str.replace(regexp, function(c){ 19336 return mapper[c]; 19337 }); 19338 return str; 19339 }; 19340 19341 dhe.html = [ 19342 ["\u0026","amp"], ["\u0022","quot"],["\u003C","lt"], ["\u003E","gt"], 19343 ["\u00A0","nbsp"] 19344 ]; 19345 19346 // dojox.html.entities.latin [public] Array 19347 // Entity characters for Latin characters and similar, represented as an array of 19348 // character code, entity name (minus & and ; wrapping. 19349 dhe.latin = [ 19350 ["\u00A1","iexcl"],["\u00A2","cent"],["\u00A3","pound"],["\u20AC","euro"], 19351 ["\u00A4","curren"],["\u00A5","yen"],["\u00A6","brvbar"],["\u00A7","sect"], 19352 ["\u00A8","uml"],["\u00A9","copy"],["\u00AA","ordf"],["\u00AB","laquo"], 19353 ["\u00AC","not"],["\u00AD","shy"],["\u00AE","reg"],["\u00AF","macr"], 19354 ["\u00B0","deg"],["\u00B1","plusmn"],["\u00B2","sup2"],["\u00B3","sup3"], 19355 ["\u00B4","acute"],["\u00B5","micro"],["\u00B6","para"],["\u00B7","middot"], 19356 ["\u00B8","cedil"],["\u00B9","sup1"],["\u00BA","ordm"],["\u00BB","raquo"], 19357 ["\u00BC","frac14"],["\u00BD","frac12"],["\u00BE","frac34"],["\u00BF","iquest"], 19358 ["\u00C0","Agrave"],["\u00C1","Aacute"],["\u00C2","Acirc"],["\u00C3","Atilde"], 19359 ["\u00C4","Auml"],["\u00C5","Aring"],["\u00C6","AElig"],["\u00C7","Ccedil"], 19360 ["\u00C8","Egrave"],["\u00C9","Eacute"],["\u00CA","Ecirc"],["\u00CB","Euml"], 19361 ["\u00CC","Igrave"],["\u00CD","Iacute"],["\u00CE","Icirc"],["\u00CF","Iuml"], 19362 ["\u00D0","ETH"],["\u00D1","Ntilde"],["\u00D2","Ograve"],["\u00D3","Oacute"], 19363 ["\u00D4","Ocirc"],["\u00D5","Otilde"],["\u00D6","Ouml"],["\u00D7","times"], 19364 ["\u00D8","Oslash"],["\u00D9","Ugrave"],["\u00DA","Uacute"],["\u00DB","Ucirc"], 19365 ["\u00DC","Uuml"],["\u00DD","Yacute"],["\u00DE","THORN"],["\u00DF","szlig"], 19366 ["\u00E0","agrave"],["\u00E1","aacute"],["\u00E2","acirc"],["\u00E3","atilde"], 19367 ["\u00E4","auml"],["\u00E5","aring"],["\u00E6","aelig"],["\u00E7","ccedil"], 19368 ["\u00E8","egrave"],["\u00E9","eacute"],["\u00EA","ecirc"],["\u00EB","euml"], 19369 ["\u00EC","igrave"],["\u00ED","iacute"],["\u00EE","icirc"],["\u00EF","iuml"], 19370 ["\u00F0","eth"],["\u00F1","ntilde"],["\u00F2","ograve"],["\u00F3","oacute"], 19371 ["\u00F4","ocirc"],["\u00F5","otilde"],["\u00F6","ouml"],["\u00F7","divide"],
19372 ["\u00F8","oslash"],["\u00F9","ugrave"],["\u00FA","uacute"],["\u00FB","ucirc"], 19373 ["\u00FC","uuml"],["\u00FD","yacute"],["\u00FE","thorn"],["\u00FF","yuml"], 19374 ["\u0192","fnof"],["\u0391","Alpha"],["\u0392","Beta"],["\u0393","Gamma"], 19375 ["\u0394","Delta"],["\u0395","Epsilon"],["\u0396","Zeta"],["\u0397","Eta"], 19376 ["\u0398","Theta"], ["\u0399","Iota"],["\u039A","Kappa"],["\u039B","Lambda"], 19377 ["\u039C","Mu"],["\u039D","Nu"],["\u039E","Xi"],["\u039F","Omicron"], 19378 ["\u03A0","Pi"],["\u03A1","Rho"],["\u03A3","Sigma"],["\u03A4","Tau"], 19379 ["\u03A5","Upsilon"],["\u03A6","Phi"],["\u03A7","Chi"],["\u03A8","Psi"], 19380 ["\u03A9","Omega"],["\u03B1","alpha"],["\u03B2","beta"],["\u03B3","gamma"], 19381 ["\u03B4","delta"],["\u03B5","epsilon"],["\u03B6","zeta"],["\u03B7","eta"], 19382 ["\u03B8","theta"],["\u03B9","iota"],["\u03BA","kappa"],["\u03BB","lambda"], 19383 ["\u03BC","mu"],["\u03BD","nu"],["\u03BE","xi"],["\u03BF","omicron"], 19384 ["\u03C0","pi"],["\u03C1","rho"],["\u03C2","sigmaf"],["\u03C3","sigma"], 19385 ["\u03C4","tau"],["\u03C5","upsilon"],["\u03C6","phi"],["\u03C7","chi"], 19386 ["\u03C8","psi"],["\u03C9","omega"],["\u03D1","thetasym"],["\u03D2","upsih"], 19387 ["\u03D6","piv"],["\u2022","bull"],["\u2026","hellip"],["\u2032","prime"], 19388 ["\u2033","Prime"],["\u203E","oline"],["\u2044","frasl"],["\u2118","weierp"], 19389 ["\u2111","image"],["\u211C","real"],["\u2122","trade"],["\u2135","alefsym"], 19390 ["\u2190","larr"],["\u2191","uarr"],["\u2192","rarr"],["\u2193","darr"], 19391 ["\u2194","harr"],["\u21B5","crarr"],["\u21D0","lArr"],["\u21D1","uArr"], 19392 ["\u21D2","rArr"],["\u21D3","dArr"],["\u21D4","hArr"],["\u2200","forall"], 19393 ["\u2202","part"],["\u2203","exist"],["\u2205","empty"],["\u2207","nabla"], 19394 ["\u2208","isin"],["\u2209","notin"],["\u220B","ni"],["\u220F","prod"], 19395 ["\u2211","sum"],["\u2212","minus"],["\u2217","lowast"],["\u221A","radic"], 19396 ["\u221D","prop"],["\u221E","infin"],["\u2220","ang"],["\u2227","and"], 19397 ["\u2228","or"],["\u2229","cap"],["\u222A","cup"],["\u222B","int"], 19398 ["\u2234","there4"],["\u223C","sim"],["\u2245","cong"],["\u2248","asymp"], 19399 ["\u2260","ne"],["\u2261","equiv"],["\u2264","le"],["\u2265","ge"], 19400 ["\u2282","sub"],["\u2283","sup"],["\u2284","nsub"],["\u2286","sube"], 19401 ["\u2287","supe"],["\u2295","oplus"],["\u2297","otimes"],["\u22A5","perp"], 19402 ["\u22C5","sdot"],["\u2308","lceil"],["\u2309","rceil"],["\u230A","lfloor"], 19403 ["\u230B","rfloor"],["\u2329","lang"],["\u232A","rang"],["\u25CA","loz"], 19404 ["\u2660","spades"],["\u2663","clubs"],["\u2665","hearts"],["\u2666","diams"], 19405 ["\u0152","OElig"],["\u0153","oelig"],["\u0160","Scaron"],["\u0161","scaron"], 19406 ["\u0178","Yuml"],["\u02C6","circ"],["\u02DC","tilde"],["\u2002","ensp"], 19407 ["\u2003","emsp"],["\u2009","thinsp"],["\u200C","zwnj"],["\u200D","zwj"], 19408 ["\u200E","lrm"],["\u200F","rlm"],["\u2013","ndash"],["\u2014","mdash"], 19409 ["\u2018","lsquo"],["\u2019","rsquo"],["\u201A","sbquo"],["\u201C","ldquo"], 19410 ["\u201D","rdquo"],["\u201E","bdquo"],["\u2020","dagger"],["\u2021","Dagger"], 19411 ["\u2030","permil"],["\u2039","lsaquo"],["\u203A","rsaquo"] 19412 ]; 19413 19414 dhe.encode = function(str/*string*/, m /*array?*/){ 19415 // summary: 19416 // Function to obtain an entity encoding for a specified character 19417 // str: 19418 // The string to process for possible entity encoding. 19419 // m: 19420 // An optional list of character to entity name mappings (array of 19421 // arrays). If not provided, it uses the and Latin entities as the 19422 // set to map and escape. 19423 // tags: 19424 // public 19425 if(str){ 19426 if(!m){ 19427 // Apply the basic mappings. HTML should always come first when decoding 19428 // as well. 19429 str = _applyEncodingMap(str, dhe.html); 19430 str = _applyEncodingMap(str, dhe.latin); 19431 19432 }else{ 19433 str = _applyEncodingMap(str, m); 19434 } 19435 } 19436 return str; 19437 }; 19438 19439 dhe.decode = function(str/*string*/, m /*array?*/){ 19440 // summary: 19441 // Function to obtain an entity encoding for a specified character 19442 // str: 19443 // The string to process for possible entity encoding to decode. 19444 // m: 19445 // An optional list of character to entity name mappings (array of 19446 // arrays). If not provided, it uses the HTML and Latin entities as the 19447 // set to map and decode. 19448 // tags: 19449 // public 19450 if(str){ 19451 if(!m){ 19452 // Apply the basic mappings. HTML should always come first when decoding 19453 // as well. 19454 str = _applyDecodingMap(str, dhe.html); 19455 str = _applyDecodingMap(str, dhe.latin); 19456 19457 }else{ 19458 str = _applyDecodingMap(str, m); 19459 } 19460 } 19461 return str; 19462 }; 19463 return dhe; 19464}); 19465 19466 19467}, 19468'dpage/widgets/SingleValueWidget':function(){ 19469define([ 19470 "dojo/_base/event" 19471 ,"dojo/on" 19472 ,"dojo/dom-attr" 19473 ,"dojo/dom-class" 19474 ,"dojo/mouse" 19475 ,"dojo/dom-geometry" 19476 , "dojo/dom-style" 19477 , "dojo/json" 19478 19479 , "dpage/modules/SingleValueModel" 19480 , "dojo/request/xhr"
19481 ,"dojox/html/entities" 19482 ,"dojo/_base/declare" 19483 , "dpage/widgets/BaseWidget"], 19484function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 19485 /** 19486 * @namespace dpage 19487 */ 19488 /** 19489 * @namespace widgets 19490 * @memberOf dpage 19491 */ 19492 /** 19493 * Base class for all widgets intended to display single values, such as single-select controls or TextBoxes, or CheckBoxes. 19494 * @class SingleValueWidget 19495 * @param {Object} [options] Optional options for the widget. 19496 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 19497 * @param {dpage.widgets.Container} [options.container] The container of the widget. 19498 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 19499 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 19500 * is created. 19501 * @param {Object} [containerNode] Optional container node to tie the widget to. 19502 * @memberOf dpage.widgets 19503 * @extends {dpage.widgets.BaseWidget} 19504 */ 19505 return dojo.declare("dpage.widgets.SingleValueWidget", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.SingleValueWidget.prototype */ { 19506 //default to the first row in the model. 19507 _dataIndex: 0, 19508 _modelIsDefault: true, 19509 _model:null, 19510 _doDataSubscriptions: true, 19511 _dataCallbackId: null, 19512 _containerNode:null, 19513 19514 constructor: function (options, srcNodeRef) 19515 { 19516 var self = this; 19517 this._containerNode = srcNodeRef; 19518 19519 //if there is no model, create a blank one. 19520 if (options == null || options.model == null) { 19521 this._model = new dpage.modules.SingleValueModel({ model: null, modelProps: { DataType: "TEXT" } }); 19522 this._modelIsDefault = true; 19523 } 19524 19525 if (options != null) { 19526 if (options.model != undefined) { 19527 this._modelIsDefault = false; 19528 if (options.model.isInstanceOf == null || !options.model.isInstanceOf(dpage.modules.SingleValueModel)) 19529 throw new Error("The model for a SingleValueWidget must be an instance of a dpage.modules.SingleValueModel for widget id = " + this.getWidgetId()); 19530 this._model = options.model; 19531 } 19532 } 19533 19534 if (this._model != null) 19535 this._dataCallbackId = this._model.addDataCallback(function () { self._modelChangedCallback(); }); 19536 }, 19537 postCreate: function () { 19538 return this.inherited(arguments); 19539 }, 19540 /** 19541 * If no model is passed into the constructor, a default model is constructed with a null value. 19542 * @returns {bool} true or false. 19543 */ 19544 isModelDefault : function() 19545 { 19546 return this._modelIsDefault; 19547 }, 19548 /** 19549 * Get the model. 19550 * @returns {dpage.modules.SingleValueModel} 19551 */ 19552 getModel : function() 19553 { 19554 return this._model; 19555 }, 19556 /** 19557 * Set the model for the SingleValueWidget 19558 * @param {dpage.modules.SingleValueModel} model 19559 * @returns {void} 19560 */ 19561 setModel: function (model) { 19562 var self = this; 19563 19564 if (this._dataCallbackId != null) 19565 this.getModel().removeDataCallback(this._dataCallbackId); 19566 19567 this._modelIsDefault = false; 19568 19569 if (model.isInstanceOf == null || !model.isInstanceOf(dpage.modules.SingleValueModel)) 19570 throw new Error("The model for a SingleValueWidget must be an instance of a dpage.modules.SingleValueModel for widget id = " + this.getWidgetId()); 19571 19572 this._model = model; 19573 19574 this._dataCallbackId = this._model.addDataCallback(function () { self._modelChangedCallback(); }); 19575 }, 19576 /** 19577 * Get the value from the underlying model. This may or not match the value in some controls (if there is a validation error for instance,
19578 * the value in the control may be marked as invalid, and in that case will not be reflected in the model). 19579 * @returns {Object} 19580 */ 19581 getValue : function() 19582 { 19583 return this._model.getValue(); 19584 }, 19585 /** 19586 * Sets the value in the model without causing the control to re-render. 19587 * @param {Object} value The value to set (String/bool/Number, etc) 19588 * @returns {void} 19589 */ 19590 setModelValue : function(value) 19591 { 19592 var oldS = this.isSubscribedToModelChanges(); 19593 19594 if (oldS) 19595 this.setDataSubscriptions(false); 19596 19597 this.getModel().setValue(value); 19598 19599 this.setDataSubscriptions(oldS); 19600 }, 19601 /** 19602 * Set the value for the widget. This will update the value in the model. 19603 * @param {Object} value The value to set. This can be a String, Date, Number, boolean. No arrays or complex objects. 19604 * @returns {void} 19605 */ 19606 setValue: function (value) 19607 { 19608 this.setModelValue(value); 19609 19610 this._updateView(); 19611 }, 19612 /** 19613 * Call this method to turn data subscriptions on or off. If off, the widget will not respond to updates on the model. 19614 * @param {bool} trueOrFalse Do data subscriptions or don't 19615 * @returns {void} 19616 */ 19617 setDataSubscriptions: function (trueOrFalse) { 19618 this._doDataSubscriptions = trueOrFalse; 19619 }, 19620 /** 19621 * Is this widget responding to changes to the model or not. 19622 * @returns {bool} 19623 */ 19624 isSubscribedToModelChanges : function() 19625 { 19626 return this._doDataSubscriptions; 19627 }, 19628 //called after the data gets added 19629 _modelChangedCallback: function () { 19630 if (this._doDataSubscriptions) { 19631 //check to see if the row is our row and the data field is our data field. 19632 this._modelChanged(); 19633 } 19634 19635 }, 19636 /* Can be overridden to listen to events on the Model. 19637 * @abstract 19638 * @returns {void} 19639 */ 19640 _modelChanged: function () { 19641 this._updateView(); 19642 }, 19643 19644 19645 destroy: function () { 19646 //so we will get garbage collected correctly. 19647 this._model.removeDataCallback(this._dataCallbackId); 19648 this.inherited(arguments); 19649 }, 19650 19651 templateString: "<div></div>" 19652 }); 19653}); 19654 19655}, 19656'dpage/modules/SingleValueModel':function(){ 19657define([ 19658 "dojo/_base/declare" 19659 , "dojo/on" 19660 , "dojo/_base/event" 19661 19662 , "dpage/modules/Date" 19663 , "dpage/modules/Model" 19664], 19665 function (declare, on, event) { 19666 /** 19667 * @namespace dpage 19668 */ 19669 /** 19670 * @namespace modules 19671 * @memberOf dpage 19672 */ 19673 /** 19674 * Class to provide controlled access to data. This class encapsulates a single scalar value such as a string, boolean, date, or number. 19675 * @class SingleValueModel 19676 * @param {Object} [options] Optional options for the TabularModel. 19677 * @param {Object} [options.displayName] The display name of this property. This will be used in things like validation messages. If passed, overrides the DisplayName and FieldName properties in the modelProps. 19678 * @param {Object} [options.model] Object containing the data. This has to be a scalar value such as a String, bool, or Number 19679 * @param {Object} [options.modelProps] Optional properties describing the model value including DataType, etc. 19680 * @param {String} [options.modelProps.ColumnName] Name of the field in the model (Deprecated). 19681 * @param {String} [options.modelProps.DataType] NUMBER, BOOL, DATE, or TEXT 19682 * @param {String} [options.modelProps.DisplayName] Value used for display of the field to the user. 19683 * @param {String} [options.modelProps.FieldName] Name of the field in the model. 19684 * @param {Number} [options.modelProps.MaxLength] Maximum character length. 19685 * @param {String} [options.modelProps.MaxLengthValidationMessage] Message to display for MaxLength validation failure. 19686 * @param {Number}
19686 [options.modelProps.MaxValue] Maximum value for NUMBER type. 19687 * @param {Number} [options.modelProps.MinValue] Minimum value for NUMBER type. 19688 * @param {String} [options.modelProps.NumberValidationMessage] Message to display if the number validation fails. 19689 * @param {Number} [options.modelProps.NumDecimals] Maximum number of decimals for NUMBER type. 19690 * @param {bool} [options.modelProps.Required] Is a non-blank value required in this field 19691 * @param {String} [options.modelProps.RequiredValidationMessage] Message to display for Required validation failure. 19692 * @param {String} [options.modelProps.ValidationPattern] Javascript regular expression for input validation. 19693 * @param {String} [options.modelProps.ValidationPatternMessage] Custom message to display if ValidationPattern fails. 19694 * @memberOf dpage.modules 19695 * @extends {dpage.modules.Model} 19696 */ 19697 return declare("dpage.modules.SingleValueModel", [dpage.modules.Model], /** @lends dpage.modules.SingleValueModel.prototype */ { 19698 _model: null, 19699 _dataCallbacks: null, 19700 _lastDataCallbackId: 0, 19701 _dataCallbackRowId: 0, 19702 _modelProps: null, 19703 _isDirty: false, 19704 _displayName:null, 19705 19706 constructor: function (options) { 19707 var self = this; 19708 19709 this._dataCallbacks = []; 19710 19711 if (options != null) { 19712 if (options.modelProps != null) 19713 this._modelProps = options.modelProps; 19714 19715 if (options.model != null) { 19716 this._model = options.model; 19717 } 19718 19719 if (options.displayName != null) 19720 this._displayName = options.displayName; 19721 } 19722 19723 if (this._modelProps == null) { 19724 this._modelProps = {FieldName : '' , DataType:'TEXT'}; 19725 } 19726 }, 19727 getRawModel : function() 19728 { 19729 return this._model; 19730 }, 19731 /** 19732 * Get the name of this model property. Used in things like validation message texts. Priority is 1) this._displayName , 2) modelProps.DisplayName, 3) modelProps.FieldName 19733 * @returns {String} 19734 */ 19735 getDisplayName : function() 19736 { 19737 if (this._displayName != null) 19738 return this._displayName; 19739 19740 else if (this._modelProps != null && this._modelProps.DisplayName != null) 19741 return this._modelProps.DisplayName; 19742 19743 else if (this._modelProps != null && this._modelProps.FieldName != null) 19744 return this._modelProps.FieldName; 19745 19746 return ""; 19747 }, 19748 /** 19749 * You can listen for changes to data by adding your callback routine here. Changes can be listened in on a row level 19750 * or global level only. 19751 * @param {function} funcRef The function to call when data is modified. The callback function will be passed a single parameter containing the new value. 19752 * Will be called if that particular row is changed. 19753 * @returns {Number} The id of the callback. Can be used to remove the callback. 19754 */ 19755 addDataCallback: function (funcRef) { 19756 var rowId; 19757 var id = ++this._lastDataCallbackId; 19758 19759 this._dataCallbacks.push({ id: id, func: funcRef}); 19760 19761 return id; 19762 }, 19763 /** 19764 * @param {Number} id The callback id to remove. 19765 * @returns {void} 19766 */ 19767 removeDataCallback: function (id) { 19768 for (idx = 0; idx < this._dataCallbacks.length ; idx++) { 19769 if (this._dataCallbacks[idx].id == id) 19770 this._dataCallbacks.splice(idx, 1); 19771 } 19772 }, 19773 /** 19774 * Get metadata for the model. 19775 * @returns {Object}
19775 This object contains the meta-data properties. Refer to the constructor's options.modelProps property 19776 * for information on supported properties. 19777 */ 19778 getMetadata : function() 19779 { 19780 return this._modelProps; 19781 }, 19782 /** 19783 * Set a value. The official way to set a value in a SingleValueModel 19784 * @param {Object} value The value to set. Must be a bool, String, or Number 19785 * @returns {void} 19786 */ 19787 setValue: function (value) { 19788 19789 if (this._modelProps.DataType == "DATE" && value != null && value != "" && dpage.modules.Date.parseModelValue(value) == null) 19790 throw new Error("Attempting to set a value on a SingleValueModel DataType=='DATE'. Value is: " + value + " but it should be in ISO-8601 format."); 19791 19792 this._model = value; 19793 19794 this._isDirty = true; 19795 19796 this.doCallbacks(); 19797 }, 19798 /** 19799 * Has the data been updated? 19800 * @returns {bool} true | false. 19801 */ 19802 isDirty : function() 19803 { 19804 return this._isDirty; 19805 }, 19806 setClean : function() 19807 { 19808 this._isDirty = false; 19809 }, 19810 /** 19811 * A caller can cause the registered callback routines to fire by calling this method directly. Not normally needed. 19812 * This will cause the callback routines to be called even if data hasn't really been changed. 19813 * Only use this method if you know what you are doing. 19814 * @returns {void} 19815 */ 19816 doCallbacks: function () { 19817 19818 for (var x = 0; x < this._dataCallbacks.length ; x++) { 19819 var callback = this._dataCallbacks[x].func; 19820 callback(this.getValue()); 19821 } 19822 }, 19823 /** 19824 * The official way to get a value from a SingleValueModel. 19825 * @returns {Object} The data. Will be String, Number, or Boolean 19826 */ 19827 getValue: function () { 19828 return this._model; 19829 } 19830 19831 }); 19832 } 19833); 19834}, 19835'dpage/widgets/BaseWidget':function(){ 19836define(["dojo/on", 19837 19838 "dpage/modules/Date", 19839 "dojo/_base/declare", 19840 "dijit/_WidgetBase", 19841 "dpage/modules/TabularModel" 19842], function (on) { 19843 /** 19844 * @namespace dpage 19845 */ 19846 /** 19847 * @namespace widgets 19848 * @memberOf dpage 19849 */ 19850 /** 19851 * Class to contain methods common to all UI widgets. 19852 * @class BaseWidget 19853 * @param {Object} [options] Optional options for the widget 19854 * @param {dpage.widgets.Container} [options.container] The container of the widget. 19855 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 19856 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 19857 * is created. 19858 * @param {Object} [containerNode] Optional container node to tie the widget to. 19859 * @memberOf dpage.widgets 19860 * @extends {dijit._WidgetBase} 19861 */ 19862 var theClass = dojo.declare("dpage.widgets.BaseWidget", [dijit._WidgetBase], /** @lends dpage.widgets.BaseWidget.prototype */ { 19863 _widgetContainer: null, 19864 _widgetId: null, 19865 _validateCallback: null, 19866 _doDataSubscriptions: true, 19867 _overlay: null, 19868 _oldFocusedNode : null, 19869 _containerNode: null, //The root dom node of the widget. 19870 _validationMessage: null, 19871 19872 constructor: function (options, containerNode) { 19873 if (options != null) 19874 { 19875 if(options.container != null) 19876 this._widgetContainer = options.container; 19877 if (options.validateCallback != null) 19878 { 19879 this._validateCallback = options.validateCallback; 19880 } 19881 if (options.wid != null) 19882 this._widgetId = options.wid; 19883 else 19884 this._widgetId = dpage.widgets.BaseWidget.getAnonWidgetId(); 19885 } 19886 19887 if(this._widgetContainer != null) 19888 this._widgetContainer.addWidget(this); 19889 }, 19890 19891 postCreate : function() 19892 { 19893 this._updateView(); 19894 }, 19895 //catch-all for dpage widgets. 19896 buildRendering: function () { 19897 this.domNode = this._containerNode; 19898 return this._containerNode; 19899 }, 19900 _blurActiveElement : function() 19901 { 19902 if (document.activeElement != null) { 19903 this._oldFocusedNode = document.activeElement; 19904 if (this._oldFocusedNode.blur != null) 19905 this._oldFocusedNode.blur(); 19906 } 19907 }, 19908 _focusOldActiveElement: function () { 19909 if (this._oldFocusedNode != null && this._oldFocusedNode.focus != null) { 19910 this._oldFocusedNode.focus(); 19911 this._oldFocusedNode = null; 19912 } 19913 }, 19914 /** 19915 * Block or un-block user interaction with the widget. 19916 * @param {bool} trueOrFalse If true, the widget will be blocked out, if false, un-blocked out. 19917 * @returns {void} 19918 */ 19919 blockUI : function(trueOrFalse) 19920 { 19921 var self = this; 19922 19923 if(trueOrFalse) 19924 {
19925 if (this._overlay == null) { 19926 //make sure this is the highest zIndex of any element in the page so it blocks the whole page. 19927 this._overlay = new dojox.widget.Standby({ target: this.getDomNode(), zIndex: 1001 }); 19928 document.body.appendChild(this._overlay.domNode); 19929 this._overlay.startup(); 19930 } 19931 19932 //for the case when tab is hit on an element and we call blockUI here, the next element in the tab order is 19933 //focused after we get here, so we try to overcome this by setting a timeout so that by the time 19934 //_blurActiveElement is called, the next element in the tab order is already focused, so that we can un-focus it. 19935 setTimeout(function () { self._blurActiveElement(); }); 19936 19937 this._overlay.show(); 19938 } 19939 else 19940 { 19941 if (this._overlay != null) 19942 this._overlay.hide(); 19943 19944 if (this._oldFocusedNode != null) { 19945 if (this._oldFocusedNode.focus != null) { 19946 setTimeout(function () { 19947 self._focusOldActiveElement(); 19948 },0); 19949 } 19950 } 19951 } 19952 }, 19953 /** 19954 * Get a reference to the native browser dom node. 19955 * @returns {NativeDomNode} 19956 */ 19957 getDomNode : function() 19958 { 19959 return this._containerNode; 19960 }, 19961 19962 /** 19963 * Gets the widgetId. 19964 * @returns {String} 19965 */ 19966 getWidgetId: function () { 19967 return this._widgetId; 19968 }, 19969 19970 /** 19971 * Gives you the container of the Widget. Could be a page or a generic container (like a dialog). 19972 * This method will return null if there is no container (container not specified in widget options). 19973 * @returns {dpage.widgets.Container} null for no container, or reference to the Container object. 19974 */ 19975 getContainer: function () { 19976 return this._widgetContainer; 19977 }, 19978 /** 19979 * Sets the container object for this widget 19980 * @param {dpage.widgets.Container} obj 19981 */ 19982 setContainer:function(obj) 19983 { 19984 if (this._widgetContainer != null) 19985 this._widgetContainer.removeWidget(this.getWidgetId()); 19986 19987 this._widgetContainer = obj; 19988 19989 obj.addWidget(this); 19990 }, 19991 /* 19992 * This method re-draws the widget in response to model changes. Can be subclassed to do widget specific drawing. All widgets overriding this method should call the base 19993 * class to do common BaseWidget operations such as clearing the validation state. 19994 * @returns {void} 19995 */ 19996 _updateView : function() 19997 { 19998 //clear the validation state. Validation is not performed on direct model changes, only on USER INPUT. 19999 this.setValidationMessage(null); 20000 }, 20001 /** Perform validation for this one particular BaseWidget. 20002 * @returns {String} Returns null for success. A string message indicating the error if not successfull. 20003 */ 20004 validate : function() 20005 { 20006 if (this._validateCallback) 20007 return this._validateCallback(this); 20008 }, 20009 /** Set the validation state of the control. 20010 * @param {String} message The message to display. Pass in null to clear an invalid state. Non-null to set the invalid state. 20011 * @returns {void} 20012 */ 20013 setValidationMessage : function(message){ 20014 this._validationMessage = message; 20015 }, 20016 /** 20017 * Get the validation state of the control. 20018 * @returns {String} null for valid state. Non-null for an invalid state and the value will be the message. 20019 */ 20020 getValidationMessage : function(){ 20021 return this._validationMessage; 20022 }, 20023 /** 20024 * This method performs any cleanup needed for the widget and removes it's getDomNode() from the DOM. 20025 * @returns {void} 20026 */ 20027 destroy : function() 20028 { 20029 return this.inherited(arguments); 20030 } 20031 });
20032 20033 theClass._awId = 0; 20034 20035 /** 20036 * Get a unique id used to uniquely identify a widget with no named id. 20037 * @memberof dpage.widgets.BaseWidget 20038 * @name getAnonWidgetId 20039 * @function 20040 * @returns {String} 20041 */ 20042 theClass.getAnonWidgetId = function () { 20043 return "aw" + (--theClass._awId); 20044 }; 20045 20046 /** 20047 * Return a message indicating the error or null for no validation error. 20048 * @memberof dpage.widgets.BaseWidget 20049 * @name validate 20050 * @function 20051 * @param {Object} value The value to validate. 20052 * @param {Object} metaData The metadata object from the model. 20053 * @param {String} fieldName The name of the field to display in the non-custom error message. 20054 * @returns {String} null for success. non-empty string otherwise. 20055 */ 20056 theClass.validate = function (value, metaData , fieldName) { 20057 var ret; 20058 var dataType; 20059 20060 dataType = metaData.DataType; 20061 20062 if (dataType == "NUMBER") 20063 ret = dpage.widgets.BaseWidget.validateNumber(value , metaData , fieldName); 20064 else if (dataType == "TEXT") 20065 ret = dpage.widgets.BaseWidget.validateText(value, metaData, fieldName); 20066 else if (dataType == "DATE") 20067 ret = dpage.widgets.BaseWidget.validateDate(value, metaData, fieldName); 20068 20069 return ret; 20070 }; 20071 20072 /** 20073 * Return a message indicating the error or null for no validation error. 20074 * @memberof dpage.widgets.BaseWidget 20075 * @name validateNumber 20076 * @function 20077 * @param {Object} value The value to validate. 20078 * @param {Object} metaData The metadata object from the model. 20079 * @param {String} fieldName The name of the field to display in the non-custom error message. 20080 * @returns {String} null for success. non-empty string otherwise. 20081 */ 20082 theClass.validateNumber = function (value , metaData , fieldName) 20083 { 20084 var vMsg; 20085 var numDecimalPlaces; 20086 var minValue; 20087 var maxValue; 20088 var numberPattern; 20089 var re; 20090 var parsedNumber; 20091 var colInfo; 20092 var required; 20093 20094 vMsg = metaData.NumberValidationMessage; 20095 var requiredMessage = metaData.RequiredValidationMessage; 20096 numDecimalPlaces = metaData.NumDecimals; 20097 minValue = metaData.MinValue; 20098 maxValue = metaData.MaxValue; 20099 required = metaData.Required; 20100 20101 if (vMsg == null) { 20102 vMsg = fieldName + " must be a"; 20103 20104 if (numDecimalPlaces == 0) 20105 vMsg += " whole number"; 20106 else if (numDecimalPlaces == -1 || numDecimalPlaces == null) 20107 vMsg += " decimal number"; 20108 else 20109 vMsg += " decimal number (maximum " + numDecimalPlaces + " decimal places)"; 20110 20111 if (minValue != null && maxValue != null) 20112 vMsg += " between " + minValue + " and " + maxValue; 20113 else if (minValue != null) 20114 vMsg += " greater than " + minValue; 20115 else if (minValue != null) 20116 vMsg += " less than " + maxValue; 20117 20118 vMsg += "."; 20119 } 20120 20121 if (fieldName == null) 20122 fieldName = metaData.FieldName; 20123 20124 if (value == null || /^\s*$/.test(value)) { 20125 if (required ) { 20126 if (requiredMessage != null) 20127 return requiredMessage; 20128 else 20129 return fieldName + " is required."; 20130 } 20131 } 20132 else { 20133 //we only get here in the case of non-null. 20134 if (numDecimalPlaces == -1 || numDecimalPlaces == null) 20135 numberPattern = "(^\\s*-[0-9]*\\s*\\.[0-9]+\\s*$)|(^\\s*-[0-9]+\\s*$)|(^\\s*[0-9]*\\.[0-9]+\\s*$)|(^\\s*[0-9]+\\s*$)$"; 20136 else if(numDecimalPlaces == 0) 20137 numberPattern = "(^\\s*-\\s*[0-9]+\\s*$)|(^\\s*[0-9]*\\s*)$"; 20138 else 20139 numberPattern = "(^\\s*-\\s*[0-9]*\\.[0-9]{1," + numDecimalPlaces + "}\\s*$)|(^\\s*-[0-9]+\\s*$)|(^\\s*[0-9]*\\.[0-9]{1," + numDecimalPlaces + "}\\s*$)|(^[0-9]+\\s*$)"; 20140 20141 re = new RegExp(numberPattern); 20142 20143 if (!re.exec(value)) 20144 { 20145 return vMsg; 20146 } 20147 20148 parsedNumber = new Number(value); 20149 20150 if((maxValue != null && parsedNumber > maxValue) 20151 || 20152 (minValue != null && parsedNumber < minValue)) 20153 { 20154 return vMsg; 20155 } 20156 } 20157 20158 return null; 20159 }; 20160 20161 /** 20162 * Return a message indicating the error or null for no validation error. 20163 * @memberof dpage.widgets.BaseWidget 20164 * @name validateText 20165 * @function 20166 * @param {Object} value The value to validate. 20167 * @param {Object} metaData The metadata object from the model. 20168 * @param {String} fieldName The name of the field to display in the non-custom error message. 20169 * @returns {String} null for success. non-empty string otherwise. 20170 */ 20171 dpage.widgets.BaseWidget.validateText = function (value, metaData , fieldName) { 20172 var maxLength = metaData.MaxLength; 20173 var required = metaData.Required; 20174 var requiredMessage = metaData.RequiredValidationMessage; 20175 var maxLengthMessage = metaData.MaxLengthValidationMessage; 20176 var patternMessage = metaData.ValidationPatternMessage; 20177 var pattern = metaData.ValidationPattern; 20178 20179 if(fieldName == null) 20180 fieldName = metaData.FieldName; 20181 20182 if (value != null && maxLength != null && value.length > maxLength) { 20183 if (maxLengthMessage != null) 20184 return maxLengthMessage; 20185 else 20186 return fieldName + " must be less than " + (maxLength + 1) + " characters."; 20187 } 20188 20189 if (required && (value == null || /^\s*$/.exec(value))) { 20190 if (requiredMessage != null) 20191 return requiredMessage; 20192 else 20193 return fieldName + " is required."; 20194 } 20195 20196 if (pattern != null) { 20197 var re = new RegExp(pattern); 20198 var nnv = value == null ? "" : value; 20199 if (!re.exec(nnv)) { 20200 if (patternMessage != null) 20201 return patternMessage; 20202 else 20203 return fieldName + " must match the pattern: '" + pattern + "'."; 20204 } 20205 } 20206 20207 return null; 20208 }; 20209 20210 /** 20211 * Return a message indicating the error or null for no validation error. 20212 * @memberof dpage.widgets.BaseWidget 20213 * @name validateDate 20214 * @function 20215 * @param {Object} value The value to validate. 20216 * @param {Object} metaData The metadata object from the model. 20217 * @param {String} fieldName The name of the field to display in the non-custom error message. 20218 * @returns {String} null for success. non-empty string otherwise. 20219 */ 20220 dpage.widgets.BaseWidget.validateDate = function (value, metaData, fieldName) { 20221 var maxLength = metaData.MaxLength; 20222 var required = metaData.Required; 20223 var requiredMessage = metaData.RequiredValidationMessage; 20224 var maxLengthMessage = metaData.MaxLengthValidationMessage; 20225 var patternMessage = metaData.ValidationPatternMessage; 20226 var pattern = metaData.ValidationPattern; 20227 20228 if (fieldName == null) 20229 fieldName = metaData.FieldName; 20230 20231 if (value != null && maxLength != null && value.length > maxLength) { 20232 if (maxLengthMessage != null) 20233 return maxLengthMessage; 20234 else 20235 return fieldName + " must be less than " + (maxLength + 1) + " characters."; 20236 } 20237 20238 if (required && (value == null || /^\s*$/.exec(value))) { 20239 if (requiredMessage != null) 20240 return requiredMessage; 20241 else 20242 return fieldName + " is required."; 20243 } 20244 20245 if (pattern != null) { 20246 var re = new RegExp(pattern); 20247 var nnv = value == null ? "" : value; 20248 if (!re.exec(nnv)) { 20249 if (patternMessage != null) 20250 return patternMessage; 20251 else 20252 return fieldName + " must match the pattern: '" + pattern + "'."; 20253 } 20254 } 20255 20256 if (value != null && value != "") { 20257 //attempt to parse the date. 20258 var v = dpage.modules.Date.parseModelValue(value); 20259 20260 if (v == null) 20261 return fieldName + " must be a valid date."; 20262 } 20263 20264 return null; 20265 }; 20266 20267 return theClass; 20268}); 20269 20270}, 20271'dijit/_WidgetBase':function(){ 20272define([ 20273 "require", // require.toUrl 20274 "dojo/_base/array", // array.forEach array.map 20275 "dojo/aspect", 20276 "dojo/_base/config", // config.blankGif 20277 "dojo/_base/connect", // connect.connect 20278 "dojo/_base/declare", // declare 20279 "dojo/dom", // dom.byId 20280 "dojo/dom-attr", // domAttr.set domAttr.remove 20281 "dojo/dom-class", // domClass.add domClass.replace 20282 "dojo/dom-construct", // domConstruct.destroy domConstruct.place 20283 "dojo/dom-geometry", // isBodyLtr 20284 "dojo/dom-style", // domStyle.set, domStyle.get 20285 "dojo/has", 20286 "dojo/_base/kernel", 20287 "dojo/_base/lang", // mixin(), isArray(), etc. 20288 "dojo/on", 20289 "dojo/ready", 20290 "dojo/Stateful", // Stateful 20291 "dojo/topic", 20292 "dojo/_base/window", // win.body() 20293 "./Destroyable", 20294 "dojo/has!dojo-bidi?./_BidiMixin", 20295 "./registry" // registry.getUniqueId(), registry.findWidgets() 20296], function(require, array, aspect, config, connect, declare, 20297 dom, domAttr, domClass, domConstruct, domGeometry, domStyle, has, kernel, 20298 lang, on, ready, Stateful, topic, win, Destroyable, _BidiMixin, registry){ 20299 20300 // module: 20301 // dijit/_WidgetBase 20302 20303 // Flag to make dijit load modules the app didn't explicitly request, for backwards compatibility 20304 has.add("dijit-legacy-requires", !kernel.isAsync); 20305 20306 // Flag to enable support for textdir attribute 20307 has.add("dojo-bidi", false); 20308 20309 20310 // For back-compat, remove in 2.0. 20311 if(has("dijit-legacy-requires")){ 20312 ready(0, function(){ 20313 var requires = ["dijit/_base/manager"]; 20314 require(requires); // use indirection so modules not rolled into a build 20315 }); 20316 } 20317 20318 // Nested hash listing attributes for each tag, all strings in lowercase.
20319 // ex: {"div": {"style": true, "tabindex" true}, "form": { ... 20320 var tagAttrs = {}; 20321 20322 function getAttrs(obj){ 20323 var ret = {}; 20324 for(var attr in obj){ 20325 ret[attr.toLowerCase()] = true; 20326 } 20327 return ret; 20328 } 20329 20330 function nonEmptyAttrToDom(attr){ 20331 // summary: 20332 // Returns a setter function that copies the attribute to this.domNode, 20333 // or removes the attribute from this.domNode, depending on whether the 20334 // value is defined or not. 20335 return function(val){ 20336 domAttr[val ? "set" : "remove"](this.domNode, attr, val); 20337 this._set(attr, val); 20338 }; 20339 } 20340 20341 function isEqual(a, b){ 20342 // summary: 20343 // Function that determines whether two values are identical, 20344 // taking into account that NaN is not normally equal to itself 20345 // in JS. 20346 20347 return a === b || (/* a is NaN */ a !== a && /* b is NaN */ b !== b); 20348 } 20349 20350 var _WidgetBase = declare("dijit._WidgetBase", [Stateful, Destroyable], { 20351 // summary: 20352 // Future base class for all Dijit widgets. 20353 // description: 20354 // Future base class for all Dijit widgets. 20355 // _Widget extends this class adding support for various features needed by desktop. 20356 // 20357 // Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(), 20358 // postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch(). 20359 // 20360 // Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value). 20361 // For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr(). 20362 // 20363 // _setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes: 20364 // 20365 // - DOM node attribute 20366 // | _setFocusAttr: {node: "focusNode", type: "attribute"} 20367 // | _setFocusAttr: "focusNode" (shorthand) 20368 // | _setFocusAttr: "" (shorthand, maps to this.domNode) 20369 // Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus 20370 // 20371 // - DOM node innerHTML 20372 // | _setTitleAttr: { node: "titleNode", type: "innerHTML" } 20373 // Maps this.title to this.titleNode.innerHTML 20374 // 20375 // - DOM node innerText 20376 // | _setTitleAttr: { node: "titleNode", type: "innerText" } 20377 // Maps this.title to this.titleNode.innerText 20378 // 20379 // - DOM node CSS class 20380 // | _setMyClassAttr: { node: "domNode", type: "class" } 20381 // Maps this.myClass to this.domNode.className 20382 // 20383 // If the value of _setXXXAttr is an array, then each element in the array matches one of the 20384 // formats of the above list. 20385 // 20386 // If the custom setter is null, no action is performed other than saving the new value 20387 // in the widget (in this). 20388 // 20389 // If no custom setter is defined for an attribute, then it will be copied 20390 // to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise. 20391 // That's only done though for attributes that match DOMNode attributes (title, 20392 // alt, aria-labelledby, etc.) 20393 20394 // id: [const] String 20395 // A unique, opaque ID string that can be assigned by users or by the 20396 // system. If the developer passes an ID which is known not to be 20397 // unique, the specified ID is ignored and the system-generated ID is 20398 // used instead. 20399 id: "", 20400 _setIdAttr: "domNode", // to copy to this.domNode even for auto-generated id's 20401 20402 // lang: [const] String 20403 // Rarely used. Overrides the default Dojo locale used to render this widget, 20404 // as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute. 20405 // Value must be among the list of locales specified during by the Dojo bootstrap, 20406 // formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us). 20407 lang: "", 20408 // set on domNode even when there's a focus node. but don't set lang="", since that's invalid. 20409 _setLangAttr: nonEmptyAttrToDom("lang"), 20410 20411 // dir: [const] String 20412 // Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir) 20413 // attribute. Either left-to-right "ltr" or right-to-left "rtl". If undefined, widgets renders in page's 20414 // default direction. 20415 dir: "", 20416 // set on domNode even when there's a focus node. but don't set dir="", since that's invalid. 20417 _setDirAttr: nonEmptyAttrToDom("dir"), // to set on domNode even when there's a focus node 20418 20419 // class: String 20420 // HTML class attribute 20421 "class": "", 20422 _setClassAttr: { node: "domNode", type: "class" }, 20423 20424 // Override automatic assigning type -->
20424 focusNode, it causes exception on IE6-8. 20425 // Instead, type must be specified as ${type} in the template, as part of the original DOM. 20426 _setTypeAttr: null, 20427 20428 // style: String||Object 20429 // HTML style attributes as cssText string or name/value hash 20430 style: "", 20431 20432 // title: String 20433 // HTML title attribute. 20434 // 20435 // For form widgets this specifies a tooltip to display when hovering over 20436 // the widget (just like the native HTML title attribute). 20437 // 20438 // For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer, 20439 // etc., it's used to specify the tab label, accordion pane title, etc. In this case it's 20440 // interpreted as HTML. 20441 title: "", 20442 20443 // tooltip: String 20444 // When this widget's title attribute is used to for a tab label, accordion pane title, etc., 20445 // this specifies the tooltip to appear when the mouse is hovered over that text. 20446 tooltip: "", 20447 20448 // baseClass: [protected] String 20449 // Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate 20450 // widget state. 20451 baseClass: "", 20452 20453 // srcNodeRef: [readonly] DomNode 20454 // pointer to original DOM node 20455 srcNodeRef: null, 20456 20457 // domNode: [readonly] DomNode 20458 // This is our visible representation of the widget! Other DOM 20459 // Nodes may by assigned to other properties, usually through the 20460 // template system's data-dojo-attach-point syntax, but the domNode 20461 // property is the canonical "top level" node in widget UI. 20462 domNode: null, 20463 20464 // containerNode: [readonly] DomNode 20465 // Designates where children of the source DOM node will be placed. 20466 // "Children" in this case refers to both DOM nodes and widgets. 20467 // For example, for myWidget: 20468 // 20469 // | <div data-dojo-type=myWidget> 20470 // | <b> here's a plain DOM node 20471 // | <span data-dojo-type=subWidget>and a widget</span> 20472 // | <i> and another plain DOM node </i> 20473 // | </div> 20474 // 20475 // containerNode would point to: 20476 // 20477 // | <b> here's a plain DOM node 20478 // | <span data-dojo-type=subWidget>and a widget</span> 20479 // | <i> and another plain DOM node </i> 20480 // 20481 // In templated widgets, "containerNode" is set via a 20482 // data-dojo-attach-point assignment. 20483 // 20484 // containerNode must be defined for any widget that accepts innerHTML 20485 // (like ContentPane or BorderContainer or even Button), and conversely 20486 // is null for widgets that don't, like TextBox. 20487 containerNode: null, 20488 20489 // ownerDocument: [const] Document? 20490 // The document this widget belongs to. If not specified to constructor, will default to 20491 // srcNodeRef.ownerDocument, or if no sourceRef specified, then to the document global 20492 ownerDocument: null, 20493 _setOwnerDocumentAttr: function(val){ 20494 // this setter is merely to avoid automatically trying to set this.domNode.ownerDocument 20495 this._set("ownerDocument", val); 20496 }, 20497 20498 /*===== 20499 // _started: [readonly] Boolean 20500 // startup() has completed. 20501 _started: false, 20502 =====*/ 20503 20504 // attributeMap: [protected] Object 20505 // Deprecated. Instead of attributeMap, widget should have a _setXXXAttr attribute 20506 // for each XXX attribute to be mapped to the DOM. 20507 // 20508 // attributeMap sets up a "binding" between attributes (aka properties) 20509 // of the widget and the widget's DOM. 20510 // Changes to widget attributes listed in attributeMap will be 20511 // reflected into the DOM. 20512 // 20513 // For example, calling set('title', 'hello') 20514 // on a TitlePane will automatically cause the TitlePane's DOM to update 20515 // with the new title. 20516 // 20517 // attributeMap is a hash where the key is an attribute of the widget, 20518 // and the value reflects a binding to a: 20519 // 20520 // - DOM node attribute 20521 // | focus: {node: "focusNode", type: "attribute"} 20522 // Maps this.focus to this.focusNode.focus 20523 // 20524 // - DOM node innerHTML 20525 // | title: { node: "titleNode", type: "innerHTML" } 20526 // Maps this.title to this.titleNode.innerHTML 20527 // 20528 // - DOM node innerText 20529 // | title: { node: "titleNode", type: "innerText" } 20530 // Maps this.title to this.titleNode.innerText 20531 // 20532 // - DOM node CSS class 20533 // | myClass: { node: "domNode", type: "class" } 20534 // Maps this.myClass to this.domNode.className 20535 // 20536 // If the value is an array, then each element in the array matches one of the 20537 // formats of the above list. 20538 // 20539 // There are also some shorthands for backwards compatibility: 20540 // 20541 // - string --> { node: string, type: "attribute" }, for example: 20542 // 20543 // | "focusNode" ---> { node: "focusNode", type: "attribute" } 20544 // 20545 // - "" --> { node: "domNode", type: "attribute" } 20546 attributeMap: {}, 20547 20548 // _blankGif: [protected] String 20549 // Path to a blank 1x1 image. 20550 // Used by `<img>` nodes in templates that really get their image via CSS background-image. 20551 _blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"), 20552 20553 //////////// INITIALIZATION METHODS /////////////////////////////////////// 20554 20555 /*=====
20556 constructor: function(params, srcNodeRef){ 20557 // summary: 20558 // Create the widget. 20559 // params: Object|null 20560 // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) 20561 // and functions, typically callbacks like onClick. 20562 // The hash can contain any of the widget's properties, excluding read-only properties. 20563 // srcNodeRef: DOMNode|String? 20564 // If a srcNodeRef (DOM node) is specified: 20565 // 20566 // - use srcNodeRef.innerHTML as my contents 20567 // - if this is a behavioral widget then apply behavior to that srcNodeRef 20568 // - otherwise, replace srcNodeRef with my generated DOM tree 20569 }, 20570 =====*/ 20571 20572 _introspect: function(){ 20573 // summary: 20574 // Collect metadata about this widget (only once per class, not once per instance): 20575 // 20576 // - list of attributes with custom setters, storing in this.constructor._setterAttrs 20577 // - generate this.constructor._onMap, mapping names like "mousedown" to functions like onMouseDown 20578 20579 var ctor = this.constructor; 20580 if(!ctor._setterAttrs){ 20581 var proto = ctor.prototype, 20582 attrs = ctor._setterAttrs = [], // attributes with custom setters 20583 onMap = (ctor._onMap = {}); 20584 20585 // Items in this.attributeMap are like custom setters. For back-compat, remove for 2.0. 20586 for(var name in proto.attributeMap){ 20587 attrs.push(name); 20588 } 20589 20590 // Loop over widget properties, collecting properties with custom setters and filling in ctor._onMap. 20591 for(name in proto){ 20592 if(/^on/.test(name)){ 20593 onMap[name.substring(2).toLowerCase()] = name; 20594 } 20595 20596 if(/^_set[A-Z](.*)Attr$/.test(name)){ 20597 name = name.charAt(4).toLowerCase() + name.substr(5, name.length - 9); 20598 if(!proto.attributeMap || !(name in proto.attributeMap)){ 20599 attrs.push(name); 20600 } 20601 } 20602 } 20603 20604 // Note: this isn't picking up info on properties like aria-label and role, that don't have custom setters 20605 // but that set() maps to attributes on this.domNode or this.focusNode 20606 } 20607 }, 20608 20609 postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){ 20610 // summary: 20611 // Kicks off widget instantiation. See create() for details. 20612 // tags: 20613 // private 20614 20615 // Note that we skip calling this.inherited(), i.e. dojo/Stateful::postscript(), because 1.x widgets don't 20616 // expect their custom setters to get called until after buildRendering(). Consider changing for 2.0. 20617 20618 this.create(params, srcNodeRef); 20619 }, 20620 20621 create: function(params, srcNodeRef){ 20622 // summary: 20623 // Kick off the life-cycle of a widget 20624 // description: 20625 // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate, 20626 // etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html 20627 // for a discussion of the widget creation lifecycle. 20628 // 20629 // Of course, adventurous developers could override create entirely, but this should 20630 // only be done as a last resort. 20631 // params: Object|null 20632 // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) 20633 // and functions, typically callbacks like onClick. 20634 // The hash can contain any of the widget's properties, excluding read-only properties. 20635 // srcNodeRef: DOMNode|String? 20636 // If a srcNodeRef (DOM node) is specified: 20637 // 20638 // - use srcNodeRef.innerHTML as my contents 20639 // - if this is a behavioral widget then apply behavior to that srcNodeRef 20640 // - otherwise, replace srcNodeRef with my generated DOM tree 20641 // tags: 20642 // private 20643 20644 // First time widget is instantiated, scan prototype to figure out info about custom setters etc. 20645 this._introspect(); 20646 20647 // store pointer to original DOM tree 20648 this.srcNodeRef = dom.byId(srcNodeRef); 20649 20650 // No longer used, remove for 2.0. 20651 this._connects = []; 20652 this._supportingWidgets = []; 20653 20654 // this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test) 20655 if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ 20656 this.id = this.srcNodeRef.id; 20657 } 20658 20659 // mix in our passed parameters 20660 if(params){ 20661 this.params = params; 20662 lang.mixin(this, params); 20663 } 20664 this.postMixInProperties(); 20665 20666 // Generate an id for the widget if one wasn't specified, or it was specified as id: undefined. 20667 // Do this before buildRendering() because it might expect the id to be there. 20668 if(!this.id){ 20669 this.id = registry.getUniqueId(this.declaredClass.replace(/\./g, "_"));
20670 if(this.params){ 20671 // if params contains {id: undefined}, prevent _applyAttributes() from processing it 20672 delete this.params.id; 20673 } 20674 } 20675 20676 // The document and <body> node this widget is associated with 20677 this.ownerDocument = this.ownerDocument || (this.srcNodeRef ? this.srcNodeRef.ownerDocument : document); 20678 this.ownerDocumentBody = win.body(this.ownerDocument); 20679 20680 registry.add(this); 20681 20682 this.buildRendering(); 20683 20684 var deleteSrcNodeRef; 20685 20686 if(this.domNode){ 20687 // Copy attributes listed in attributeMap into the [newly created] DOM for the widget. 20688 // Also calls custom setters for all attributes with custom setters. 20689 this._applyAttributes(); 20690 20691 // If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree. 20692 // For 2.0, move this after postCreate(). postCreate() shouldn't depend on the 20693 // widget being attached to the DOM since it isn't when a widget is created programmatically like 20694 // new MyWidget({}). See #11635. 20695 var source = this.srcNodeRef; 20696 if(source && source.parentNode && this.domNode !== source){ 20697 source.parentNode.replaceChild(this.domNode, source); 20698 deleteSrcNodeRef = true; 20699 } 20700 20701 // Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId", 20702 // assuming that dojo._scopeName even exists in 2.0 20703 this.domNode.setAttribute("widgetId", this.id); 20704 } 20705 this.postCreate(); 20706 20707 // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC. 20708 // I think for back-compatibility it isn't deleting srcNodeRef until after postCreate() has run. 20709 if(deleteSrcNodeRef){ 20710 delete this.srcNodeRef; 20711 } 20712 20713 this._created = true; 20714 }, 20715 20716 _applyAttributes: function(){ 20717 // summary: 20718 // Step during widget creation to copy widget attributes to the 20719 // DOM according to attributeMap and _setXXXAttr objects, and also to call 20720 // custom _setXXXAttr() methods. 20721 // 20722 // Skips over blank/false attribute values, unless they were explicitly specified 20723 // as parameters to the widget, since those are the default anyway, 20724 // and setting tabIndex="" is different than not setting tabIndex at all. 20725 // 20726 // For backwards-compatibility reasons attributeMap overrides _setXXXAttr when 20727 // _setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap. 20728 // tags: 20729 // private 20730 20731 // Call this.set() for each property that was either specified as parameter to constructor, 20732 // or is in the list found above. For correlated properties like value and displayedValue, the one 20733 // specified as a parameter should take precedence. 20734 // Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is 20735 // NaN and thus is not ignored like a default value of "". 20736 20737 // Step 1: Save the current values of the widget properties that were specified as parameters to the constructor. 20738 // Generally this.foo == this.params.foo, except if postMixInProperties() changed the value of this.foo. 20739 var params = {}; 20740 for(var key in this.params || {}){ 20741 params[key] = this._get(key); 20742 } 20743 20744 // Step 2: Call set() for each property with a non-falsy value that wasn't passed as a parameter to the constructor 20745 array.forEach(this.constructor._setterAttrs, function(key){ 20746 if(!(key in params)){ 20747 var val = this._get(key); 20748 if(val){ 20749 this.set(key, val); 20750 } 20751 } 20752 }, this); 20753 20754 // Step 3: Call set() for each property that was specified as parameter to constructor. 20755 // Use params hash created above to ignore side effects from step #2 above. 20756 for(key in params){ 20757 this.set(key, params[key]); 20758 } 20759 }, 20760 20761 postMixInProperties: function(){ 20762 // summary: 20763 // Called after the parameters to the widget have been read-in, 20764 // but before the widget template is instantiated. Especially 20765 // useful to set properties that are referenced in the widget 20766 // template. 20767 // tags: 20768 // protected 20769 }, 20770 20771 buildRendering: function(){ 20772 // summary: 20773 // Construct the UI for this widget, setting this.domNode. 20774 // Most widgets will mixin `dijit._TemplatedMixin`, which implements this method. 20775 // tags: 20776 // protected 20777 20778 if(!this.domNode){ 20779 // Create root node if it wasn't created by _TemplatedMixin 20780 this.domNode = this.srcNodeRef || this.ownerDocument.createElement("div"); 20781 } 20782 20783 // baseClass is a single class name or occasionally a space-separated list of names. 20784 // Add those classes to the DOMNode. If RTL mode then also add with Rtl suffix. 20785 // TODO: make baseClass custom setter 20786 if(this.baseClass){ 20787 var classes = this.baseClass.split(" "); 20788 if(!this.isLeftToRight()){ 20789 classes = classes.concat(array.map(classes, function(name){ 20790 return name + "Rtl"; 20791 })); 20792 } 20793 domClass.add(this.domNode, classes); 20794 } 20795 }, 20796 20797 postCreate: function(){ 20798 // summary: 20799 // Processing after the DOM fragment is created 20800 // description: 20801 // Called after the DOM fragment has been created, but not necessarily 20802 // added to the document. Do not include any operations which rely on 20803 // node dimensions or placement. 20804 // tags: 20805 // protected 20806 }, 20807 20808 startup: function(){ 20809 // summary: 20810 // Processing after the DOM fragment is added to the document 20811 // description: 20812 // Called after a widget and its children have been created and added to the page, 20813 // and all related widgets have finished their create() cycle, up through postCreate(). 20814 // 20815 // Note that startup() may be called while the widget is still hidden, for example if the widget is 20816 // inside a hidden dijit/Dialog or an unselected tab of a dijit/layout/TabContainer. 20817 // For widgets that need to do layout, it's best to put that layout code inside resize(), and then 20818 // extend dijit/layout/_LayoutWidget so that resize() is called when the widget is visible. 20819 if(this._started){ 20820 return; 20821 } 20822 this._started = true; 20823 array.forEach(this.getChildren(), function(obj){ 20824 if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ 20825 obj.startup(); 20826 obj._started = true; 20827 } 20828 }); 20829 }, 20830 20831 //////////// DESTROY FUNCTIONS //////////////////////////////// 20832 20833 destroyRecursive: function(/*Boolean?*/ preserveDom){ 20834 // summary:
20835 // Destroy this widget and its descendants 20836 // description: 20837 // This is the generic "destructor" function that all widget users 20838 // should call to cleanly discard with a widget. Once a widget is 20839 // destroyed, it is removed from the manager object. 20840 // preserveDom: 20841 // If true, this method will leave the original DOM structure 20842 // alone of descendant Widgets. Note: This will NOT work with 20843 // dijit._TemplatedMixin widgets. 20844 20845 this._beingDestroyed = true; 20846 this.destroyDescendants(preserveDom); 20847 this.destroy(preserveDom); 20848 }, 20849 20850 destroy: function(/*Boolean*/ preserveDom){ 20851 // summary: 20852 // Destroy this widget, but not its descendants. Descendants means widgets inside of 20853 // this.containerNode. Will also destroy any resources (including widgets) registered via this.own(). 20854 // 20855 // This method will also destroy internal widgets such as those created from a template, 20856 // assuming those widgets exist inside of this.domNode but outside of this.containerNode. 20857 // 20858 // For 2.0 it's planned that this method will also destroy descendant widgets, so apps should not 20859 // depend on the current ability to destroy a widget without destroying its descendants. Generally 20860 // they should use destroyRecursive() for widgets with children. 20861 // preserveDom: Boolean 20862 // If true, this method will leave the original DOM structure alone. 20863 // Note: This will not yet work with _TemplatedMixin widgets 20864 20865 this._beingDestroyed = true; 20866 this.uninitialize(); 20867 20868 function destroy(w){ 20869 if(w.destroyRecursive){ 20870 w.destroyRecursive(preserveDom); 20871 }else if(w.destroy){ 20872 w.destroy(preserveDom); 20873 } 20874 } 20875 20876 // Back-compat, remove for 2.0 20877 array.forEach(this._connects, lang.hitch(this, "disconnect")); 20878 array.forEach(this._supportingWidgets, destroy); 20879 20880 // Destroy supporting widgets, but not child widgets under this.containerNode (for 2.0, destroy child widgets 20881 // here too). if() statement is to guard against exception if destroy() called multiple times (see #15815). 20882 if(this.domNode){ 20883 array.forEach(registry.findWidgets(this.domNode, this.containerNode), destroy); 20884 } 20885 20886 this.destroyRendering(preserveDom); 20887 registry.remove(this.id); 20888 this._destroyed = true; 20889 }, 20890 20891 destroyRendering: function(/*Boolean?*/ preserveDom){ 20892 // summary: 20893 // Destroys the DOM nodes associated with this widget. 20894 // preserveDom: 20895 // If true, this method will leave the original DOM structure alone 20896 // during tear-down. Note: this will not work with _Templated 20897 // widgets yet. 20898 // tags: 20899 // protected 20900 20901 if(this.bgIframe){ 20902 this.bgIframe.destroy(preserveDom); 20903 delete this.bgIframe; 20904 } 20905 20906 if(this.domNode){ 20907 if(preserveDom){ 20908 domAttr.remove(this.domNode, "widgetId"); 20909 }else{ 20910 domConstruct.destroy(this.domNode); 20911 } 20912 delete this.domNode; 20913 } 20914 20915 if(this.srcNodeRef){ 20916 if(!preserveDom){ 20917 domConstruct.destroy(this.srcNodeRef); 20918 } 20919 delete this.srcNodeRef; 20920 } 20921 }, 20922 20923 destroyDescendants: function(/*Boolean?*/ preserveDom){ 20924 // summary: 20925 // Recursively destroy the children of this widget and their 20926 // descendants. 20927 // preserveDom: 20928 // If true, the preserveDom attribute is passed to all descendant 20929 // widget's .destroy() method. Not for use with _Templated 20930 // widgets. 20931 20932 // get all direct descendants and destroy them recursively 20933 array.forEach(this.getChildren(), function(widget){ 20934 if(widget.destroyRecursive){ 20935 widget.destroyRecursive(preserveDom); 20936 } 20937 }); 20938 }, 20939 20940 uninitialize: function(){ 20941 // summary: 20942 // Deprecated. Override destroy() instead to implement custom widget tear-down 20943 // behavior. 20944 // tags: 20945 // protected 20946 return false; 20947 }, 20948 20949 ////////////////// GET/SET, CUSTOM SETTERS, ETC. /////////////////// 20950 20951 _setStyleAttr: function(/*String||Object*/ value){ 20952 // summary: 20953 // Sets the style attribute of the widget according to value, 20954 // which is either a hash like {height: "5px", width: "3px"} 20955 // or a plain string 20956 // description: 20957 // Determines which node to set the style on based on style setting 20958 // in attributeMap. 20959 // tags: 20960 // protected 20961 20962 var mapNode = this.domNode; 20963 20964 // Note: technically we should revert any style setting made in a previous call 20965 // to his method, but that's difficult to keep track of. 20966 20967 if(lang.isObject(value)){ 20968 domStyle.set(mapNode, value); 20969 }else{ 20970 if(mapNode.style.cssText){ 20971 mapNode.style.cssText += "; " + value; 20972 }else{ 20973 mapNode.style.cssText = value; 20974 } 20975 } 20976 20977 this._set("style", value); 20978 }, 20979 20980 _attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){ 20981 // summary: 20982 // Reflect a widget attribute (title, tabIndex, duration etc.) to 20983 // the widget DOM, as specified by commands parameter. 20984 // If commands isn't specified then it's looked up from attributeMap. 20985 // Note some attributes like "type" 20986 // cannot be processed this way as they are not mutable. 20987 // attr: 20988 // Name of member variable (ex: "focusNode" maps to this.focusNode) pointing 20989 // to DOMNode inside the widget, or alternately pointing to a subwidget 20990 // tags: 20991 // private 20992 20993 commands = arguments.length >= 3 ? commands : this.attributeMap[attr]; 20994 20995 array.forEach(lang.isArray(commands) ? commands : [commands], function(command){ 20996 20997 // Get target node and what we are doing to that node 20998 var mapNode = this[command.node || command || "domNode"]; // DOM node 20999 var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute 21000 21001 switch(type){ 21002 case "attribute": 21003 if(lang.isFunction(value)){ // functions execute in the context of the widget 21004 value = lang.hitch(this, value); 21005 } 21006 21007 // Get the name of the DOM node attribute; usually it's the same 21008 // as the name of the attribute in the widget (attr), but can be overridden. 21009 // Also maps handler names to lowercase, like onSubmit --> onsubmit 21010 var attrName = command.attribute ? command.attribute : 21011 (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr); 21012 21013 if(mapNode.tagName){ 21014 // Normal case, mapping to a DOMNode. Note that modern browsers will have a mapNode.set() 21015 // method, but for consistency we still call domAttr 21016 domAttr.set(mapNode, attrName, value); 21017 }else{ 21018 // mapping to a sub-widget 21019 mapNode.set(attrName, value); 21020 } 21021 break; 21022 case "innerText": 21023 mapNode.innerHTML = ""; 21024 mapNode.appendChild(this.ownerDocument.createTextNode(value)); 21025 break; 21026 case "innerHTML": 21027 mapNode.innerHTML = value; 21028 break; 21029 case "class": 21030 domClass.replace(mapNode, value, this[attr]); 21031 break; 21032 } 21033 }, this); 21034 }, 21035 21036 get: function(name){ 21037 // summary: 21038 // Get a property from a widget. 21039 // name: 21040 // The property to get. 21041 // description: 21042 // Get a named property from a widget. The property may 21043 // potentially be retrieved via a getter method. If no getter is defined, this 21044 // just retrieves the object's property. 21045 // 21046 // For example, if the widget has properties `foo` and `bar`
21047 // and a method named `_getFooAttr()`, calling: 21048 // `myWidget.get("foo")` would be equivalent to calling 21049 // `widget._getFooAttr()` and `myWidget.get("bar")` 21050 // would be equivalent to the expression 21051 // `widget.bar2` 21052 var names = this._getAttrNames(name); 21053 return this[names.g] ? this[names.g]() : this._get(name); 21054 }, 21055 21056 set: function(name, value){ 21057 // summary: 21058 // Set a property on a widget 21059 // name: 21060 // The property to set. 21061 // value: 21062 // The value to set in the property. 21063 // description: 21064 // Sets named properties on a widget which may potentially be handled by a 21065 // setter in the widget. 21066 // 21067 // For example, if the widget has properties `foo` and `bar` 21068 // and a method named `_setFooAttr()`, calling 21069 // `myWidget.set("foo", "Howdy!")` would be equivalent to calling 21070 // `widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)` 21071 // would be equivalent to the statement `widget.bar = 3;` 21072 // 21073 // set() may also be called with a hash of name/value pairs, ex: 21074 // 21075 // | myWidget.set({ 21076 // | foo: "Howdy", 21077 // | bar: 3 21078 // | }); 21079 // 21080 // This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)` 21081 21082 if(typeof name === "object"){ 21083 for(var x in name){ 21084 this.set(x, name[x]); 21085 } 21086 return this; 21087 } 21088 var names = this._getAttrNames(name), 21089 setter = this[names.s]; 21090 if(lang.isFunction(setter)){ 21091 // use the explicit setter 21092 var result = setter.apply(this, Array.prototype.slice.call(arguments, 1)); 21093 }else{ 21094 // Mapping from widget attribute to DOMNode/subwidget attribute/value/etc. 21095 // Map according to: 21096 // 1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0) 21097 // 2. _setFooAttr: {...} type attribute in the widget (if one exists) 21098 // 3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick. 21099 // Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar 21100 // attribute name (ex: accept-charset attribute matches jsObject.acceptCharset). 21101 // Note also that Tree.focusNode() is a function not a DOMNode, so test for that. 21102 var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode", 21103 tag = this[defaultNode] && this[defaultNode].tagName, 21104 attrsForTag = tag && (tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode]))), 21105 map = name in this.attributeMap ? this.attributeMap[name] : 21106 names.s in this ? this[names.s] : 21107 ((attrsForTag && names.l in attrsForTag && typeof value != "function") || 21108 /^aria-|^data-|^role$/.test(name)) ? defaultNode : null; 21109 if(map != null){ 21110 this._attrToDom(name, value, map); 21111 } 21112 this._set(name, value); 21113 } 21114 return result || this; 21115 }, 21116 21117 _attrPairNames: {}, // shared between all widgets 21118 _getAttrNames: function(name){ 21119 // summary: 21120 // Helper function for get() and set(). 21121 // Caches attribute name values so we don't do the string ops every time. 21122 // tags: 21123 // private 21124 21125 var apn = this._attrPairNames; 21126 if(apn[name]){ 21127 return apn[name]; 21128 } 21129 var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ 21130 return c.charAt(c.length - 1).toUpperCase(); 21131 }); 21132 return (apn[name] = { 21133 n: name + "Node", 21134 s: "_set" + uc + "Attr", // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr 21135 g: "_get" + uc + "Attr", 21136 l: uc.toLowerCase() // lowercase name w/out dashes, ex: acceptcharset 21137 }); 21138 }, 21139 21140 _set: function(/*String*/ name, /*anything*/ value){ 21141 // summary: 21142 // Helper function to set new value for specified property, and call handlers 21143 // registered with watch() if the value has changed. 21144 var oldValue = this[name]; 21145 this[name] = value; 21146 if(this._created && !isEqual(oldValue, value)){ 21147 if(this._watchCallbacks){ 21148 this._watchCallbacks(name, oldValue, value); 21149 } 21150 this.emit("attrmodified-" + name, { 21151 detail: { 21152 prevValue: oldValue, 21153 newValue: value 21154 } 21155 }); 21156 } 21157 }, 21158 21159 _get: function(/*String*/ name){ 21160 // summary: 21161 // Helper function to get value for specified property stored by this._set(), 21162 // i.e. for properties with custom setters. Used mainly by custom getters. 21163 // 21164 // For example, CheckBox._getValueAttr() calls this._get("value"). 21165 21166 // future: return name in this.props ? this.props[name] : this[name]; 21167 return this[name]; 21168 }, 21169 21170 emit: function(/*String*/ type, /*Object?*/ eventObj, /*Array?*/ callbackArgs){ 21171 // summary: 21172 // Used by widgets to signal that a synthetic event occurred, ex: 21173 // | myWidget.emit("attrmodified-selectedChildWidget", {}). 21174 // 21175 // Emits an event on this.domNode named type.toLowerCase(), based on eventObj. 21176 // Also calls onType() method, if present, and returns value from that method. 21177 // By default passes eventObj to callback, but will pass callbackArgs instead, if specified. 21178 // Modifies eventObj by adding missing parameters (bubbles, c
21178ancelable, widget). 21179 // tags: 21180 // protected 21181 21182 // Specify fallback values for bubbles, cancelable in case they are not set in eventObj. 21183 // Also set pointer to widget, although since we can't add a pointer to the widget for native events 21184 // (see #14729), maybe we shouldn't do it here? 21185 eventObj = eventObj || {}; 21186 if(eventObj.bubbles === undefined){ 21187 eventObj.bubbles = true; 21188 } 21189 if(eventObj.cancelable === undefined){ 21190 eventObj.cancelable = true; 21191 } 21192 if(!eventObj.detail){ 21193 eventObj.detail = {}; 21194 } 21195 eventObj.detail.widget = this; 21196 21197 var ret, callback = this["on" + type]; 21198 if(callback){ 21199 ret = callback.apply(this, callbackArgs ? callbackArgs : [eventObj]); 21200 } 21201 21202 // Emit event, but avoid spurious emit()'s as parent sets properties on child during startup/destroy 21203 if(this._started && !this._beingDestroyed){ 21204 on.emit(this.domNode, type.toLowerCase(), eventObj); 21205 } 21206 21207 return ret; 21208 }, 21209 21210 on: function(/*String|Function*/ type, /*Function*/ func){ 21211 // summary: 21212 // Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }). 21213 // type: 21214 // Name of event (ex: "click") or extension event like touch.press. 21215 // description: 21216 // Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`. 21217 // Note that the function is not run in any particular scope, so if (for example) you want it to run in the 21218 // widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`. 21219 21220 // For backwards compatibility, if there's an onType() method in the widget then connect to that. 21221 // Remove in 2.0. 21222 var widgetMethod = this._onMap(type); 21223 if(widgetMethod){ 21224 return aspect.after(this, widgetMethod, func, true); 21225 } 21226 21227 // Otherwise, just listen for the event on this.domNode. 21228 return this.own(on(this.domNode, type, func))[0]; 21229 }, 21230 21231 _onMap: function(/*String|Function*/ type){ 21232 // summary: 21233 // Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove"). 21234 // If type is a synthetic event like touch.press then returns undefined. 21235 var ctor = this.constructor, map = ctor._onMap; 21236 if(!map){ 21237 map = (ctor._onMap = {}); 21238 for(var attr in ctor.prototype){ 21239 if(/^on/.test(attr)){ 21240 map[attr.replace(/^on/, "").toLowerCase()] = attr; 21241 } 21242 } 21243 } 21244 return map[typeof type == "string" && type.toLowerCase()]; // String 21245 }, 21246 21247 toString: function(){ 21248 // summary: 21249 // Returns a string that represents the widget. 21250 // description: 21251 // When a widget is cast to a string, this method will be used to generate the 21252 // output. Currently, it does not implement any sort of reversible 21253 // serialization. 21254 return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String 21255 }, 21256 21257 getChildren: function(){ 21258 // summary: 21259 // Returns all direct children of this widget, i.e. all widgets underneath this.containerNode whose parent 21260 // is this widget. Note that it does not return all descendants, but rather just direct children. 21261 // Analogous to [Node.childNodes](https://developer.mozilla.org/en-US/docs/DOM/Node.childNodes), 21262 // except containing widgets rather than DOMNodes. 21263 // 21264 // The result intentionally excludes internally created widgets (a.k.a. supporting widgets) 21265 // outside of this.containerNode. 21266 // 21267 // Note that the array returned is a simple array. Application code should not assume 21268 // existence of methods like forEach(). 21269 21270 return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit/_WidgetBase[] 21271 }, 21272 21273 getParent: function(){ 21274 // summary: 21275 // Returns the parent widget of this widget. 21276 21277 return registry.getEnclosingWidget(this.domNode.parentNode); 21278 }, 21279 21280 connect: function(/*Object|null*/ obj, /*String|Function*/ event, /*String|Function*/ method){ 21281 // summary: 21282 // Deprecated, will be removed in 2.0, use this.own(on(...)) or this.own(aspect.after(...)) instead. 21283 // 21284 // Connects specified obj/event to specified method of this object 21285 // and registers for disconnect() on widget destroy. 21286 // 21287 // Provide widget-specific analog to dojo.connect, except with the 21288 // implicit use of this widget as the target object. 21289 // Events connected with `this.connect` are disconnected upon 21290 // destruction. 21291 // returns: 21292 // A handle that can be passed to `disconnect` in order to disconnect before 21293 // the widget is destroyed. 21294 // example: 21295 // | var btn = new Button(); 21296 // | // when foo.bar() is called, call the listener we're going to 21297 // | // provide in the scope of btn 21298 // | btn.connect(foo, "bar", function(){ 21299 // | console.debug(this.toString()); 21300 // | }); 21301 // tags: 21302 // protected 21303 21304 return this.own(connect.connect(obj, event, this, method))[0]; // handle 21305 }, 21306 21307 disconnect: function(handle){ 21308 // summary: 21309 // Deprecated, will be removed in 2.0, use handle.remove() instead. 21310 // 21311 // Disconnects handle created by `connect`. 21312 // tags: 21313 // protected 21314 21315 handle.remove(); 21316 }, 21317 21318 subscribe: function(t, method){ 21319 // summary: 21320 // Deprecated, will be removed in 2.0, use this.own(topic.subscribe()) instead. 21321 // 21322 // Subscribes to the specified topic and calls the specified method 21323 // of this object and registers for unsubscribe() on widget destroy. 21324 // 21325 // Provide widget-specific analog to dojo.subscribe, except with the 21326 // implicit use of this widget as the target object. 21327 // t: String 21328 // The topic 21329 // method: Function 21330 // The callback 21331 // example: 21332 // | var btn = new Button(); 21333 // | // when /my/topic is published, this button changes its label to 21334 // | // be the parameter of the topic. 21335 // | btn.subscribe("/my/topic", function(v){ 21336 // | this.set("label", v); 21337 // | }); 21338 // tags: 21339 // protected 21340 return this.own(topic.subscribe(t, lang.hitch(this, method)))[
213400]; // handle 21341 }, 21342 21343 unsubscribe: function(/*Object*/ handle){ 21344 // summary: 21345 // Deprecated, will be removed in 2.0, use handle.remove() instead. 21346 // 21347 // Unsubscribes handle created by this.subscribe. 21348 // Also removes handle from this widget's list of subscriptions 21349 // tags: 21350 // protected 21351 21352 handle.remove(); 21353 }, 21354 21355 isLeftToRight: function(){ 21356 // summary: 21357 // Return this widget's explicit or implicit orientation (true for LTR, false for RTL) 21358 // tags: 21359 // protected 21360 return this.dir ? (this.dir.toLowerCase() == "ltr") : domGeometry.isBodyLtr(this.ownerDocument); //Boolean 21361 }, 21362 21363 isFocusable: function(){ 21364 // summary: 21365 // Return true if this widget can currently be focused 21366 // and false if not 21367 return this.focus && (domStyle.get(this.domNode, "display") != "none"); 21368 }, 21369 21370 placeAt: function(/*String|DomNode|DocumentFragment|dijit/_WidgetBase*/ reference, /*String|Int?*/ position){ 21371 // summary: 21372 // Place this widget somewhere in the DOM based 21373 // on standard domConstruct.place() conventions. 21374 // description: 21375 // A convenience function provided in all _Widgets, providing a simple 21376 // shorthand mechanism to put an existing (or newly created) Widget 21377 // somewhere in the dom, and allow chaining. 21378 // reference: 21379 // Widget, DOMNode, DocumentFragment, or id of widget or DOMNode 21380 // position: 21381 // If reference is a widget (or id of widget), and that widget has an ".addChild" method, 21382 // it will be called passing this widget instance into that method, supplying the optional 21383 // position index passed. In this case position (if specified) should be an integer. 21384 // 21385 // If reference is a DOMNode (or id matching a DOMNode but not a widget), 21386 // the position argument can be a numeric index or a string 21387 // "first", "last", "before", or "after", same as dojo/dom-construct::place(). 21388 // returns: dijit/_WidgetBase 21389 // Provides a useful return of the newly created dijit._Widget instance so you 21390 // can "chain" this function by instantiating, placing, then saving the return value 21391 // to a variable. 21392 // example: 21393 // | // create a Button with no srcNodeRef, and place it in the body: 21394 // | var button = new Button({ label:"click" }).placeAt(win.body()); 21395 // | // now, 'button' is still the widget reference to the newly created button 21396 // | button.on("click", function(e){ console.log('click'); })); 21397 // example: 21398 // | // create a button out of a node with id="src" and append it to id="wrapper": 21399 // | var button = new Button({},"src").placeAt("wrapper"); 21400 // example: 21401 // | // place a new button as the first element of some div 21402 // | var button = new Button({ label:"click" }).placeAt("wrapper","first"); 21403 // example: 21404 // | // create a contentpane and add it to a TabContainer 21405 // | var tc = dijit.byId("myTabs"); 21406 // | new ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc) 21407 21408 var refWidget = !reference.tagName && registry.byId(reference); 21409 if(refWidget && refWidget.addChild && (!position || typeof position === "number")){ 21410 // Adding this to refWidget and can use refWidget.addChild() to handle everything. 21411 refWidget.addChild(this, position); 21412 }else{ 21413 // "reference" is a plain DOMNode, or we can't use refWidget.addChild(). Use domConstruct.place() and 21414 // target refWidget.containerNode for nested placement (position==number, "first", "last", "only"), and 21415 // refWidget.domNode otherwise ("after"/"before"/"replace"). (But not supported officially, see #14946.) 21416 var ref = refWidget && ("domNode" in refWidget) ? 21417 (refWidget.containerNode && !/after|before|replace/.test(position || "") ? 21418 refWidget.containerNode : refWidget.domNode) : dom.byId(reference, this.ownerDocument); 21419 domConstruct.place(this.domNode, ref, position); 21420 21421 // Start this iff it has a parent widget that's already started. 21422 // TODO: for 2.0 maybe it should also start the widget when this.getParent() returns null?? 21423 if(!this._started && (this.getParent() || {})._started){ 21424 this.startup(); 21425 } 21426 } 21427 return this; 21428 }, 21429 21430 defer: function(fcn, delay){ 21431 // summary: 21432 // Wrapper to setTimeout to avoid deferred functions executing 21433 // after the originating widget has been destroyed. 21434 // Returns an object handle with a remove method (that returns null) (replaces clearTimeout). 21435 // fcn: Function 21436 // Function reference. 21437 // delay: Number? 21438 // Delay, defaults to 0. 21439 // tags: 21440 // protected 21441 21442 var timer = setTimeout(lang.hitch(this, 21443 function(){ 21444 if(!timer){
21445 return; 21446 } 21447 timer = null; 21448 if(!this._destroyed){ 21449 lang.hitch(this, fcn)(); 21450 } 21451 }), 21452 delay || 0 21453 ); 21454 return { 21455 remove: function(){ 21456 if(timer){ 21457 clearTimeout(timer); 21458 timer = null; 21459 } 21460 return null; // so this works well: handle = handle.remove(); 21461 } 21462 }; 21463 } 21464 }); 21465 21466 if(has("dojo-bidi")){ 21467 _WidgetBase.extend(_BidiMixin); 21468 } 21469 21470 return _WidgetBase; 21471}); 21472 21473}, 21474'dojo/Stateful':function(){ 21475define(["./_base/declare", "./_base/lang", "./_base/array", "./when"], function(declare, lang, array, when){ 21476 // module: 21477 // dojo/Stateful 21478 21479return declare("dojo.Stateful", null, { 21480 // summary: 21481 // Base class for objects that provide named properties with optional getter/setter 21482 // control and the ability to watch for property changes 21483 // 21484 // The class also provides the functionality to auto-magically manage getters 21485 // and setters for object attributes/properties. 21486 // 21487 // Getters and Setters should follow the format of _xxxGetter or _xxxSetter where 21488 // the xxx is a name of the attribute to handle. So an attribute of "foo" 21489 // would have a custom getter of _fooGetter and a custom setter of _fooSetter. 21490 // 21491 // example: 21492 // | require(["dojo/Stateful", function(Stateful) { 21493 // | var obj = new Stateful(); 21494 // | obj.watch("foo", function(){ 21495 // | console.log("foo changed to " + this.get("foo")); 21496 // | }); 21497 // | obj.set("foo","bar"); 21498 // | }); 21499 21500 // _attrPairNames: Hash 21501 // Used across all instances a hash to cache attribute names and their getter 21502 // and setter names. 21503 _attrPairNames: {}, 21504 21505 _getAttrNames: function(name){ 21506 // summary: 21507 // Helper function for get() and set(). 21508 // Caches attribute name values so we don't do the string ops every time. 21509 // tags: 21510 // private 21511 21512 var apn = this._attrPairNames; 21513 if(apn[name]){ return apn[name]; } 21514 return (apn[name] = { 21515 s: "_" + name + "Setter", 21516 g: "_" + name + "Getter" 21517 }); 21518 }, 21519 21520 postscript: function(/*Object?*/ params){ 21521 // Automatic setting of params during construction 21522 if (params){ this.set(params); } 21523 }, 21524 21525 _get: function(name, names){ 21526 // summary: 21527 // Private function that does a get based off a hash of names 21528 // names: 21529 // Hash of names of custom attributes 21530 return typeof this[names.g] === "function" ? this[names.g]() : this[name]; 21531 }, 21532 get: function(/*String*/name){ 21533 // summary: 21534 // Get a property on a Stateful instance. 21535 // name: 21536 // The property to get. 21537 // returns: 21538 // The property value on this Stateful instance. 21539 // description: 21540 // Get a named property on a Stateful object. The property may 21541 // potentially be retrieved via a getter method in subclasses. In the base class 21542 // this just retrieves the object's property. 21543 // example: 21544 // | require(["dojo/Stateful", function(Stateful) { 21545 // | var stateful = new Stateful({foo: 3}); 21546 // | stateful.get("foo") // returns 3 21547 // | stateful.foo // returns 3 21548 // | }); 21549 21550 return this._get(name, this._getAttrNames(name)); //Any 21551 }, 21552 set: function(/*String*/name, /*Object*/value){ 21553 // summary: 21554 // Set a property on a Stateful instance 21555 // name: 21556 // The property to set. 21557 // value: 21558 // The value to set in the property. 21559 // returns: 21560 // The function returns this dojo.Stateful instance. 21561 // description: 21562 // Sets named properties on a stateful object and notifies any watchers of 21563 // the property. A programmatic setter may be defined in subclasses. 21564 // example: 21565 // | require(["dojo/Stateful", function(Stateful) { 21566 // | var stateful = new Stateful(); 21567 // | stateful.watch(function(name, oldValue, value){ 21568 // | // this will be called on the set below 21569 // | } 21570 // | stateful.set(foo, 5); 21571 // set() may also be called with a hash of name/value pairs, ex: 21572 // | stateful.set({ 21573 // | foo: "Howdy", 21574 // | bar: 3 21575 // | }); 21576 // | }); 21577 // This is equivalent to calling set(foo, "Howdy") and set(bar, 3) 21578 21579 // If an object is used, iterate through object 21580 if(typeof name === "object"){ 21581 for(var x in name){ 21582 if(name.hasOwnProperty(x) && x !="_watchCallbacks"){ 21583 this.set(x, name[x]); 21584 } 21585 } 21586 return this; 21587 } 21588 21589 var names = this._getAttrNames(name), 21590 oldValue = this._get(name, names), 21591 setter = this[names.s], 21592 result; 21593 if(typeof setter === "function"){ 21594 // use the explicit setter 21595 result = setter.apply(this, Array.prototype.slice.call(arguments, 1)); 21596 }else{ 21597 // no setter so set attribute directly 21598 this[name] = value; 21599 } 21600 if(this._watchCallbacks){ 21601 var self = this; 21602 // If setter returned a promise, wait for it to complete, otherwise call watches immediately 21603 when(result, function(){ 21604 self._watchCallbacks(name, oldValue, value); 21605 }); 21606 } 21607 return this; // dojo/Stateful 21608 }, 21609 _changeAttrValue: function(name, value){ 21610 // summary: 21611 // Internal helper for directly changing an attribute value. 21612 // 21613 // name: String 21614 // The property to set. 21615 // value: Mixed 21616 // The value to set in the property. 21617 // 21618 // description: 21619 // Directly change the value of an attribute on an object, bypassing any 21620 // accessor setter. Also handles the calling of watch and emitting events. 21621 // It is designed to be used by descendant class when there are two values 21622 // of attributes that are linked, but calling .set() is not appropriate. 21623 21624 var oldValue = this.get(name); 21625 this[name] = value; 21626 if(this._watchCallbacks){ 21627 this._watchCallbacks(name, oldValue, value); 21628 } 21629 return this; // dojo/Stateful 21630 }, 21631 watch: function(/*String?*/name, /*Function*/callback){ 21632 // summary: 21633 // Watches a property for changes 21634 // name:
21635 // Indicates the property to watch. This is optional (the callback may be the 21636 // only parameter), and if omitted, all the properties will be watched 21637 // returns: 21638 // An object handle for the watch. The unwatch method of this object 21639 // can be used to discontinue watching this property: 21640 // | var watchHandle = obj.watch("foo", callback); 21641 // | watchHandle.unwatch(); // callback won't be called now 21642 // callback: 21643 // The function to execute when the property changes. This will be called after 21644 // the property has been changed. The callback will be called with the |this| 21645 // set to the instance, the first argument as the name of the property, the 21646 // second argument as the old value and the third argument as the new value. 21647 21648 var callbacks = this._watchCallbacks; 21649 if(!callbacks){ 21650 var self = this; 21651 callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){ 21652 var notify = function(propertyCallbacks){ 21653 if(propertyCallbacks){ 21654 propertyCallbacks = propertyCallbacks.slice(); 21655 for(var i = 0, l = propertyCallbacks.length; i < l; i++){ 21656 propertyCallbacks[i].call(self, name, oldValue, value); 21657 } 21658 } 21659 }; 21660 notify(callbacks['_' + name]); 21661 if(!ignoreCatchall){ 21662 notify(callbacks["*"]); // the catch-all 21663 } 21664 }; // we use a function instead of an object so it will be ignored by JSON conversion 21665 } 21666 if(!callback && typeof name === "function"){ 21667 callback = name; 21668 name = "*"; 21669 }else{ 21670 // prepend with dash to prevent name conflicts with function (like "name" property) 21671 name = '_' + name; 21672 } 21673 var propertyCallbacks = callbacks[name]; 21674 if(typeof propertyCallbacks !== "object"){ 21675 propertyCallbacks = callbacks[name] = []; 21676 } 21677 propertyCallbacks.push(callback); 21678 21679 // TODO: Remove unwatch in 2.0 21680 var handle = {}; 21681 handle.unwatch = handle.remove = function(){ 21682 var index = array.indexOf(propertyCallbacks, callback); 21683 if(index > -1){ 21684 propertyCallbacks.splice(index, 1); 21685 } 21686 }; 21687 return handle; //Object 21688 } 21689 21690}); 21691 21692}); 21693 21694}, 21695'dijit/Destroyable':function(){ 21696define([ 21697 "dojo/_base/array", // array.forEach array.map 21698 "dojo/aspect", 21699 "dojo/_base/declare" 21700], function(array, aspect, declare){ 21701 21702 // module: 21703 // dijit/Destroyable 21704 21705 return declare("dijit.Destroyable", null, { 21706 // summary: 21707 // Mixin to track handles and release them when instance is destroyed. 21708 // description: 21709 // Call this.own(...) on list of handles (returned from dojo/aspect, dojo/on, 21710 // dojo/Stateful::watch, or any class (including widgets) with a destroyRecursive() or destroy() method. 21711 // Then call destroy() later to destroy this instance and release the resources. 21712 21713 destroy: function(/*Boolean*/ preserveDom){ 21714 // summary: 21715 // Destroy this class, releasing any resources registered via own(). 21716 this._destroyed = true; 21717 }, 21718 21719 own: function(){ 21720 // summary: 21721 // Track specified handles and remove/destroy them when this instance is destroyed, unless they were 21722 // already removed/destroyed manually. 21723 // tags: 21724 // protected 21725 // returns: 21726 // The array of specified handles, so you can do for example: 21727 // | var handle = this.own(on(...))[0]; 21728 21729 var cleanupMethods = [ 21730 "destroyRecursive", 21731 "destroy", 21732 "remove" 21733 ]; 21734 21735 array.forEach(arguments, function(handle){ 21736 // When this.destroy() is called, destroy handle. Since I'm using aspect.before(), 21737 // the handle will be destroyed before a subclass's destroy() method starts running, before it calls 21738 // this.inherited() or even if it doesn't call this.inherited() at all. If that's an issue, make an 21739 // onDestroy() method and connect to that instead. 21740 var destroyMethodName; 21741 var odh = aspect.before(this, "destroy", function (preserveDom){ 21742 handle[destroyMethodName](preserveDom); 21743 }); 21744 21745 // Callback for when handle is manually destroyed. 21746 var hdhs = []; 21747 function onManualDestroy(){ 21748 odh.remove(); 21749 array.forEach(hdhs, function(hdh){ 21750 hdh.remove(); 21751 });
21752 } 21753 21754 // Setup listeners for manual destroy of handle. 21755 // Also computes destroyMethodName, used in listener above. 21756 if(handle.then){ 21757 // Special path for Promises. Detect when Promise is resolved, rejected, or 21758 // canceled (nb: cancelling a Promise causes it to be rejected). 21759 destroyMethodName = "cancel"; 21760 handle.then(onManualDestroy, onManualDestroy); 21761 }else{ 21762 // Path for other handles. Just use AOP to detect when handle is manually destroyed. 21763 array.forEach(cleanupMethods, function(cleanupMethod){ 21764 if(typeof handle[cleanupMethod] === "function"){ 21765 if(!destroyMethodName){ 21766 // Use first matching method name in above listener (prefer destroyRecursive() to destroy()) 21767 destroyMethodName = cleanupMethod; 21768 } 21769 hdhs.push(aspect.after(handle, cleanupMethod, onManualDestroy, true)); 21770 } 21771 }); 21772 } 21773 }, this); 21774 21775 return arguments; // handle 21776 } 21777 }); 21778}); 21779 21780}, 21781'dijit/registry':function(){ 21782define([ 21783 "dojo/_base/array", // array.forEach array.map 21784 "dojo/_base/window", // win.body 21785 "./main" // dijit._scopeName 21786], function(array, win, dijit){ 21787 21788 // module: 21789 // dijit/registry 21790 21791 var _widgetTypeCtr = {}, hash = {}; 21792 21793 var registry = { 21794 // summary: 21795 // Registry of existing widget on page, plus some utility methods. 21796 21797 // length: Number 21798 // Number of registered widgets 21799 length: 0, 21800 21801 add: function(widget){ 21802 // summary: 21803 // Add a widget to the registry. If a duplicate ID is detected, a error is thrown. 21804 // widget: dijit/_WidgetBase 21805 // Any dijit/_WidgetBase subclass. 21806 if(hash[widget.id]){ 21807 throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered"); 21808 } 21809 hash[widget.id] = widget; 21810 this.length++; 21811 }, 21812 21813 remove: function(/*String*/ id){ 21814 // summary: 21815 // Remove a widget from the registry. Does not destroy the widget; simply 21816 // removes the reference. 21817 if(hash[id]){ 21818 delete hash[id]; 21819 this.length--; 21820 } 21821 }, 21822 21823 byId: function(/*String|Widget*/ id){ 21824 // summary: 21825 // Find a widget by it's id. 21826 // If passed a widget then just returns the widget. 21827 return typeof id == "string" ? hash[id] : id; // dijit/_WidgetBase 21828 }, 21829 21830 byNode: function(/*DOMNode*/ node){ 21831 // summary: 21832 // Returns the widget corresponding to the given DOMNode 21833 return hash[node.getAttribute("widgetId")]; // dijit/_WidgetBase 21834 }, 21835 21836 toArray: function(){ 21837 // summary: 21838 // Convert registry into a true Array 21839 // 21840 // example: 21841 // Work with the widget .domNodes in a real Array 21842 // | array.map(registry.toArray(), function(w){ return w.domNode; }); 21843 21844 var ar = []; 21845 for(var id in hash){ 21846 ar.push(hash[id]); 21847 } 21848 return ar; // dijit/_WidgetBase[] 21849 }, 21850 21851 getUniqueId: function(/*String*/widgetType){ 21852 // summary: 21853 // Generates a unique id for a given widgetType 21854 21855 var id; 21856 do{ 21857 id = widgetType + "_" + 21858 (widgetType in _widgetTypeCtr ? 21859 ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0); 21860 }while(hash[id]); 21861 return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String 21862 }, 21863 21864 findWidgets: function(root, skipNode){ 21865 // summary: 21866 // Search subtree under root returning widgets found. 21867 // Doesn't search for nested widgets (ie, widgets inside other widgets). 21868 // root: DOMNode 21869 // Node to search under. 21870 // skipNode: DOMNode 21871 // If specified, don't search beneath this node (usually containerNode). 21872 21873 var outAry = []; 21874 21875 function getChildrenHelper(root){ 21876 for(var node = root.firstChild; node; node = node.nextSibling){ 21877 if(node.nodeType == 1){ 21878 var widgetId = node.getAttribute("widgetId"); 21879 if(widgetId){ 21880 var widget = hash[widgetId]; 21881 if(widget){ // may be null on page w/multiple dojo's loaded 21882 outAry.push(widget); 21883 } 21884 }else if(node !== skipNode){ 21885 getChildrenHelper(node); 21886 } 21887 } 21888 } 21889 } 21890 21891 getChildrenHelper(root); 21892 return outAry; 21893 }, 21894 21895 _destroyAll: function(){ 21896 // summary: 21897 // Code to destroy all widgets and do other cleanup on page unload 21898 21899 // Clean up focus manager lingering references to widgets and nodes 21900 dijit._curFocus = null; 21901 dijit._prevFocus = null; 21902 dijit._activeStack = []; 21903 21904 // Destroy all the widgets, top down 21905 array.forEach(registry.findWidgets(win.body()), function(widget){ 21906 // Avoid double destroy of widgets like Menu that are attached to <body> 21907 // even though they are logically children of other widgets. 21908 if(!widget._destroyed){ 21909 if(widget.destroyRecursive){ 21910 widget.destroyRecursive(); 21911 }else if(widget.destroy){ 21912 widget.destroy(); 21913 } 21914 } 21915 }); 21916 }, 21917 21918 getEnclosingWidget: function(/*DOMNode*/ node){ 21919 // summary: 21920 // Returns the widget whose DOM tree contains the specified DOMNode, or null if 21921 // the node is not contained within the DOM tree of any widget 21922 while(node){ 21923 var id = node.nodeType == 1 && node.getAttribute("widgetId"); 21924 if(id){ 21925 return hash[id]; 21926 } 21927 node = node.parentNode; 21928 } 21929 return null; 21930 }, 21931 21932 // In case someone needs to access hash. 21933 // Actually, this is accessed from WidgetSet back-compatibility code 21934 _hash: hash 21935 }; 21936 21937 dijit.registry = registry; 21938 21939 return registry; 21940}); 21941 21942}, 21943'dijit/main':function(){ 21944define([ 21945 "dojo/_base/kernel" 21946], function(dojo){ 21947 // module: 21948 // dijit/main 21949 21950/*===== 21951return { 21952 // summary: 21953 // The dijit package main module. 21954 // Deprecated. Users should access individual modules (ex: dijit/registry) directly. 21955}; 21956=====*/ 21957 21958 return dojo.dijit; 21959}); 21960 21961}, 21962'dpage/widgets/AlertValidationMessage':function(){ 21963define([ 21964 "dojo/_base/event" 21965 ,"dojo/on" 21966 ,"dojo/dom-attr" 21967 ,"dojo/dom-class" 21968 ,"dojo/mouse" 21969 ,"dojo/dom-geometry" 21970 , "dojo/dom-style" 21971 , "dojo/json" 21972 21973 , "dojo/request/xhr"
21974 ,"dojox/html/entities" 21975 ,"dojo/_base/declare" 21976 , "dpage/widgets/ValidationMessage"], 21977function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 21978 /** 21979 * @namespace dpage 21980 */ 21981 /** 21982 * @namespace widgets 21983 * @memberOf dpage 21984 */ 21985 /** 21986 * Implementation of a ValidationMessage that pops up an alert dialog. 21987 * @class AlertValidationMessage 21988 * @param {Object} [options] Optional options for the widget. 21989 * @param {String} [options.dataField] The field (column name) this widget is bound to. 21990 21991 * @param {dpage.modules.TabularModel} [options.model] The model to use. 21992 * @param {dpage.widgets.Container} [options.container] The container of the widget. 21993 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 21994 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 21995 * is created. 21996 * @param {Object} [containerNode] Optional container node to tie the widget to. 21997 * @memberOf dpage.widgets 21998 * @extends {dpage.widgets.ValidationMessage} 21999 */ 22000 return dojo.declare("dpage.widgets.AlertValidationMessage", [dpage.widgets.ValidationMessage], /** @lends dpage.widgets.AlertValidationMessage.prototype */ { 22001 _containerNode : null 22002 22003 ,constructor : function(options , srcNodeRef) 22004 { 22005 var self = this; 22006 this._containerNode = srcNodeRef; 22007 }, 22008 22009 _updateView : function(){ 22010 var errors = this._errors; 22011 var ul; 22012 var strErrors = []; 22013 22014 //set up the data. 22015 this.inherited(arguments); 22016 22017 if (errors.length > 0) { 22018 for (var idx = 0; idx < errors.length ; idx++) { 22019 var obj = errors[idx]; 22020 22021 strErrors.push(obj.message); 22022 } 22023 22024 alert(strErrors.join("\n")); 22025 } 22026 } 22027 }); 22028}); 22029 22030}, 22031'dpage/widgets/ValidationMessage':function(){ 22032define([ 22033 "dojo/_base/event" 22034 ,"dojo/on" 22035 ,"dojo/dom-attr" 22036 ,"dojo/dom-class" 22037 ,"dojo/dom-geometry" 22038 , "dojo/dom-style" 22039 , "dojo/json" 22040 22041 , "dojo/request/xhr" 22042 ,"dojox/html/entities" 22043 ,"dojo/_base/declare" 22044 , "dpage/widgets/MultiValueWidget"], 22045function (event, on, domAttr, domClass, domGeom, style, json) { 22046 /** 22047 * @namespace dpage 22048 */ 22049 /** 22050 * @namespace widgets 22051 * @memberOf dpage 22052 */ 22053 /** 22054 * Abstract base class for all ValidationMessage widgets. 22055 * @class ValidationMessage 22056 * @param {Object} [options] Optional options for the widget. 22057 * @param {String} [options.dataField] The field (column name) this widget is bound to. 22058 22059 * @param {dpage.modules.TabularModel} [options.model] The model to use. 22060 * @param {dpage.widgets.Container} [options.container] The container of the widget. 22061 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 22062 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 22063 * is created. 22064 * @param {Object} [containerNode] Optional container node to tie the widget to. 22065 * @memberOf dpage.widgets 22066 * @extends {dpage.widgets.MultiValueWidget} 22067 */ 22068 return dojo.declare("dpage.widgets.ValidationMessage", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.ValidationMessage.prototype */ { 22069 _containerNode : null 22070 ,_dataField : null 22071 , _errors : null 22072 22073 ,constructor : function(options , srcNodeRef) 22074 { 22075 this._errors = []; 22076 if (options == null || options.dataField == null) { 22077 this._dataField = "default";//default column name for an empty model. 22078 } 22079 else 22080 this._dataField = options.dataField; 22081 }, 22082 templateString: "<div></div>", 22083 postCreate: function () 22084 { 22085 if(this.getContainer() != null) 22086 this.getContainer().setValidationMessageWidget(this); 22087 22088 return this.inherited(arguments); 22089 }, 22090 setContainer : function() 22091 { 22092 //call base method. 22093 this.inherited(arguments); 22094 this.getContainer().setValidationMessageWidget(this); 22095 }, 22096 /** 22097 * Clear the error message. Will update the underlying model. 22098 * @returns {void} 22099 */ 22100 clearError: function () 22101 { 22102 //this will cause the _updateView() method to be called. 22103 this.getModel().clear(); 22104 }, 22105 /** 22106 * Set the list of errors. Clears out any errors that may currently be set. Will update the underlying model. 22107 * @param {Array} errors Array of error Objects. 22108 * @param {String} errors.message The message of the error. 22109 * @param {Number} [errors.widgetId] The widgetId the error is tied to. 22110 * @returns {void} 22111 */ 22112 setError: function (errors) { 22113 this._errors = errors; 22114 var modelRows = []; 22115 22116 for (var i = 0; i < errors.length; i++) 22117 { 22118 var modelRow = {}; 22119 modelRow[this._dataField] = errors[i].message; 22120 22121 modelRows.push(modelRow); 22122 //keep track of the row. 22123 errors[i].modelRow = modelRow; 22124 } 22125 22126 //causes the control to re-render (_updateView). 22127 this.getModel().setRows(modelRows); 22128 }, 22129 /** 22130 * Removes the error for a widgetId. Will update the underlying model. 22131 * @param {Number} widgetID Numeric widget id. 22132 * @returns {void} 22133 */ 22134 removeErrorByWidgetID: function (widgetID) { 22135 for (var i = this._errors.length; i-- > 0;) { 22136 if (this._errors[i].widgetId === widgetID) { 22137 this.getModel().deleteRow(this._errors[i].modelRow); 22138 } 22139 } 22140 }, 22141 //Gets called whenever the model changes on us. 22142 _updateView: function () 22143 { 22144 var oldErrors = this._errors; 22145 this._errors = []; 22146 22147 if(this.getModel() != null) 22148 { 22149 for(var idx = 0; idx<this.getModel().getRows().length;idx++) 22150 { 22151 var errorObj = { message: this.getModel().getValue(idx, this._dataField) , modelRow : this.getModel().getRows()[idx] }; 22152 22153 //find the old error so we can hook up the correct widgetId. 22154 for (var i = 0; i < oldErrors.length; i++) 22155 { 22156 if (oldErrors[i].widgetId != null 22157 && dpage.modules.TabularModel.isSameRow(oldErrors[i].modelRow, this.getModel().getRows()[idx])) 22158 { 22159 errorObj.widgetId = oldErrors[i].widgetId; 22160 break; 22161 } 22162 } 22163 this._errors.push(errorObj); 22164 } 22165 } 22166 }, 22167 setModel : function() 22168 { 22169 this.inherited(arguments); 22170 this._updateView(); 22171 } 22172 }); 22173}); 22174 22175}, 22176'dpage/widgets/MultiValueWidget':function(){ 22177define([ 22178 "dojo/_base/event" 22179 ,"dojo/on" 22180 ,"dojo/dom-attr" 22181 ,"dojo/dom-class" 22182 ,"dojo/dom-geometry" 22183 , "dojo/dom-style" 22184 , "dojo/json" 22185 22186 , "dpage/modules/TabularModel" 22187 , "dojo/request/xhr"
22188 ,"dojox/html/entities" 22189 ,"dojo/_base/declare" 22190 , "dpage/widgets/BaseWidget"], 22191function (event, on, domAttr, domClass, domGeom, style, json) { 22192 /** 22193 * @namespace dpage 22194 */ 22195 /** 22196 * @namespace widgets 22197 * @memberOf dpage 22198 */ 22199 /** 22200 * Base class for all widgets intended to display multiple values, such as multi-select controls or Tables of data. 22201 * @class MultiValueWidget 22202 * @param {Object} [options] Optional options for the widget. 22203 * @param {dpage.modules.TabularModel} [options.model] The model to use. 22204 * @param {dpage.widgets.Container} [options.container] The container of the widget. 22205 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 22206 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 22207 * is created. 22208 * @param {Object} [containerNode] Optional container node to tie the widget to. 22209 * @memberOf dpage.widgets 22210 * @extends {dpage.widgets.BaseWidget} 22211 */ 22212 return dojo.declare("dpage.widgets.MultiValueWidget", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.MultiValueWidget.prototype */ { 22213 _doDataSubscriptions: true, 22214 _dataCallbackId: null, 22215 _model: null, 22216 22217 constructor : function(options , srcNodeRef) 22218 { 22219 var self = this; 22220 this._containerNode = srcNodeRef; 22221 22222 //if there is no model, create a blank one. 22223 if (options == null || options.model == null) { 22224 this._model = new dpage.modules.TabularModel(); 22225 } 22226 22227 if (options != null) { 22228 if (options.model != null) { 22229 if (options.model.isInstanceOf == null || !options.model.isInstanceOf(dpage.modules.TabularModel)) 22230 throw new Error("model must be a dpage.widgets.TabularModel for widget id = " + this.getWidgetId()); 22231 else 22232 this._model = options.model; 22233 } 22234 } 22235 22236 if(this._model != null) 22237 this._dataCallbackId = this._model.addDataCallback(function (type, rowObj, dataField) { self._modelChangedCallback(type, rowObj, dataField); }, this._dataRow); 22238 22239 }, 22240 templateString: "<div></div>", 22241 /** 22242 * Get the TabularModel. 22243 * @returns {dpage.modules.TabularModel} 22244 */ 22245 getModel : function() 22246 { 22247 return this._model; 22248 }, 22249 /** 22250 * Set the model for the MultiValueWidget 22251 * @param {dpage.modules.TabularModel} model The model to set. 22252 * @returns {void} 22253 */ 22254 setModel : function(model) 22255 { 22256 var self = this; 22257 22258 if (this._dataCallbackId != null) 22259 this.getModel().removeDataCallback(this._dataCallbackId); 22260 22261 if (model.isInstanceOf == null || !model.isInstanceOf(dpage.modules.TabularModel)) 22262 throw new Error("model must be a dpage.modules.TabularModel for widget id = " + this.getWidgetId()); 22263 22264 this._model = model; 22265 22266 this._dataCallbackId = this._model.addDataCallback(function (type, rowObj, dataField) { self._modelChangedCallback(type, rowObj, dataField); }, this._dataRow); 22267 }, 22268 /** 22269 * Sets the value in the model without causing the control to re-render. 22270 * @param {Object} dataRow The row to set the value in. 22271 * @param {String} dataField The dataField in the row to set the value of. 22272 * @param {Object} value The value to set (String/bool/Number, etc). 22273 * @returns {void} 22274 */ 22275 setModelValue: function (dataRow , dataField , value) { 22276 var oldS = this.isSubscribedToModelChanges(); 22277 22278 if (oldS) 22279 this.setDataSubscriptions(false); 22280 22281 this.getModel().setValue(dataRow , dataField , value); 22282 22283 this.setDataSubscriptions(oldS); 22284 }, 22285 /** 22286 * Is this widget responding to changes to the model or not. 22287 * @returns {bool} 22288 */ 22289 isSubscribedToModelChanges: function () { 22290 return this._doDataSubscriptions; 22291 }, 22292 /** 22293 * Call this method to turn data subscriptions on or off. If off, the widget will not respond to updates on the model. 22294 * @param {bool} trueOrFalse Do data subscriptions or don't 22295 * @returns {void} 22296 */ 22297 setDataSubscriptions: function (trueOrFalse) { 22298 this._doDataSubscriptions = trueOrFalse; 22299 }, 22300 //called after the data gets added 22301 _modelChangedCallback: function (type, rowObj, dataField) { 22302 if (this._doDataSubscriptions) { 22303 this._modelChanged(type, rowObj, dataField); 22304 } 22305 }, 22306 /* 22307 * Can be overridden to listen to events on the Model. 22308 * @param {String} type CHANGE|ADD|DEL|INS|INVALIDATE 22309 * @param {Object} rowObj The row of data that was altered 22310 * @param {String} dataField The column of data that was changed. 22311 * @returns {void} 22312 */ 22313 _modelChanged: function (type, rowObj, dataField) { 22314 this._updateView(); 22315 }, 22316 destroy: function () { 22317 //so we will get garbage collected correctly. 22318 this._model.removeDataCallback(this._dataCallbackId); 22319 this.inherited(arguments); 22320 } 22321 }); 22322}); 22323 22324}, 22325'dpage/widgets/Button':function(){ 22326define([ 22327 "dojo/_base/event" 22328 ,"dojo/on" 22329 ,"dojo/dom-attr" 22330 ,"dojo/dom-class" 22331 ,"dojo/mouse" 22332 ,"dojo/dom-geometry" 22333 , "dojo/dom-style" 22334 , "dojo/json" 22335 22336 , "dojo/request/xhr"
22337 ,"dojox/html/entities" 22338 ,"dojo/_base/declare" 22339 , "dpage/widgets/SingleValueWidget"], 22340function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 22341 /** 22342 * @namespace dpage 22343 */ 22344 /** 22345 * @namespace widgets 22346 * @memberOf dpage 22347 */ 22348 /** 22349 * Class to encapulate the functionality of a <button> element. Has added benifits over the native button. For instance, if you include a native <button> element inside of a form without 22350 * the type attribute set to "button", clicking the button will submit a form in some browsers. If you turn your native button elements into dpage.widgets.Button you don't have to remember about this browser quirk. 22351 * @class Button 22352 * @param {Object} [options] Optional options for the widget. 22353 * @param {Function} [options.onClick] callback for click. The callback function will be called with a single parameter with 2 properties (event , and widget). The event property is a reference 22354 * to the click event. The widget property is a reference to the widget that the event was triggered on. 22355 * @param {String} [options.text] The button text. 22356 22357 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 22358 * @param {dpage.widgets.Container} [options.container] The container of the widget. 22359 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 22360 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 22361 * is created. 22362 * @param {Object} [containerNode] Optional container node to tie the widget to. 22363 * @memberOf dpage.widgets 22364 * @extends {dpage.widgets.SingleValueWidget} 22365 */ 22366 return dojo.declare("dpage.widgets.Button", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Button.prototype */ { 22367 _containerNode: null, 22368 22369 constructor: function (options, srcNodeRef) 22370 { 22371 var self = this; 22372 this._containerNode = srcNodeRef; 22373 22374 if (this._containerNode == null) { 22375 this._containerNode = document.createElement("BUTTON"); 22376 } 22377 22378 if (this._containerNode.nodeName != "BUTTON" && this._containerNode.nodeName != "A") 22379 { 22380 if(this._containerNode.nodeName != "INPUT" && domAttr.get(this._containerNode, "type") != "SUBMIT") 22381 throw new Error("Source node for widgets.Button must be a BUTTON or an A or INPUT[type=submit]."); 22382 } 22383 22384 if (this._containerNode.nodeName == "BUTTON") 22385 { 22386 //to prevent the button from submitting forms if it is contained within a form. 22387 domAttr.set(this._containerNode, "type", "button"); 22388 } 22389 22390 if(options != null) 22391 { 22392 if (options.onClick != null) 22393 this.on("click", options.onClick); 22394 if (options.text != null) 22395 this._containerNode.innerHTML = dojox.html.entities.encode(options.text); 22396 } 22397 22398 }, 22399 templateString: "<div></div>", 22400 /** 22401 * Set an event handler. 22402 * @param {String} eventName The event to bind to. Only supported events are "click". 22403 * @param {function} functionRef The callback function to call. 22404 * @returns {void} 22405 */ 22406 on : function(eventName , functionRef) 22407 { 22408 var self = this; 22409 22410 if (eventName != "click") 22411 throw new Error("Supported events are: 'click'."); 22412 22413 on(this._containerNode, eventName, function(evt){functionRef({event:evt , widget : self})}); 22414 }, 22415 /** 22416 * Enable or disable the widget for user interaction. 22417 * @param {bool} val A value of true will enable the widget, a value of false will disable the widget. 22418 * @returns {void} 22419 */ 22420 setEnabled: function (val) 22421 { 22422 this.domNode.disabled = !val; 22423 } 22424 22425 }); 22426}); 22427 22428}, 22429'dpage/widgets/CheckBox':function(){ 22430define([ 22431 "dojo/_base/event" 22432 ,"dojo/on" 22433 ,"dojo/dom-attr" 22434 ,"dojo/dom-class" 22435 ,"dojo/mouse" 22436 ,"dojo/dom-geometry" 22437 , "dojo/dom-style" 22438 , "dojo/json" 22439 22440 , "dpage/modules/TabularModel" 22441 , "dojo/request/xhr"
22442 ,"dojox/html/entities" 22443 ,"dojo/_base/declare" 22444 , "dpage/widgets/SingleValueWidget"], 22445function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 22446 /** 22447 * @namespace dpage 22448 */ 22449 /** 22450 * @namespace widgets 22451 * @memberOf dpage 22452 */ 22453 /** 22454 * Class to encapulate the functionality of a <input type="check"> element. To manipulate the value, change the value in the model. The 22455 * CheckBox is aware of changes to the model and will update accordingly. 22456 * @class CheckBox 22457 * @param {Object} [options] Optional options for the widget. 22458 * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input. 22459 22460 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 22461 * @param {dpage.widgets.Container} [options.container] The container of the widget. 22462 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 22463 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 22464 * is created. 22465 * @param {Object} [containerNode] Optional container node to tie the widget to. 22466 * @memberOf dpage.widgets 22467 * @extends {dpage.widgets.SingleValueWidget} 22468 */ 22469 return dojo.declare("dpage.widgets.CheckBox", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.CheckBox.prototype */ { 22470 _containerNode: null, 22471 _onChange : null, 22472 constructor: function (options, srcNodeRef) 22473 { 22474 var self = this; 22475 this._containerNode = srcNodeRef; 22476 var dataIndex = 0; 22477 22478 this._onChange = []; 22479 if (this._containerNode == null) { 22480 this._containerNode = document.createElement("INPUT"); 22481 domAttr.set(this._containerNode, "type", "checkbox"); 22482 } 22483 22484 if (options != null) { 22485 if (options.onChange != null) { 22486 this.on("change", options.onChange); 22487 } 22488 } 22489 22490 if (this._containerNode.nodeName != "INPUT") 22491 throw new Error("Source node for widgets.CheckBox must be an INPUT type='checkbox'"); 22492 22493 on(this._containerNode, "click", function () { self._input_OnChange(event); }); 22494 }, 22495 postCreate: function () { 22496 //default to unchecked if we were not passed a model. 22497 if (this.isModelDefault()) 22498 this.setModelValue(false); 22499 //render the control. 22500 this._updateView(); 22501 return this.inherited(arguments); 22502 }, 22503 setModel: function (model, dataIndex) { 22504 this.inherited(arguments); 22505 22506 if (!this.isModelDefault() && this._dataType != "BOOL") 22507 throw new Error("Checkbox: " + this.getWidgetId() + ". The model datatype for a CheckBox must be BOOL. The datatype on this column is: " + this._dataType); 22508 22509 this._updateView(); 22510 }, 22511 _updateView : function() 22512 { 22513 //update the value in the checkbox. 22514 this._containerNode.checked = this.getModel().getValue(); 22515 }, 22516 _input_OnChange: function (evt) 22517 { 22518 var controlVal; 22519 var self = this; 22520 22521 if (this.validate() == null) { 22522 //set the value in the model. 22523 controlVal = this._containerNode.checked; 22524 this.setModelValue(controlVal); 22525 } 22526 22527 //call callbacks in order. 22528 for (var i = 0; i < this._onChange.length; i++) 22529 this._onChange[i]({ event: evt, widget: self }); 22530 22531 }, 22532 templateString: "<div></div>", 22533 /** 22534 * Set an event handler. 22535 * @param {String} eventName The event to bind to. Only supported events are "change". 22536 * @param {function} functionRef The callback function to call. 22537 * @returns {void} 22538 */ 22539 on: function (eventName, functionRef) { 22540 var self = this; 22541 22542 if (eventName != "change") 22543 throw new Error("Supported events are: 'change'."); 22544 22545 this._onChange.push(functionRef); 22546 } 22547 22548 }); 22549}); 22550 22551}, 22552'dpage/widgets/ClickToEditTextBox':function(){ 22553define([ 22554 "dojo/_base/event" 22555 ,"dojo/on" 22556 ,"dojo/dom-attr" 22557 ,"dojo/dom-class" 22558 ,"dojo/mouse" 22559 ,"dojo/dom-geometry" 22560 , "dojo/dom-style" 22561 , "dojo/json" 22562 22563 , "dpage/widgets/Anchor" 22564 , "xstyle/css!dpage/widgets/TextBox.css" 22565 , "dpage/modules/LegacyPlaceholder" 22566 , "dpage/modules/TabularModel" 22567 , "dojo/request/xhr"
22568 ,"dojox/html/entities" 22569 ,"dojo/_base/declare" 22570 , "dpage/widgets/SingleValueWidget"], 22571function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 22572 /** 22573 * @namespace dpage 22574 */ 22575 /** 22576 * @namespace widgets 22577 * @memberOf dpage 22578 */ 22579 /** 22580 * This class is to provide a widget that displays data like a Label, but allows you to edit the data like a TextBox. 22581 * @class ClickToEditTextBox 22582 * @param {Object} [options] Optional options for the widget. 22583 * @param {Number} [options.minTextBoxWidth] Default 40px. Minimum width for texbox. By default this widget sizes the textbox to the size of the area the label occupies. 22584 * If the label has a blank value, it would make it hard to edit the value unless we had a minimum width. 22585 * @param {bool} [options.styleTextBoxBorder] Default true. If true, the border is removed on the textbox. 22586 * @param {bool} [options.styleTextBoxMargin] Default true. If true, the margin is removed on the textbox. 22587 * @param {bool} [options.styleTextBoxPadding] Default true. If true, the padding is removed on the textbox. 22588 * @param {bool} [options.styleTextBoxOutline] Default true. If true, the outline is removed on the textbox. 22589 * @param {bool} [options.styleTextBoxFont] Default true. If true, attempt to style the textbox font to the same font as the label. 22590 * @param {bool} [options.styleTextBoxSize] Default true. If true, the textBox is sized to fit the content of the label. 22591 22592 * @param {String} [options.placeHolder] Optional placeholder text. Backwards compatible on browsers that don't natively support this attribute. 22593 * @param {Function} [options.formatter] string options.formatter(rawValue). Function to call for formatting the text. The formatter will be used 22594 * to set the value of the input when the input is non-focused. When the input is focused, 22595 * the raw value from the model will be shown. This function returns the value to display in the textbox. 22596 * @param {Function} [options.editFormatter] string options.formatter(rawValue). Function to call for formatting the text when the TextBox is focused. 22597 * The formatter will be used 22598 * to set the value of the input when the input is focused. 22599 * @param {Function} [options.inputFilter] string options.inputFilter(rawValue). This function will be called to return the value that is saved to the model. 22600 * Default behavior is to store the value the user types into the TextBox to the model. Passing in this function overrides 22601 * this behavior. 22602 * The function is passed the raw value that the user types into the textbox. The function will return the value 22603 * to store in the model. This function only operates on user input and is meant to be used to coerce different forms of user 22604 * input to the correct model value. 22605 * @param {bool} [options.highlightOnFocus] Default false. Highlight the text when the input is focused. 22606 * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input. 22607 22608 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 22609 * @param {dpage.widgets.Container} [options.container] The container of the widget. 22610 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 22611 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 22612 * is created. 22613 * @param {Object} [containerNode] Optional container node to tie the widget to. The only valid nodes are <input type='text'> and LABEL 22614 * @memberOf dpage.widgets 22615 * @extends {dpage.widgets.SingleValueWidget} 22616 */ 22617 return dojo.declare("dpage.widgets.ClickToEditTextBox", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.ClickToEditTextBox.prototype */ { 22618 _hrefWidget: null, 22619 _tbWidget: null, 22620 _minTextBoxWidth: 40, 22621 _containsPlaceholder: false, 22622 _styleTextBoxBorder : true, 22623 _styleTextBoxPadding : true, 22624 _styleTextBoxMargin : true, 22625 _styleTextBoxOutline : true, 22626 _styleTextBoxSize: true, 22627 _styleTextBoxFont:true, 22628 22629 constructor : function(options , srcNodeRef) 22630 { 22631 var self = this; 22632 var labelText = null; 22633 var model; 22634 22635 if (srcNodeRef == null) 22636 this._containerNode = document.createElement("SPAN"); 22637 else 22638 this._containerNode = srcNodeRef; 22639 22640 if(options != null) 22641 { 22642 if(options.minTextBoxWidth != null) 22643 this._minTextBoxWidth = options.minTextBoxWidth; 22644 if (options.styleTextBoxBorder !== undefined) { 22645 this._styleTextBoxBorder = options.styleTextBoxBorder; 22646 } 22647 if (options.styleTextBoxPadding !== undefined) { 22648 this._styleTextBoxPadding = options.styleTextBoxPadding; 22649 } 22650 if (options.styleTextBoxMargin !== undefined) { 22651 this._styleTextBoxMargin = options.styleTextBoxMargin; 22652 } 22653 if (options.styleTextBoxOutline !== undefined) { 22654 this._styleTextBoxOutline = options.styleTextBoxOutline; 22655 } 22656 if (options.styleTextBoxBorder !== undefined) { 22657 this._styleTextBoxSize = options.styleTextBoxSize; 22658 } 22659 if (options.styleTextBoxFont !== undefined) { 22660 this._styleTextBoxFont = options.styleTextBoxFont; 22661 } 22662 } 22663 22664 if (srcNodeRef != null) { 22665 if (srcNodeRef.nodeName == "LABEL" | srcNodeRef.nodeName == "DIV" || srcNodeRef.nodeName == "SPAN") { 22666 labelText = srcNodeRef.innerHTML; 22667 } 22668 else { 22669 throw new Error("The only support node types for a dpage.widgets.ClickToEditTextBox are label, span, or div"); 22670 } 22671 } 22672 22673 this._tbWidget = new dpage.widgets.TextBox(options); 22674 22675 this._hrefWidget = new dpage.widgets.Anchor({ disableClick: true });
22676 22677 if (options != null && options.model != null) 22678 this._hrefWidget.setModel(options.model); 22679 //textbox was already supplied the model in the constructor along with all other options. 22680 else { 22681 if (labelText != null) { 22682 this._hrefWidget.setValue(labelText); 22683 } 22684 this._tbWidget.setModel(this._hrefWidget.getModel()); 22685 } 22686 22687 if (this._tbWidget.getValue() == "") 22688 { 22689 this._containsPlaceholder = true; 22690 this._tbWidget.setValue(" "); 22691 } 22692 22693 var s = getComputedStyle(this._containerNode); 22694 22695 this._hrefWidget.getDomNode().style.color = s.color; 22696 this._hrefWidget.getDomNode().style.textDecoration = s.textDecoration; 22697 this._hrefWidget.getDomNode().style.font = s.font; 22698 this._hrefWidget.getDomNode().style.fontFamily = s.fontFamily; 22699 this._hrefWidget.getDomNode().style.fontSize = s.fontSize; 22700 22701 if (this._styleTextBoxFont) { 22702 this._tbWidget.getDomNode().style.color = s.color; 22703 this._tbWidget.getDomNode().style.textDecoration = s.textDecoration; 22704 this._tbWidget.getDomNode().style.font = s.font; 22705 this._tbWidget.getDomNode().style.fontFamily = s.fontFamily; 22706 this._tbWidget.getDomNode().style.fontSize = s.fontSize; 22707 } 22708 22709 this._tbWidget.getDomNode().style.display = "none"; 22710 this._containerNode.innerHTML = ""; 22711 this._containerNode.appendChild(this._tbWidget.getDomNode()); 22712 this._containerNode.appendChild(this._hrefWidget.getDomNode()); 22713 22714 on(this._tbWidget.getDomNode(), "blur", function (event) { self.tbNode_OnBlur(event); }); 22715 this._hrefWidget.on("click", function (obj) { self.href_OnClick(obj); }); 22716 on(this._hrefWidget.getDomNode(), "focus", function (obj) { self.href_OnClick(obj); }); 22717 }, 22718 href_OnClick: function (obj) { 22719 22720 if (this._styleTextBoxSize) { 22721 var coords = domGeom.getContentBox(this._hrefWidget.getDomNode()); 22722 if (coords.w < this._minTextBoxWidth) 22723 coords.w = this._minTextBoxWidth; 22724 if (this._containsPlaceholder) 22725 this._tbWidget.setValue(""); 22726 this._tbWidget.getDomNode().style.width = coords.w + "px"; 22727 if (coords.h != 0) 22728 this._tbWidget.getDomNode().style.height = coords.h + "px"; 22729 } 22730 22731 if(this._styleTextBoxBorder) 22732 this._tbWidget.getDomNode().style.border = "0px"; 22733 if(this._styleTextBoxMargin) 22734 this._tbWidget.getDomNode().style.margin = "0px"; 22735 if(this._styleTextBoxPadding) 22736 this._tbWidget.getDomNode().style.padding = "0px"; 22737 22738 this._tbWidget.getDomNode().style.display = "inline"; 22739 22740 if(this._styleTextBoxOutline) 22741 this._tbWidget.getDomNode().style.outline = "none"; 22742 22743 this._hrefWidget.getDomNode().style.display = "none"; 22744 this._tbWidget.getDomNode().focus(); 22745 }, 22746 tbNode_OnBlur: function (event) { 22747 if (this._tbWidget.getValue() == "") { 22748 this._containsPlaceholder = true; 22749 this._tbWidget.setValue(" "); 22750 } 22751 else 22752 this._containsPlaceholder = false; 22753 22754 this._tbWidget.getDomNode().style.display = "none"; 22755 this._hrefWidget.getDomNode().style.display = ""; 22756 } 22757 }); 22758}); 22759 22760}, 22761'xstyle/css':function(){ 22762define(["require"], function(moduleRequire){ 22763"use strict"; 22764/* 22765 * AMD css! plugin 22766 * This plugin will load and wait for css files. This allows JavaScript resources to 22767 * fully there dependencies on stylesheets. This can also be used when 22768 * loading css files as part of a layer or as a way to apply a run-time theme. This 22769 * module checks to see if the CSS is already loaded before incurring the cost 22770 * of loading the full CSS loader codebase 22771 */ 22772 function testElementStyle(tag, id, property){ 22773 // test an element's style 22774 var docElement = document.documentElement; 22775 var testDiv = docElement.insertBefore(document.createElement(tag), docElement.firstChild); 22776 testDiv.id = id; 22777 var styleValue = (testDiv.currentStyle || getComputedStyle(testDiv, null) || {})[property]; 22778 docElement.removeChild(testDiv); 22779 return styleValue; 22780 } 22781 return { 22782 load: function(resourceDef, require, callback, config) { 22783 var url = require.toUrl(resourceDef); 22784 var options; 22785 if(url.match(/!$/)){ 22786 // a final ! can be used to indicate not to wait for the stylesheet to load 22787 options = { 22788 wait: false 22789 }; 22790 url = url.slice(0, -1); 22791 } 22792 var cachedCss = require.cache && require.cache['url:' + url]; 22793 if(cachedCss){ 22794 // we have CSS cached inline in the build 22795 if(cachedCss.xCss){ 22796 var parser = cachedCss.parser; 22797 var xCss =cachedCss.xCss;
22798 cachedCss = cachedCss.cssText; 22799 } 22800 moduleRequire(['./core/load-css'],function(load){ 22801 checkForParser(load.insertCss(cachedCss)); 22802 }); 22803 if(xCss){ 22804 //require([parsed], callback); 22805 } 22806 return; 22807 } 22808 function checkForParser(styleSheetElement){ 22809 var parser = testElementStyle('x-parse', null, 'content'); 22810 var sheet = styleSheetElement && 22811 (styleSheetElement.sheet || styleSheetElement.styleSheet); 22812 if(parser && parser != 'none' && parser != 'normal'){ 22813 // TODO: wait for parser to load 22814 require([eval(parser)], function(parser){ 22815 if(styleSheetElement){ 22816 parser.process(styleSheetElement, callback); 22817 }else{ 22818 parser.processAll(); 22819 callback(sheet); 22820 } 22821 }); 22822 }else{ 22823 callback(sheet); 22824 } 22825 } 22826 22827 // if there is an id test available, see if the referenced rule is already loaded, 22828 // and if so we can completely avoid any dynamic CSS loading. If it is 22829 // not present, we need to use the dynamic CSS loader. 22830 var displayStyle = testElementStyle('div', resourceDef.replace(/\//g,'-').replace(/\..*/,'') + "-loaded", 'display'); 22831 if(displayStyle == "none"){ 22832 return checkForParser(); 22833 } 22834 // use dynamic loader 22835 moduleRequire(["./core/load-css"], function(load){ 22836 load(url, checkForParser, options); 22837 }); 22838 } 22839 }; 22840}); 22841 22842}, 22843'dpage/widgets/Container':function(){ 22844/// <reference path="ExpandCollapse.js" /> 22845define([ 22846 "dojo/_base/declare" 22847 , "dojo/on" 22848 , "dojo/_base/event" 22849 , "dojo/json" 22850 22851 , "dpage/modules/SingleValueModel" 22852 , "dpage/modules/TabularModel" 22853 , "dpage/modules/Model" 22854 , "dpage/widgets/BaseWidget" 22855 , "dojox/widget/Standby" 22856 , "dojo/parser" 22857], 22858 function (declare, on, event, json) { 22859 /** 22860 * @namespace dpage 22861 */ 22862 /** 22863 * @namespace widgets 22864 * @memberOf dpage 22865 */ 22866 /** 22867 * Class to contain methods common to all Containers. A container is a concept of a UI widget that contains 22868 * other UI widgets. These can be a {@link dpage.widgets.Page} which encapulates all the javascript for the entire browser window. 22869 * A container could be a {@link dpage.widgets.Dialog} widget that contains widgets, or a Container could be a widget representing a partial view 22870 * of a Page or Dialog. The model is a javascript object that should contain the data for child widgets. At the moment, widgets can be bound to an instance of 22871 * {@link dpage.widgets.SingleValueWidget} or {@link dpage.widgets.MultiValueWidget}. 22872 * @class Container 22873 * @param {Object} [options] Optional options for the widget. 22874 * @param {Object} [options.model] Data destined for Container child controls. 22875 * @param {bool} [options.modelTransform] Default false. If true, parse the model as if it contains meta-data. If false, don't bother parsing. Use it as-is. 22876 * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady. 22877 * @param {function} [options.widgetsParsedCallback] widgetsParsedCallback(referenceToTheContainer). callback function for when widgets in this container are parsed. 22878 * a reference to the container is passed into this function. 22879 * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided 22880 * markup. As with all containers, the markup can contain widgets that can be accessed through 22881 * getWidget() or getWidgets(). 22882 * @param {String} [options.templatePath] Optional server URI that contains the template. If provided, the Container will make a request to the 22883 * specified server path that contains the template. The container will then instantiate a container with the provided 22884 * markup. As with all containers, the markup can contain widgets that can be accessed through 22885 * getWidget() or getWidgets(). 22886 * @param {dpage.widgets.Container} [options.container] The container of the widget. 22887 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 22888 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 22889 * is created. 22890 * @param {Object} [containerNode] Optional container node to tie the widget to. 22891 * @memberOf dpage.widgets 22892 * @extends {dpage.widgets.BaseWidget} 22893 */ 22894 var theClass = declare("dpage.widgets.Container", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.Container.prototype */ { 22895 _widgets: null, 22896 _widgetContainer: null, 22897 _validationMessageWidget: null, 22898 _overlay: null, 22899 _containerNode: null, 22900 _model: null, 22901 _depsLoading: 0, //used by the parser. 22902 _doneParsing: false, 22903 _widgetsParsedCallback: null, 22904 _parseNow: true, 22905 _modelTransform : false, 22906 22907 constructor: function (options, containerNode) { 22908 var self = this; 22909 var nodeInnerHTML; 22910 22911 this._widgets = []; 22912 this._containerNode = containerNode; 22913 22914 if (this._containerNode == null) 22915 { 22916 this._containerNode = document.createElement("SPAN"); 22917 } 22918 22919 if (options != null) { 22920 22921 if (options.widgetsParsedCallback != null) 22922 { 22923 this._widgetsParsedCallback = options.widgetsParsedCallback; 22924 } 22925 22926 if (options.parseNow != undefined && options.parseNow == false) 22927 this._parseNow = false; 22928 22929 if (options.templateString) 22930 this.templateString = options.templateString; 22931 22932 else if (options.templatePath) { 22933 this.templatePath = options.templatePath; 22934 } 22935 else { 22936 this.templateString = ""; 22937 this.templatePath = ""; 22938 } 22939 22940 if (options.modelTransform != undefined && options.modelTransform == true) 22941 this._modelTransform = true; 22942 22943 //a PageModel 22944 if (options.model != null) 22945 this.setModel(options.model , this._modelTransform); 22946 22947 //a page can have a container too. 22948 if (options.container != null) 22949 this._widgetContainer = options.container; 22950 } 22951 }, 22952 22953 _widgetsParsed : function(){ 22954 if(this._widgetsParsedCallback) 22955 this._widgetsParsedCallback(this); 22956 22957 //call method that user can override. 22958 this.widgetsParsed(); 22959 }, 22960 /**Called after the parser finishes. All widgets in the Container will be available at this point. 22961 * Override this method to hook up events and such to widgets. 22962 * @returns {void} 22963 */ 22964 widgetsParsed: function () { 22965 22966 22967 }, 22968 22969 //called after a child widget is parsed. 22970 _decrementDepCount : function() 22971 { 22972 --this._depsLoading; 22973 22974 if (this._depsLoading == 0 22975 && this._doneParsing) 22976 { 22977 this._widgetsParsed(); 22978 22979 if (this._widgetContainer != null) { 22980 this._widgetContainer._decrementDepCount(); 22981 } 22982 } 22983 }, 22984 22985 parseContent : function() 22986 { 22987 var self = this; 22988 22989 if (this.templateString != null 22990 && this.templateString.length > 0) 22991 { 22992 this._containerNode.innerHTML = this.templateString; 22993 this._parseContent(this, this._containerNode); 22994 } 22995 else if (this.templatePath != null 22996 && this.templatePath.length > 0) 22997 { 22998 require(["dojo/text!" + this.templatePath], function (template) { 22999 self._containerNode.innerHTML = template; 23000 self._parseContent(self, self._containerNode); 23001 }); 23002 } 23003 else 23004 this._parseContent(this, this._containerNode); 23005 }, 23006 23007 _parseContent: function (containerWidget, nodeToParse) { 23008 23009 if (nodeToParse.firstChild != null) 23010 this._parseContentRecursive(containerWidget, nodeToParse.firstChild); 23011 23012 this._doneParsing = true; 23013 23014 if (this._depsLoading == 0) { 23015 this._widgetsParsed(); 23016 23017 if (this._widgetContainer != null) { 23018 this._widgetContainer._decrementDepCount(); 23019 } 23020 } 23021 }, 23022 23023 //This is an intense method. 23024 _parseContentRecursive : function(containerWidget , nodeToParse) 23025 { 23026 var dataDojoType; 23027 var newWidget; 23028 var self = this; 23029 var dataDojoTypeObj; 23030 23031 do 23032 { 23033 dataDojoType = nodeToParse.getAttribute ? nodeToParse.getAttribute("data-dojo-type") : null; 23034 23035 if(dataDojoType != null) 23036 dataDojoType = dataDojoType.replace(/\./g, "/"); 23037 //Only parse the nodes with this attribute. 23038 //This will parse just one node. No child nodes will be parsed. 23039 if (dataDojoType != null) 23040 { 23041 ++this._depsLoading; 23042 23043 (function(cNodeToParse , cContainerWidget, cDataDojoType){ 23044 //auto-require modules in. 23045 require([cDataDojoType], function () { 23046 var nodeObj = dojo.parser.instantiate([cNodeToParse], {}, { propsThis: cContainerWidget })[0];//should always return an array of one element unless I am missing something? 23047 var isContainer = nodeObj.isInstanceOf(dpage.widgets.Container); 23048 23049 //ensure that the container is set. 23050 if (nodeObj.getContainer() == null) { 23051 cContainerWidget.addWidget(nodeObj); 23052 //If the nodeObj is a container and the container for it was not set, the _decrementDepCount will not be called on us, 23053 // so we will fire it off manually here. 23054 if (isContainer && nodeObj._depsLoading == 0) 23055 self._decrementDepCount(); 23056 } 23057 23058 if (!isContainer) { 23059 //A Container will perform it's own parse, and then decrement our count once it finishes loading all widgets asynchronously. 23060 if (cNodeToParse.hasChildNodes()) { 23061 self._parseContentRecursive(cContainerWidget, cNodeToParse.firstChild); 23062 } 23063 self._decrementDepCount(); 23064 } 23065 }); 23066 })(nodeToParse , containerWidget , dataDojoType); 23067 } 23068 else 23069 { 23070 if (nodeToParse.hasChildNodes()) { 23071 this._parseContentRecursive(containerWidget, nodeToParse.firstChild); 23072 } 23073 } 23074 23075 } while (nodeToParse = nodeToParse.nextSibling); 23076 }, 23077 buildRendering: function () { 23078 23079 var self = this; 23080 23081 if (this._parseNow) 23082 this.parseContent(); 23083 else 23084 dojo.ready(function () { 23085 self.parseContent(); 23086 }); 23087 23088 this.domNode = this._containerNode; 23089 }, 23090 /** 23091 * Gets the model for the Container. 23092 * @returns {Object} The model. 23093 */ 23094 getModel: function () { 23095 return this._model; 23096 }, 23097 23098 /** 23099 * Sets a model. Use this model for all of the widgets on the page. 23100 * @param {Object} model Javascript object. 23101 * @param [modelTransform] default false. If false, just use the javascript object that was passed in. If true, each property of the javascript object 23102 * contains meta-data about the type of data and we will c
23102onstruct those objects here. The passed in model object WILL BE MODIFIED. 23103 * Typically used to construct dpage.modules.Model objects from the server. 23104 * @returns {void} 23105 */ 23106 setModel: function (val , modelTransform) { 23107 this._model = val; 23108 23109 if (modelTransform == null) 23110 modelTransform = false; 23111 23112 if (modelTransform) { 23113 //transform the model here. 23114 dpage.widgets.Container.parseServerModel(this._model); 23115 } 23116 }, 23117 //will attempt to divine out which objects should be SingleValueModels and TabularModels based on the format of the objects coming in. 23118 //The model is not transformed. 23119 _recurseRefreshModel: function (obj, modelObj) { 23120 23121 for (var p in obj) { 23122 var objHasProps = false; 23123 if (obj.hasOwnProperty(p)) { 23124 if (obj[p] == null) 23125 modelObj[p] = obj[p]; 23126 else if (obj[p].isInstanceOf != null && obj[p].isInstanceOf(dpage.modules.SingleValueModel)) { 23127 //causes CHANGE event to be called for subscribers (including SingleValue widgets). 23128 if (modelObj[p] == null || modelObj[p].isInstanceOf == null || !modelObj[p].isInstanceOf(dpage.modules.SingleValueModel)) 23129 throw new Error("Model mismatch. The structure of the existing model must match the new model."); 23130 modelObj[p].setValue(obj[p].getValue()); 23131 modelObj[p].setClean(); 23132 } 23133 else if (obj[p].isInstanceOf != null && obj[p].isInstanceOf(dpage.modules.TabularModel)) { 23134 //causes the INVALIDATE event to be called for subscribers (including MultiValue widgets). 23135 if (modelObj[p] == null || modelObj[p].isInstanceOf == null || !modelObj[p].isInstanceOf(dpage.modules.TabularModel)) 23136 throw new Error("Model mismatch. The structure of the existing model must match the new model."); 23137 modelObj[p].setRows(obj[p].getRows()); 23138 modelObj[p].setClean(); 23139 } 23140 else { 23141 //recurse. 23142 if (dpage.widgets.Container._isSimpleType(obj[p])) { 23143 //just set the value. 23144 modelObj[p] = obj[p]; 23145 } 23146 else { 23147 if (modelObj == null) 23148 throw new Error("Model mismatch. The structure of the existing model must match the new model."); 23149 this._recurseRefreshModel(obj[p], modelObj[p]); 23150 } 23151 } 23152 } 23153 } 23154 }, 23155 /** 23156 * Refresh the model. This is usefull to update the data in the entire Container. Calling this method will cause all of the widgets to update as well. 23157 * Very usefull when making async calls to the server and getting back updated data just as it would be when doing a page refresh. The model passed 23158 * in must match the structure of the existing model. Sets the state of all models to clean. 23159 * @param {Object} model Javascript object. 23160 * @param {bool} modelTransform Default false. If true, the model must convorm to a special format returned by the server serializer (or constructed manually). The 23161 * model will be transformed (val is changed). If false, just use the raw model passed in. 23162 * @returns {void} 23163 */ 23164 refreshModel: function (val, modelTransform) { 23165 if (modelTransform == null) 23166 modelTransform = false; 23167 23168 if (modelTransform) { 23169 //transform the model here. 23170 dpage.widgets.Container.parseServerModel(val); 23171 } 23172 23173 this._recurseRefreshModel(val , this._model); 23174 }, 23175 /** 23176 * Returns an array of the widgets registered with this container. To register a widget with this container, 23177 * you need to include the container property in the widget constructor with the value of the container you want 23178 * to register it with. 23179 * @returns {Array.<dpage.widgets.BaseWidget>} An Array of BaseWidgets. 23180 */ 23181 getWidgets: function () { 23182 return this._widgets; 23183 }, 23184 /** 23185 * Get a widget by its id 23186 * @param {Number} id The numeric widget id. 23187 * @returns {dpage.widgets.BaseWidget} 23188 */ 23189 getWidget: function (id) { 23190 for (var idx = 0; idx < this._widgets.length ; idx++) { 23191 if (this._widgets[idx].getWidgetId() == id) 23192 return this._widgets[idx]; 23193 } 23194 return null; 23195 }, 23196 /** 23197 * Add a widget to this container. 23198 * @param {dpage.widgets.BaseWidget} widgetRef 23199 * @param {bool}
23199 appendToDom Default false. If true, append as the last child of the containers getDomNode() 23200 * @returns {void} 23201 */ 23202 addWidget: function (widgetRef , appendToDom) { 23203 if (widgetRef.isInstanceOf == null || !widgetRef.isInstanceOf(dpage.widgets.BaseWidget)) 23204 throw new Error("Invalid widget detected. All widgets must inherit from WidgetBase."); 23205 23206 if (widgetRef.getContainer() == null || widgetRef.getContainer().getWidgetId() != this.getWidgetId()) { 23207 widgetRef.setContainer(this); 23208 } 23209 else { 23210 for (var idx = 0; idx < this._widgets.length ; idx++) { 23211 if (this._widgets[idx].getWidgetId() == widgetRef.getWidgetId()) 23212 throw new Error("Duplicate widget id of " + widgetRef.getWidgetId()) 23213 } 23214 this._widgets.push(widgetRef); 23215 } 23216 23217 if (appendToDom) 23218 this.getDomNode().appendChild(widgetRef.getDomNode()); 23219 }, 23220 /** 23221 * Remove a widget by its id. To remove the widget from the dom, call the destroy() method on it after removing it from the container. 23222 * @param {Number} widgetId 23223 * @returns {dpage.widgets.BaseWidget} Reference to the removed widget. 23224 */ 23225 removeWidget: function (widgetId) { 23226 for (var idx = 0; idx < this._widgets.length ; idx++) { 23227 if (this._widgets[idx].getWidgetId() == widgetId) { 23228 this._widgets.splice(idx, 1); 23229 return this._widgets[idx]; 23230 } 23231 } 23232 }, 23233 /** 23234 * Clears the list of widgets for the container. It will also call the destroy() method on each widget. 23235 * @returns {void} 23236 */ 23237 clearWidgets: function () { 23238 for (var i = 0; i < this._widgets.length; i++) 23239 this._widgets[i].destroy(); 23240 23241 this._widgets = []; 23242 }, 23243 /** 23244 * Set the widget to be used to handle the validation message for this container. 23245 * @param {dpage.widgets.BaseWidget} widget 23246 * @return {void} 23247 */ 23248 setValidationMessageWidget: function (widget) { 23249 this._validationMessageWidget = widget; 23250 }, 23251 /** 23252 * Get a reference to the validation widget that will be used to display the validation message for this container. 23253 * @returns {dpage.widgets.ValidationMessage} 23254 */ 23255 getValidationMessageWidget: function () { 23256 return this._validationMessageWidget; 23257 }, 23258 /** 23259 * Validate all the widgets in this container. 23260 * @param {bool} disablePage If true the page will be disabled while the validation is taking place. 23261 * @returns {bool} Returns true if the page is OK. False, if there are validation issues. 23262 */ 23263 validateWidgets: function (disablePage) { 23264 var containerWidgets = this.getWidgets(); 23265 var validationResults = []; 23266 var result = true; 23267 23268 if (disablePage) { 23269 this.disablePage(); 23270 } 23271 23272 if (this.getValidationMessageWidget != null && this.getValidationMessageWidget() != null) { 23273 this.getValidationMessageWidget().clearError(); 23274 } 23275 23276 for (var idx = 0 ; idx < containerWidgets.length ; idx++) { 23277 var ret = containerWidgets[idx].validate(); 23278 if (ret != null) 23279 validationResults.push({ widgetId: containerWidgets[idx].getWidgetId(), message: ret }); 23280 } 23281 23282 if (validationResults.length > 0) { 23283 if (this.getValidationMessageWidget != null && this.getValidationMessageWidget() != null) { 23284 this.getValidationMessageWidget().setError(validationResults); 23285 } 23286 result = false; 23287 } 23288 23289 if (disablePage) { 23290 this.enablePage(); 23291 } 23292 23293 return result; 23294 }, 23295 _serializeRecurseObject : function(obj , objCopy) 23296 { 23297 for(var prop in obj) 23298 { 23299 var objHasProperties = false; 23300 23301 if(obj.hasOwnProperty(prop)) 23302 { 23303 if (obj[prop] == null) 23304 continue; 23305 if (obj[prop].isInstanceOf != null && obj[prop].isInstanceOf(dpage.modules.Model)) { 23306 if (obj[prop].suppressSerialization(null)) 23307 objCopy[prop] = null; 23308 else 23309 objCopy[prop] = obj[prop].getRawModel(); 23310 } 23311 else { 23312 if (obj[prop] instanceof Array) { 23313 objCopy[prop] = []; 23314 this._serializeRecurseObject(obj[prop], objCopy[prop]); 23315 } 23316 else { 23317 if(dpage.widgets.Container._isSimpleType(obj[prop])) { 23318 //just copy the raw value. 23319 objCopy[prop] = obj[prop]; 23320 } 23321 else { 23322 objCopy[prop] = {}; 23323 this._serializeRecurseObject(obj[prop], objCopy[prop]); 23324 } 23325 } 23326 23327 } 23328 } 23329 } 23330 }, 23331 /** 23332 *Stringify the Model so that we can communicate with a server.
23333 * @returns {String} 23334 */ 23335 serializeModel: function () { 23336 var strModel; 23337 var thisModel = this.getModel(); 23338 var simplePageModel = {}; 23339 23340 if (thisModel != null) { 23341 this._serializeRecurseObject(thisModel , simplePageModel); 23342 23343 strModel = json.stringify(simplePageModel); 23344 } 23345 else 23346 strModel = 'null'; 23347 23348 return strModel; 23349 } 23350 }); 23351 23352 /** 23353 * Parse the model that comes back from the server. This call will create TabularModels and SingleValueModels automatically based on the 23354 * format of the message that comes back from the server. This method modifies the object passed in. 23355 * @memberof dpage.widgets.Container 23356 * @name parseServerModel 23357 * @function 23358 * @param {String} Serialized string model from server. 23359 * @returns {Object} Object to use in calls to Container.setModel() or Container.refreshModel() 23360 *//** 23361 * Parse the model that comes back from the server. This call will create TabularModels and SingleValueModels automatically based on the 23362 * format of the message that comes back from the server. This method modifies the object passed in. 23363 * @memberof dpage.widgets.Container 23364 * @name parseServerModel 23365 * @function 23366 * @param {Object} Object obtained from de-serializing the serialized string model from server. 23367 * @returns {Object} Object to use in calls to Container.setModel() or Container.refreshModel() 23368 */ 23369 theClass.parseServerModel = function (modelIn) { 23370 var model; 23371 23372 if (typeof (modelIn) === "string" || modelIn instanceof String) 23373 model = json.parse(modelIn); 23374 else 23375 model = modelIn; 23376 23377 dpage.widgets.Container._recurseParseModel(model); 23378 23379 return model; 23380 }; 23381 23382 theClass._isSimpleType = function (obj) { 23383 var t = typeof(obj); 23384 23385 if( t === "string" || obj instanceof String || 23386 t === "boolean" || obj instanceof Boolean || 23387 t === "number" || obj instanceof Number){ 23388 return true; 23389 } 23390 23391 return false; 23392 }; 23393 23394 //will attempt to divine out which objects should be SingleValueModels and TabularModels based on the format of the objects coming in. 23395 theClass._recurseParseModel = function (obj) 23396 { 23397 for(var p in obj) 23398 { 23399 if(obj.hasOwnProperty(p)) 23400 { 23401 if (obj[p] == null) 23402 continue; 23403 if (obj[p].dt == null) 23404 throw new Error("Encountered an anomaly parsing the model. Each model property must contain a 'dt' property. You must pass the modelTransform:false property to disable this. "); 23405 23406 if (obj[p].dt == "Literal") { 23407 obj[p] = obj[p].v; 23408 dpage.widgets.Container._recurseParseModel(obj[p]); 23409 } 23410 else if(obj[p].dt == "dpage.modules.SingleValueModel") 23411 obj[p] = dpage.modules.SingleValueModel.apply(null, obj[p].args); 23412 else if (obj[p].dt == "dpage.modules.TabularModel") { 23413 //transform the columns of the TabularModel if they are type=="OBJECT" 23414 for (var i = 0; i < obj[p].args[0].model.Columns.length; i++) { 23415 if (obj[p].args[0].model.Columns[i].DataType == "OBJECT") { 23416 //we only take this hit if we are taking advantage of the funtionality thankfully. 23417 for (var ri = 0 ; ri < obj[p].args[0].model.Rows.length; ri++) 23418 { 23419 var t = { z: obj[p].args[0].model.Rows[ri][obj[p].args[0].model.Columns[i].ColumnName] }; 23420 dpage.widgets.Container._recurseParseModel(t); 23421 obj[p].args[0].model.Rows[ri][obj[p].args[0].model.Columns[i].ColumnName] = t.z; 23422 } 23423 } 23424 } 23425 //finally, turn the value into a TabularModel. 23426 obj[p] = dpage.modules.TabularModel.apply(null, obj[p].args); 23427 } 23428 else 23429 throw new Error("Encountered an anomaly parsing the model. Unexpected dt property of: " + obj[p].dt + ". Supported types are dpage.modules.TabularModel, dpage.modules.SingleValueModel, or Literal. "); 23430 } 23431 } 23432 }; 23433 return theClass; 23434 } 23435); 23436}, 23437'dojox/widget/Standby':function(){ 23438define(["dojo/_base/kernel", 23439 "dojo/_base/declare", 23440 "dojo/_base/array", 23441 "dojo/_base/event", 23442 "dojo/_base/sniff", 23443 "dojo/dom", 23444 "dojo/dom-attr", 23445 "dojo/dom-construct", 23446 "dojo/dom-geometry", 23447 "dojo/dom-style",
23448 "dojo/window", 23449 "dojo/_base/window", 23450 "dojo/_base/fx", 23451 "dojo/fx", 23452 "dijit/_Widget", 23453 "dijit/_TemplatedMixin", 23454 "dijit/registry"], 23455 23456function(kernel, 23457 declare, 23458 array, 23459 event, 23460 has, 23461 dom, 23462 attr, 23463 construct, 23464 geometry, 23465 domStyle, 23466 window, 23467 baseWindow, 23468 baseFx, 23469 fx, 23470 _Widget, 23471 _TemplatedMixin, 23472 registry) { 23473 23474kernel.experimental("dojox.widget.Standby"); 23475 23476return declare("dojox.widget.Standby", [_Widget, _TemplatedMixin],{ 23477 // summary: 23478 // A widget designed to act as a Standby/Busy/Disable/Blocking widget to indicate a 23479 // particular DOM node is processing and cannot be clicked on at this time. 23480 // This widget uses absolute positioning to apply the overlay and image. 23481 23482 // image: String 23483 // A URL to an image to center within the blocking overlay. 23484 // The default is a basic spinner. 23485 image: require.toUrl("dojox/widget/Standby/images/loading.gif").toString(), 23486 23487 // imageText: String 23488 // Text to set on the ALT tag of the image. 23489 // The default is 'Please wait...' 23490 imageText: "Please Wait...", // TODO: i18n 23491 23492 // text: String 23493 // Text/HTML to display in the center of the overlay 23494 // This is used if image center is disabled. 23495 // Defaults to 'Please Wait...' 23496 text: "Please wait...", 23497 23498 // centerIndicator: String 23499 // Property to define if the image and its alt text should be used, or 23500 // a simple Text/HTML node should be used. Allowable values are 'image' 23501 // and 'text'. 23502 // Default is 'image'. 23503 centerIndicator: "image", 23504 23505 // target: DOMNode||DOMID(String)||WidgetID(String) 23506 // The target to overlay when active. Can be a widget id, a 23507 // dom id, or a direct node reference. 23508 target: "", 23509 23510 // color: String 23511 // The color to set the overlay. Should be in #XXXXXX form. 23512 // Default color for the translucent overlay is light gray. 23513 color: "#C0C0C0", 23514 23515 // duration: Integer 23516 // Integer defining how long the show and hide effects should take in milliseconds. 23517 // Defaults to 500 23518 duration: 500, 23519 23520 // zIndex: String 23521 // Control that lets you specify if the zIndex for the overlay 23522 // should be auto-computed based off parent zIndex, or should be set 23523 // to a particular value. This is useful when you want to overlay 23524 // things in digit.Dialogs, you can specify a base zIndex to append from. 23525 zIndex: "auto", 23526 23527 // opacity: float 23528 // The opacity to make the overlay when it is displayed/faded in. 23529 // The default is 0.75. This does not affect the image opacity, only the 23530 // overlay. 23531 opacity: 0.75, 23532 23533 // templateString: [protected] String 23534 // The template string defining out the basics of the widget. No need for an external 23535 // file. 23536 templateString: 23537 "<div>" + 23538 "<div style=\"display: none; opacity: 0; z-index: 9999; " + 23539 "position: absolute; cursor:wait;\" dojoAttachPoint=\"_underlayNode\"></div>" + 23540 "<img src=\"${image}\" style=\"opacity: 0; display: none; z-index: -10000; " + 23541 "position: absolute; top: 0px; left: 0px; cursor:wait;\" "+ 23542 "dojoAttachPoint=\"_imageNode\">" + 23543 "<div style=\"opacity: 0; display: none; z-index: -10000; position: absolute; " + 23544 "top: 0px;\" dojoAttachPoint=\"_textNode\"></div>" + 23545 "</div>", 23546 23547 // _underlayNode: [private] DOMNode 23548 // The node that is the translucent underlay for the 23549 // image that blocks access to the target. 23550 _underlayNode: null, 23551 23552 // _imageNode: [private] DOMNode 23553 // The image node where we attach and define the image to display. 23554 _imageNode: null, 23555 23556 // _textNode: [private] DOMNode 23557 // The div to attach text/HTML in the overlay center item. 23558 _textNode: null, 23559 23560 // _centerNode: [private] DOMNode 23561 // Which node to use as the center node, the image or the text node. 23562 _centerNode: null, 23563 23564 // _displayed: [private] Boolean 23565 // Flag to indicate if the overlay is displayed or not. 23566 _displayed: false, 23567 23568 // _resizeCheck: [private] Object 23569 // Handle to interval function that checks the target for changes. 23570 _resizeCheck: null, 23571 23572 // _started: [private] Boolean 23573 // Trap flag to ensure startup only processes once. 23574 _started: false, 23575 23576 // _parent: [private] DOMNode 23577 // Wrapping div for the widget, also used for IE 7 in dealing with the 23578 // zoom issue. 23579 _parent: null, 23580 23581 startup: function(args){ 23582 // summary: 23583 // Over-ride of the basic widget startup function. 23584 // Configures the target node and sets the image to use. 23585 if(!this._started){ 23586 if(typeof this.target === "string"){ 23587 var w = registry.byId(this.target);
23588 this.target = w ? w.domNode : dom.byId(this.target); 23589 } 23590 23591 if(this.text){ 23592 this._textNode.innerHTML = this.text; 23593 } 23594 if(this.centerIndicator === "image"){ 23595 this._centerNode = this._imageNode; 23596 attr.set(this._imageNode, "src", this.image); 23597 attr.set(this._imageNode, "alt", this.imageText); 23598 }else{ 23599 this._centerNode = this._textNode; 23600 } 23601 domStyle.set(this._underlayNode, { 23602 display: "none", 23603 backgroundColor: this.color 23604 }); 23605 domStyle.set(this._centerNode, "display", "none"); 23606 this.connect(this._underlayNode, "onclick", "_ignore"); 23607 23608 //Last thing to do is move the widgets parent, if any, to the current document body. 23609 //Avoids having to deal with parent relative/absolute mess. Otherwise positioning 23610 //tends to go goofy. 23611 if(this.domNode.parentNode && this.domNode.parentNode != baseWindow.body()){ 23612 baseWindow.body().appendChild(this.domNode); 23613 } 23614 23615 //IE 7 has a horrible bug with zoom, so we have to create this node 23616 //to cross-check later. Sigh. 23617 if(has("ie") == 7){ 23618 this._ieFixNode = construct.create("div"); 23619 domStyle.set(this._ieFixNode, { 23620 opacity: "0", 23621 zIndex: "-1000", 23622 position: "absolute", 23623 top: "-1000px" 23624 }); 23625 baseWindow.body().appendChild(this._ieFixNode); 23626 } 23627 this.inherited(arguments); 23628 } 23629 }, 23630 23631 show: function(){ 23632 // summary: 23633 // Function to display the blocking overlay and busy/status icon or text. 23634 if(!this._displayed){ 23635 if(this._anim){ 23636 this._anim.stop(); 23637 delete this._anim; 23638 } 23639 this._displayed = true; 23640 this._size(); 23641 this._disableOverflow(); 23642 this._fadeIn(); 23643 } 23644 }, 23645 23646 hide: function(){ 23647 // summary: 23648 // Function to hide the blocking overlay and status icon or text. 23649 if(this._displayed){ 23650 if(this._anim){ 23651 this._anim.stop(); 23652 delete this._anim; 23653 } 23654 this._size(); 23655 this._fadeOut(); 23656 this._displayed = false; 23657 if(this._resizeCheck !== null){ 23658 clearInterval(this._resizeCheck); 23659 this._resizeCheck = null; 23660 } 23661 } 23662 }, 23663 23664 isVisible: function(){ 23665 // summary: 23666 // Helper function so you can test if the widget is already visible or not. 23667 // returns: 23668 // boolean indicating if the widget is in 'show' state or not. 23669 return this._displayed; // boolean 23670 }, 23671 23672 onShow: function(){ 23673 // summary: 23674 // Event that fires when the display of the Standby completes. 23675 }, 23676 23677 onHide: function(){ 23678 // summary: 23679 // Event that fires when the display of the Standby completes. 23680 }, 23681 23682 uninitialize: function(){ 23683 // summary: 23684 // Over-ride to hide the widget, which clears intervals, before cleanup. 23685 this._displayed = false; 23686 if(this._resizeCheck){ 23687 clearInterval(this._resizeCheck); 23688 } 23689 domStyle.set(this._centerNode, "display", "none"); 23690 domStyle.set(this._underlayNode, "display", "none"); 23691 if(has("ie") == 7 && this._ieFixNode){ 23692 baseWindow.body().removeChild(this._ieFixNode); 23693 delete this._ieFixNode; 23694 } 23695 if(this._anim){ 23696 this._anim.stop(); 23697 delete this._anim; 23698 } 23699 this.target = null; 23700 this._imageNode = null; 23701 this._textNode = null; 23702 this._centerNode = null; 23703 this.inherited(arguments); 23704 }, 23705 23706 _size: function(){ 23707 // summary: 23708 // Internal function that handles resizing the overlay and 23709 // centering of the image on window resizing. 23710 // tags: 23711 // private 23712 if(this._displayed){ 23713 var dir = attr.get(baseWindow.body(), "dir"); 23714 if(dir){dir = dir.toLowerCase();} 23715 var _ie7zoom; 23716 var scrollers = this._scrollerWidths(); 23717 23718 var target = this.target; 23719 23720 //Show the image and make sure the zIndex is set high. 23721 var curStyle = domStyle.get(this._centerNode, "display"); 23722 domStyle.set(this._centerNode, "display", "block"); 23723 var box = geometry.position(target, true); 23724 if(target === baseWindow.body() || target === baseWindow.doc){ 23725 // Target is the whole doc, so scale to viewport. 23726 box = window.getBox(); 23727 box.x = box.l; 23728 box.y = box.t; 23729 } 23730 23731 var cntrIndicator = geometry.getMarginBox(this._centerNode); 23732 domStyle.set(this._centerNode, "display", curStyle); 23733 23734 //IE has a horrible zoom bug. So, we have to try and account for 23735 //it and fix up the scaling. 23736 if(this._ieFixNode){ 23737 _ie7zoom = -this._ieFixNode.offsetTop / 1000; 23738 box.x = Math.floor((box.x + 0.9) / _ie7zoom); 23739 box.y = Math.floor((box.y + 0.9) / _ie7zoom); 23740 box.w = Math.floor((box.w + 0.9) / _ie7zoom); 23741 box.h = Math.floor((box.h + 0.9) / _ie7zoom); 23742 } 23743 23744 //Figure out how to zIndex this thing over the target. 23745 var zi = domStyle.get(target, "zIndex");
23746 var ziUl = zi; 23747 var ziIn = zi; 23748 23749 if(this.zIndex === "auto"){ 23750 if(zi != "auto"){ 23751 ziUl = parseInt(ziUl, 10) + 1; 23752 ziIn = parseInt(ziIn, 10) + 2; 23753 }else{ 23754 //We need to search up the chain to see if there 23755 //are any parent zIndexs to overlay. 23756 var cNode = target; 23757 if(cNode && cNode !== baseWindow.body() && cNode !== baseWindow.doc){ 23758 cNode = target.parentNode; 23759 var oldZi = -100000; 23760 while(cNode && cNode !== baseWindow.body()){ 23761 zi = domStyle.get(cNode, "zIndex"); 23762 if(!zi || zi === "auto"){ 23763 cNode = cNode.parentNode; 23764 }else{ 23765 var newZi = parseInt(zi, 10); 23766 if(oldZi < newZi){ 23767 oldZi = newZi; 23768 ziUl = newZi + 1; 23769 ziIn = newZi + 2; 23770 } 23771 // Keep looking until we run out, we want the highest zIndex. 23772 cNode = cNode.parentNode; 23773 } 23774 } 23775 } 23776 } 23777 }else{ 23778 ziUl = parseInt(this.zIndex, 10) + 1; 23779 ziIn = parseInt(this.zIndex, 10) + 2; 23780 } 23781 23782 domStyle.set(this._centerNode, "zIndex", ziIn); 23783 domStyle.set(this._underlayNode, "zIndex", ziUl); 23784 23785 23786 var pn = target.parentNode; 23787 if(pn && pn !== baseWindow.body() && 23788 target !== baseWindow.body() && 23789 target !== baseWindow.doc){ 23790 23791 // If the parent is the body tag itself, 23792 // we can avoid all this, the body takes 23793 // care of overflow for me. Besides, browser 23794 // weirdness with height and width on body causes 23795 // problems with this sort of intersect testing 23796 // anyway. 23797 var obh = box.h; 23798 var obw = box.w; 23799 var pnBox = geometry.position(pn, true); 23800 23801 //More IE zoom corrections. Grr. 23802 if(this._ieFixNode){ 23803 _ie7zoom = -this._ieFixNode.offsetTop / 1000; 23804 pnBox.x = Math.floor((pnBox.x + 0.9) / _ie7zoom); 23805 pnBox.y = Math.floor((pnBox.y + 0.9) / _ie7zoom); 23806 pnBox.w = Math.floor((pnBox.w + 0.9) / _ie7zoom); 23807 pnBox.h = Math.floor((pnBox.h + 0.9) / _ie7zoom); 23808 } 23809 23810 //Shift the parent width/height a bit if scollers are present. 23811 pnBox.w -= pn.scrollHeight > pn.clientHeight && 23812 pn.clientHeight > 0 ? scrollers.v: 0; 23813 pnBox.h -= pn.scrollWidth > pn.clientWidth && 23814 pn.clientWidth > 0 ? scrollers.h: 0; 23815 23816 //RTL requires a bit of massaging in some cases 23817 //(and differently depending on browser, ugh!) 23818 //WebKit and others still need work. 23819 if(dir === "rtl"){ 23820 if(has("opera")){ 23821 box.x += pn.scrollHeight > pn.clientHeight && 23822 pn.clientHeight > 0 ? scrollers.v: 0; 23823 pnBox.x += pn.scrollHeight > pn.clientHeight && 23824 pn.clientHeight > 0 ? scrollers.v: 0; 23825 }else if(has("ie")){ 23826 pnBox.x += pn.scrollHeight > pn.clientHeight && 23827 pn.clientHeight > 0 ? scrollers.v: 0; 23828 }else if(has("webkit")){ 23829 //TODO: FIX THIS! 23830 } 23831 } 23832 23833 //Figure out if we need to adjust the overlay to fit a viewable 23834 //area, then resize it, we saved the original height/width above. 23835 //This is causing issues on IE. Argh! 23836 if(pnBox.w < box.w){ 23837 //Scale down the width if necessary. 23838 box.w = box.w - pnBox.w; 23839 } 23840 if(pnBox.h < box.h){ 23841 //Scale down the width if necessary. 23842 box.h = box.h - pnBox.h; 23843 } 23844 23845 //Look at the y positions and see if we intersect with the 23846 //viewport borders. Will have to do computations off it. 23847 var vpTop = pnBox.y; 23848 var vpBottom = pnBox.y + pnBox.h; 23849 var bTop = box.y; 23850 var bBottom = box.y + obh; 23851 var vpLeft = pnBox.x; 23852 var vpRight = pnBox.x + pnBox.w; 23853 var bLeft = box.x; 23854 var bRight = box.x + obw; 23855 var delta; 23856 //Adjust the height now 23857 if(bBottom > vpTop && 23858 bTop < vpTop){ 23859 box.y = pnBox.y; 23860 //intersecting top, need to do some shifting. 23861 delta = vpTop - bTop; 23862 var visHeight = obh - delta; 23863 //If the visible height < viewport height, 23864 //We need to shift it. 23865 if(visHeight < pnBox.h){ 23866 box.h = visHeight; 23867 }else{ 23868 //Deal with horizontal scrollbars if necessary. 23869 box.h -= 2*(pn.scrollWidth > pn.clientWidth && 23870 pn.clientWidth > 0? scrollers.h: 0); 23871 } 23872 }else if(bTop < vpBottom && bBottom > vpBottom){ 23873 //Intersecting bottom, just figure out how much 23874 //overlay to show. 23875 box.h = vpBottom - bTop; 23876 }else if(bBottom <= vpTop || bTop >= vpBottom){ 23877 //Outside view, hide it. 23878 box.h = 0; 23879 } 23880 23881 //adjust width 23882 if(bRight > vpLeft && bLeft < vpLeft){
23883 box.x = pnBox.x; 23884 //intersecting left, need to do some shifting. 23885 delta = vpLeft - bLeft; 23886 var visWidth = obw - delta; 23887 //If the visible width < viewport width, 23888 //We need to shift it. 23889 if(visWidth < pnBox.w){ 23890 box.w = visWidth; 23891 }else{ 23892 //Deal with horizontal scrollbars if necessary. 23893 box.w -= 2*(pn.scrollHeight > pn.clientHeight && 23894 pn.clientHeight > 0? scrollers.w:0); 23895 } 23896 }else if(bLeft < vpRight && bRight > vpRight){ 23897 //Intersecting right, just figure out how much 23898 //overlay to show. 23899 box.w = vpRight - bLeft; 23900 }else if(bRight <= vpLeft || bLeft >= vpRight){ 23901 //Outside view, hide it. 23902 box.w = 0; 23903 } 23904 } 23905 23906 if(box.h > 0 && box.w > 0){ 23907 //Set position and size of the blocking div overlay. 23908 domStyle.set(this._underlayNode, { 23909 display: "block", 23910 width: box.w + "px", 23911 height: box.h + "px", 23912 top: box.y + "px", 23913 left: box.x + "px" 23914 }); 23915 23916 var styles = ["borderRadius", "borderTopLeftRadius", 23917 "borderTopRightRadius","borderBottomLeftRadius", 23918 "borderBottomRightRadius"]; 23919 this._cloneStyles(styles); 23920 if(!has("ie")){ 23921 //Browser specific styles to try and clone if non-IE. 23922 styles = ["MozBorderRadius", "MozBorderRadiusTopleft", 23923 "MozBorderRadiusTopright","MozBorderRadiusBottomleft", 23924 "MozBorderRadiusBottomright","WebkitBorderRadius", 23925 "WebkitBorderTopLeftRadius", "WebkitBorderTopRightRadius", 23926 "WebkitBorderBottomLeftRadius","WebkitBorderBottomRightRadius" 23927 ]; 23928 this._cloneStyles(styles, this); 23929 } 23930 var cntrIndicatorTop = (box.h/2) - (cntrIndicator.h/2); 23931 var cntrIndicatorLeft = (box.w/2) - (cntrIndicator.w/2); 23932 //Only show the image if there is height and width room. 23933 if(box.h >= cntrIndicator.h && box.w >= cntrIndicator.w){ 23934 domStyle.set(this._centerNode, { 23935 top: (cntrIndicatorTop + box.y) + "px", 23936 left: (cntrIndicatorLeft + box.x) + "px", 23937 display: "block" 23938 }); 23939 }else{ 23940 domStyle.set(this._centerNode, "display", "none"); 23941 } 23942 }else{ 23943 //Target has no size, display nothing on it! 23944 domStyle.set(this._underlayNode, "display", "none"); 23945 domStyle.set(this._centerNode, "display", "none"); 23946 } 23947 if(this._resizeCheck === null){ 23948 //Set an interval timer that checks the target size and scales as needed. 23949 //Checking every 10th of a second seems to generate a fairly smooth update. 23950 var self = this; 23951 this._resizeCheck = setInterval(function(){self._size();}, 100); 23952 } 23953 } 23954 }, 23955 23956 _cloneStyles: function(list){ 23957 // summary: 23958 // Internal function to clone a set of styles from the target to 23959 // the underlay. 23960 // list: Array 23961 // An array of style names to clone. 23962 // 23963 // tags: 23964 // private 23965 array.forEach(list, function(s){ 23966 domStyle.set(this._underlayNode, s, domStyle.get(this.target, s)); 23967 }, this); 23968 }, 23969 23970 _fadeIn: function(){ 23971 // summary: 23972 // Internal function that does the opacity style fade in animation. 23973 // tags: 23974 // private 23975 var self = this; 23976 var underlayNodeAnim = baseFx.animateProperty({ 23977 duration: self.duration, 23978 node: self._underlayNode, 23979 properties: {opacity: {start: 0, end: self.opacity}} 23980 }); 23981 var imageAnim = baseFx.animateProperty({ 23982 duration: self.duration, 23983 node: self._centerNode, 23984 properties: {opacity: {start: 0, end: 1}}, 23985 onEnd: function(){ 23986 self.onShow(); 23987 delete self._anim; 23988 } 23989 }); 23990 this._anim = fx.combine([underlayNodeAnim,imageAnim]); 23991 this._anim.play(); 23992 }, 23993 23994 _fadeOut: function(){ 23995 // summary: 23996 // Internal function that does the opacity style fade out animation. 23997 // tags: 23998 // private 23999 var self = this; 24000 var underlayNodeAnim = baseFx.animateProperty({ 24001 duration: self.duration, 24002 node: self._underlayNode, 24003 properties: {opacity: {start: self.opacity, end: 0}}, 24004 onEnd: function(){ 24005 domStyle.set(this.node,{"display":"none", "zIndex": "-1000"}); 24006 } 24007 }); 24008 var imageAnim = baseFx.animateProperty({ 24009 duration: self.duration, 24010 node: self._centerNode, 24011 properties: {opacity: {start: 1, end: 0}}, 24012 onEnd: function(){ 24013 domStyle.set(this.node,{"display":"none", "zIndex": "-1000"}); 24014 self.onHide(); 24015 self._enableOverflow(); 24016 delete self._anim; 24017 } 24018 }); 24019 this._anim = fx.combine([underlayNodeAnim,imageAnim]); 24020 this._anim.play(); 24021 }, 24022 24023 _ignore: function(e){
24024 // summary: 24025 // Function to ignore events that occur on the overlay. 24026 // event: Event 24027 // The event to halt 24028 // tags: 24029 // private 24030 if(e){ 24031 event.stop(e); 24032 } 24033 }, 24034 24035 _scrollerWidths: function(){ 24036 // summary: 24037 // This function will calculate the size of the vertical and 24038 // horizontaol scrollbars. 24039 // returns: 24040 // Object of form: {v: Number, h: Number} where v is vertical scrollbar width 24041 // and h is horizontal scrollbar width. 24042 // tags: 24043 // private 24044 var div = construct.create("div"); 24045 domStyle.set(div, { 24046 position: "absolute", 24047 opacity: 0, 24048 overflow: "hidden", 24049 width: "50px", 24050 height: "50px", 24051 zIndex: "-100", 24052 top: "-200px", 24053 padding: "0px", 24054 margin: "0px" 24055 }); 24056 var iDiv = construct.create("div"); 24057 domStyle.set(iDiv, { 24058 width: "200px", 24059 height: "10px" 24060 }); 24061 div.appendChild(iDiv); 24062 baseWindow.body().appendChild(div); 24063 24064 //Figure out content size before and after 24065 //scrollbars are there, then just subtract to 24066 //get width. 24067 var b = geometry.getContentBox(div); 24068 domStyle.set(div, "overflow", "scroll"); 24069 var a = geometry.getContentBox(div); 24070 baseWindow.body().removeChild(div); 24071 return { v: b.w - a.w, h: b.h - a.h }; 24072 }, 24073 24074 /* The following are functions that tie into _Widget.attr() */ 24075 24076 _setTextAttr: function(text){ 24077 // summary: 24078 // Function to allow widget.attr to set the text displayed in center 24079 // if using text display. 24080 // text: String 24081 // The text to set. 24082 this._textNode.innerHTML = text; 24083 this.text = text; 24084 }, 24085 24086 _setColorAttr: function(c){ 24087 // summary: 24088 // Function to allow widget.attr to set the color used for the translucent 24089 // div overlay. 24090 // c: String 24091 // The color to set the background underlay to in #XXXXXX format.. 24092 domStyle.set(this._underlayNode, "backgroundColor", c); 24093 this.color = c; 24094 }, 24095 24096 _setImageTextAttr: function(text){ 24097 // summary: 24098 // Function to allow widget.attr to set the ALT text text displayed for 24099 // the image (if using image center display). 24100 // text: String 24101 // The text to set. 24102 attr.set(this._imageNode, "alt", text); 24103 this.imageText = text; 24104 }, 24105 24106 _setImageAttr: function(url){ 24107 // summary: 24108 // Function to allow widget.attr to set the url source for the center image 24109 // text: String 24110 // The url to set for the image. 24111 attr.set(this._imageNode, "src", url); 24112 this.image = url; 24113 }, 24114 24115 _setCenterIndicatorAttr: function(indicator){ 24116 // summary: 24117 // Function to allow widget.attr to set the node used for the center indicator, 24118 // either the image or the text. 24119 // indicator: String 24120 // The indicator to use, either 'image' or 'text'. 24121 this.centerIndicator = indicator; 24122 if(indicator === "image"){ 24123 this._centerNode = this._imageNode; 24124 domStyle.set(this._textNode, "display", "none"); 24125 }else{ 24126 this._centerNode = this._textNode; 24127 domStyle.set(this._imageNode, "display", "none"); 24128 } 24129 }, 24130 24131 _disableOverflow: function(){ 24132 // summary: 24133 // Function to disable scrollbars on the body. Only used if the overlay 24134 // targets the body or the document. 24135 if(this.target === baseWindow.body() || this.target === baseWindow.doc){ 24136 // Store the overflow state we have to restore later. 24137 // IE had issues, so have to check that it's defined. Ugh. 24138 this._overflowDisabled = true; 24139 var body = baseWindow.body(); 24140 if(body.style && body.style.overflow){ 24141 this._oldOverflow = domStyle.get(body, "overflow"); 24142 }else{ 24143 this._oldOverflow = ""; 24144 } 24145 if(has("ie") && !has("quirks")){ 24146 // IE will put scrollbars in anyway, html (parent of body) 24147 // also controls them in standards mode, so we have to 24148 // remove them, argh. 24149 if(body.parentNode && 24150 body.parentNode.style && 24151 body.parentNode.style.overflow){ 24152 this._oldBodyParentOverflow = body.parentNode.style.overflow; 24153 }else{ 24154 try{ 24155 this._oldBodyParentOverflow = domStyle.get(body.parentNode, "overflow"); 24156 }catch(e){ 24157 this._oldBodyParentOverflow = "scroll"; 24158 } 24159 } 24160 domStyle.set(body.parentNode, "overflow", "hidden"); 24161 } 24162 domStyle.set(body, "overflow", "hidden"); 24163 } 24164 }, 24165 24166 _enableOverflow: function(){ 24167 // summary: 24168 // Function to restore scrollbars on the body. Only used if the overlay 24169 // targets the body or the document. 24170 if(this._overflowDisabled){ 24171 delete this._overflowDisabled; 24172 var body = baseWindow.body(); 24173 // Restore all the overflow.
vendor: 7,208 bytes, lines 24174-24355
24174 if(has("ie") && !has("quirks")){ 24175 body.parentNode.style.overflow = this._oldBodyParentOverflow; 24176 delete this._oldBodyParentOverflow; 24177 } 24178 domStyle.set(body, "overflow", this._oldOverflow); 24179 if(has("webkit")){ 24180 //Gotta poke WebKit, or scrollers don't come back. :-( 24181 var div = construct.create("div", { style: { 24182 height: "2px" 24183 } 24184 }); 24185 body.appendChild(div); 24186 setTimeout(function(){ 24187 body.removeChild(div); 24188 }, 0); 24189 } 24190 delete this._oldOverflow; 24191 } 24192 } 24193}); 24194 24195}); 24196 24197}, 24198'dojo/window':function(){ 24199define(["./_base/lang", "./sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style", "./dom-construct"], 24200 function(lang, has, baseWindow, dom, geom, style, domConstruct){ 24201 24202 // feature detection 24203 /* not needed but included here for future reference 24204 has.add("rtl-innerVerticalScrollBar-on-left", function(win, doc){ 24205 var body = baseWindow.body(doc), 24206 scrollable = domConstruct.create('div', { 24207 style: {overflow:'scroll', overflowX:'hidden', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', width:'64px', height:'64px'} 24208 }, body, "last"), 24209 center = domConstruct.create('center', { 24210 style: {overflow:'hidden', direction:'ltr'} 24211 }, scrollable, "last"), 24212 inner = domConstruct.create('div', { 24213 style: {overflow:'visible', display:'inline' } 24214 }, center, "last"); 24215 inner.innerHTML=" "; 24216 var midPoint = Math.max(inner.offsetLeft, geom.position(inner).x); 24217 var ret = midPoint >= 32; 24218 center.removeChild(inner); 24219 scrollable.removeChild(center); 24220 body.removeChild(scrollable); 24221 return ret; 24222 }); 24223 */ 24224 has.add("rtl-adjust-position-for-verticalScrollBar", function(win, doc){ 24225 var body = baseWindow.body(doc), 24226 scrollable = domConstruct.create('div', { 24227 style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'} 24228 }, body, "last"), 24229 div = domConstruct.create('div', { 24230 style: {overflow:'hidden', direction:'ltr'} 24231 }, scrollable, "last"), 24232 ret = geom.position(div).x != 0; 24233 scrollable.removeChild(div); 24234 body.removeChild(scrollable); 24235 return ret; 24236 }); 24237 24238 has.add("position-fixed-support", function(win, doc){ 24239 // IE6, IE7+quirks, and some older mobile browsers don't support position:fixed 24240 var body = baseWindow.body(doc), 24241 outer = domConstruct.create('span', { 24242 style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'} 24243 }, body, "last"), 24244 inner = domConstruct.create('span', { 24245 style: {position:'fixed', left:'0', top:'0'} 24246 }, outer, "last"), 24247 ret = geom.position(inner).x != geom.position(outer).x; 24248 outer.removeChild(inner); 24249 body.removeChild(outer); 24250 return ret; 24251 }); 24252 24253 // module: 24254 // dojo/window 24255 24256 var window = { 24257 // summary: 24258 // TODOC 24259 24260 getBox: function(/*Document?*/ doc){ 24261 // summary: 24262 // Returns the dimensions and scroll position of the viewable area of a browser window 24263 24264 doc = doc || baseWindow.doc; 24265 24266 var 24267 scrollRoot = (doc.compatMode == 'BackCompat') ? baseWindow.body(doc) : doc.documentElement, 24268 // get scroll position 24269 scroll = geom.docScroll(doc), // scrollRoot.scrollTop/Left should work 24270 w, h; 24271 24272 if(has("touch")){ // if(scrollbars not supported) 24273 var uiWindow = window.get(doc); // use UI window, not dojo.global window 24274 // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight 24275 w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated 24276 h = uiWindow.innerHeight || scrollRoot.clientHeight; 24277 }else{ 24278 // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight 24279 // uiWindow.innerWidth/Height includes the scrollbar and cannot be used 24280 w = scrollRoot.clientWidth; 24281 h = scrollRoot.clientHeight; 24282 } 24283 return { 24284 l: scroll.x, 24285 t: scroll.y, 24286 w: w, 24287 h: h 24288 }; 24289 }, 24290 24291 get: function(/*Document*/ doc){ 24292 // summary: 24293 // Get window object associated with document doc. 24294 // doc: 24295 // The document to get the associated window for. 24296 24297 // In some IE versions (at least 6.0), document.parentWindow does not return a 24298 // reference to the real window object (maybe a copy), so we must fix it as well 24299 // We use IE specific execScript to attach the real window reference to 24300 // document._parentWindow for later use 24301 if(has("ie") && window !== document.parentWindow){ 24302 /* 24303 In IE 6, only the variable "window" can be used to connect events (others 24304 may be only copies). 24305 */ 24306 doc.parentWindow.execScript("document._parentWindow = window;", "Javascript"); 24307 //to prevent memory leak, unset it after use 24308 //another possibility is to add an onUnload handler which seems overkill to me (liucougar) 24309 var win = doc._parentWindow; 24310 doc._parentWindow = null; 24311 return win; // Window 24312 } 24313 24314 return doc.parentWindow || doc.defaultView; // Window 24315 }, 24316 24317 scrollIntoView: function(/*DomNode*/ node, /*Object?*/ pos){ 24318 // summary: 24319 // Scroll the passed node into view using minimal movement, if it is not already. 24320 24321 // Don't rely on node.scrollIntoView working just because the function is there since 24322 // it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement. 24323 // WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode 24324 // and when there's a fixed position scrollable element 24325 24326 try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method 24327 node = dom.byId(node); 24328 var doc = node.ownerDocument || baseWindow.doc, // TODO: why baseWindow.doc? Isn't node.ownerDocument always defined? 24329 body = baseWindow.body(doc), 24330 html = doc.documentElement || body.parentNode, 24331 isIE = has("ie"), 24332 isWK = has("webkit"); 24333 // if an untested browser, then use the native method 24334 if(node == body || node == html){ return; } 24335 if(!(has("mozilla") || isIE || isWK || has("opera") || has("trident")) && ("scrollIntoView" in node)){ 24336 node.scrollIntoView(false); // short-circuit to native if possible 24337 return; 24338 } 24339 var backCompat = doc.compatMode == 'BackCompat', 24340 rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth), 24341 rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight), 24342 scrollRoot = (isWK || backCompat) ? body : html, 24343 nodePos = pos || geom.position(node), 24344 el = node.parentNode, 24345 isFixed = function(el){ 24346 return (isIE <= 6 || (isIE == 7 && backCompat)) 24347 ? false 24348 : (has("position-fixed-support") && (style.get(el, 'position').toLowerCase() == "fixed")); 24349 }, 24350 self = this, 24351 scrollElementBy = function(el, x, y){ 24352 if(el.tagName == "BODY" || el.tagName == "HTML"){ 24353 self.get(el.ownerDocument).scrollBy(x, y); 24354 }else{ 24355 x && (el.scrollLeft += x);
24356 y && (el.scrollTop += y); 24357 } 24358 }; 24359 if(isFixed(node)){ return; } // nothing to do 24360 while(el){ 24361 if(el == body){ el = scrollRoot; } 24362 var elPos = geom.position(el), 24363 fixedPos = isFixed(el), 24364 rtl = style.getComputedStyle(el).direction.toLowerCase() == "rtl"; 24365 24366 if(el == scrollRoot){ 24367 elPos.w = rootWidth; elPos.h = rootHeight; 24368 if(scrollRoot == html && (isIE || has("trident")) && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x 24369 if(elPos.x < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.x = 0; } // older IE can have values > 0 24370 if(elPos.y < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.y = 0; } 24371 }else{ 24372 var pb = geom.getPadBorderExtents(el); 24373 elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t; 24374 var clientSize = el.clientWidth, 24375 scrollBarSize = elPos.w - clientSize; 24376 if(clientSize > 0 && scrollBarSize > 0){ 24377 if(rtl && has("rtl-adjust-position-for-verticalScrollBar")){ 24378 elPos.x += scrollBarSize; 24379 } 24380 elPos.w = clientSize; 24381 } 24382 clientSize = el.clientHeight; 24383 scrollBarSize = elPos.h - clientSize; 24384 if(clientSize > 0 && scrollBarSize > 0){ 24385 elPos.h = clientSize; 24386 } 24387 } 24388 if(fixedPos){ // bounded by viewport, not parents 24389 if(elPos.y < 0){ 24390 elPos.h += elPos.y; elPos.y = 0; 24391 } 24392 if(elPos.x < 0){ 24393 elPos.w += elPos.x; elPos.x = 0; 24394 } 24395 if(elPos.y + elPos.h > rootHeight){ 24396 elPos.h = rootHeight - elPos.y; 24397 } 24398 if(elPos.x + elPos.w > rootWidth){ 24399 elPos.w = rootWidth - elPos.x; 24400 } 24401 } 24402 // calculate overflow in all 4 directions 24403 var l = nodePos.x - elPos.x, // beyond left: < 0 24404// t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0 24405 t = nodePos.y - elPos.y, // beyond top: < 0 24406 r = l + nodePos.w - elPos.w, // beyond right: > 0 24407 bot = t + nodePos.h - elPos.h; // beyond bottom: > 0 24408 var s, old; 24409 if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){ 24410 s = Math[l < 0? "max" : "min"](l, r); 24411 if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9 || has("trident"))){ s = -s; } 24412 old = el.scrollLeft; 24413 scrollElementBy(el, s, 0); 24414 s = el.scrollLeft - old; 24415 nodePos.x -= s; 24416 } 24417 if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){ 24418 s = Math.ceil(Math[t < 0? "max" : "min"](t, bot)); 24419 old = el.scrollTop; 24420 scrollElementBy(el, 0, s); 24421 s = el.scrollTop - old; 24422 nodePos.y -= s; 24423 } 24424 el = (el != scrollRoot) && !fixedPos && el.parentNode; 24425 } 24426 }catch(error){ 24427 console.error('scrollIntoView: ' + error); 24428 node.scrollIntoView(false); 24429 } 24430 } 24431 }; 24432 24433 1 && lang.setObject("dojo.window", window); 24434 24435 return window; 24436}); 24437 24438}, 24439'dojo/fx':function(){ 24440define([ 24441 "./_base/lang", 24442 "./Evented", 24443 "./_base/kernel", 24444 "./_base/array", 24445 "./aspect", 24446 "./_base/fx", 24447 "./dom", 24448 "./dom-style", 24449 "./dom-geometry", 24450 "./ready", 24451 "require" // for context sensitive loading of Toggler 24452], function(lang, Evented, dojo, arrayUtil, aspect, baseFx, dom, domStyle, geom, ready, require){ 24453 24454 // module: 24455 // dojo/fx 24456 24457 // For back-compat, remove in 2.0. 24458 if(!dojo.isAsync){ 24459 ready(0, function(){ 24460 var requires = ["./fx/Toggler"]; 24461 require(requires); // use indirection so modules not rolled into a build 24462 }); 24463 } 24464 24465 var coreFx = dojo.fx = { 24466 // summary: 24467 // Effects library on top of Base animations 24468 }; 24469 24470 var _baseObj = { 24471 _fire: function(evt, args){ 24472 if(this[evt]){ 24473 this[evt].apply(this, args||[]); 24474 } 24475 return this; 24476 } 24477 }; 24478 24479 var _chain = function(animations){ 24480 this._index = -1; 24481 this._animations = animations||[]; 24482 this._current = this._onAnimateCtx = this._onEndCtx = null; 24483 24484 this.duration = 0; 24485 arrayUtil.forEach(this._animations, function(a){ 24486 this.duration += a.duration; 24487 if(a.delay){ this.duration += a.delay; } 24488 }, this); 24489 }; 24490 _chain.prototype = new Evented(); 24491 lang.extend(_chain, { 24492 _onAnimate: function(){ 24493 this._fire("onAnimate", arguments); 24494 }, 24495 _onEnd: function(){ 24496 this._onAnimateCtx.remove(); 24497 this._onEndCtx.remove(); 24498 this._onAnimateCtx = this._onEndCtx = null; 24499 if(this._index + 1 == this._animations.length){ 24500 this._fire("onEnd"); 24501 }else{ 24502 // switch animations 24503 this._current = this._animations[++this._index]; 24504 this._onAnimateCtx = aspect.after(this._current, "onAnimate", lang.hitch(this, "_onAnimate"), true); 24505 this._onEndCtx = aspect.after(this._current, "onEnd", lang.hitch(this, "_onEnd"), true); 24506 this._current.play(0, true); 24507 } 24508 }, 24509 play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ 24510 if(!this._current){ this._current = this._animations[this._index = 0]; } 24511 if(!gotoStart && this._current.status() == "playing"){ return this; } 24512 var beforeBegin = aspect.after(this._current, "beforeBegin", lang.hitch(this, function(){ 24513 this._fire("beforeBegin"); 24514 }), true), 24515 onBegin = aspect.after(this._current, "onBegin", lang.hitch(this, function(arg){ 24516 this._fire("onBegin", arguments); 24517 }), true), 24518 onPlay = aspect.after(this._current, "onPlay", lang.hitch(this, function(arg){ 24519 this._fire("onPlay", arguments); 24520 beforeBegin.remove(); 24521 onBegin.remove(); 24522 onPlay.remove(); 24523 })); 24524 if(this._onAnimateCtx){ 24525 this._onAnimateCtx.remove(); 24526 } 24527 this._onAnimateCtx = aspect.after(this._current, "onAnimate", lang.hitch(this, "_onAnimate"), true); 24528 if(this._onEndCtx){ 24529 this._onEndCtx.remove(); 24530 } 24531 this._onEndCtx = aspect.after(this._current, "onEnd", lang.hitch(this, "_onEnd"), true); 24532 this._current.play.apply(this._current, arguments); 24533 return this; 24534 }, 24535 pause: function(){ 24536 if(this._current){ 24537 var e = aspect.after(this._current, "onPause", lang.hitch(this, function(arg){ 24538 this._fire("onPause", arguments); 24539 e.remove(); 24540 }), true); 24541 this._current.pause(); 24542 } 24543 return this; 24544 }, 24545 gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ 24546 this.pause(); 24547 var offset = this.duration * percent; 24548 this._current = null; 24549 24550 arrayUtil.some(this._animations, function(a, index){ 24551 if(offset <= a.duration){ 24552 this._current = a; 24553 this._index = index; 24554 return true; 24555 } 24556 offset -= a.duration; 24557 return false; 24558 }, this); 24559 if(this._current){ 24560 this._current.gotoPercent(offset / this._current.duration); 24561 } 24562 if (andPlay) { this.play(); } 24563 return this; 24564 }, 24565 stop: function(/*boolean?*/ gotoEnd){ 24566 if(this._current){ 24567 if(gotoEnd){ 24568 for(; this._index + 1 < this._animations.length; ++this._index){ 24569 this._animations[this._index].stop(true); 24570 } 24571 this._current = this._animations[this._index]; 24572 } 24573 var e = aspect.after(this._current, "onStop", lang.hitch(this, function(arg){ 24574 this._fire("onStop", arguments); 24575 e.remove(); 24576 }), true); 24577 this._current.stop(); 24578 } 24579 return this; 24580 }, 24581 status: function(){ 24582 return this._current ? this._current.status() : "stopped"; 24583 }, 24584 destroy: function(){ 24585 this.stop(); 24586 if(this._onAnimateCtx){ this._onAnimateCtx.remove(); } 24587 if(this._onEndCtx){ this._onEndCtx.remove(); } 24588 } 24589 }); 24590 lang.extend(_chain, _baseObj); 24591 24592 coreFx.chain = function(/*dojo/_base/fx.Animation[]*/ animations){ 24593 // summary: 24594 // Chain a list of `dojo/_base/fx.Animation`s to run in sequence 24595 // 24596 // description: 24597 // Return a `dojo/_base/fx.Animation` which will play all passed 24598 // `dojo/_base/fx.Animation` instances in sequence, firing its own 24599 // synthesized events simulating a single animation. (eg: 24600 // onEnd of this animation means the end of the chain, 24601 // not the individual animations within) 24602 // 24603 // example: 24604 // Once `node` is faded out, fade in `otherNode` 24605 // | require(["dojo/fx"], function(fx){ 24606 // | fx.chain([ 24607 // | fx.fadeIn({ node:node }),
vendor: 2,906 bytes, lines 24608-24703
24608 // | fx.fadeOut({ node:otherNode }) 24609 // | ]).play(); 24610 // | }); 24611 // 24612 return new _chain(animations); // dojo/_base/fx.Animation 24613 }; 24614 24615 var _combine = function(animations){ 24616 this._animations = animations||[]; 24617 this._connects = []; 24618 this._finished = 0; 24619 24620 this.duration = 0; 24621 arrayUtil.forEach(animations, function(a){ 24622 var duration = a.duration; 24623 if(a.delay){ duration += a.delay; } 24624 if(this.duration < duration){ this.duration = duration; } 24625 this._connects.push(aspect.after(a, "onEnd", lang.hitch(this, "_onEnd"), true)); 24626 }, this); 24627 24628 this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration}); 24629 var self = this; 24630 arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"], 24631 function(evt){ 24632 self._connects.push(aspect.after(self._pseudoAnimation, evt, 24633 function(){ self._fire(evt, arguments); }, 24634 true)); 24635 } 24636 ); 24637 }; 24638 lang.extend(_combine, { 24639 _doAction: function(action, args){ 24640 arrayUtil.forEach(this._animations, function(a){ 24641 a[action].apply(a, args); 24642 }); 24643 return this; 24644 }, 24645 _onEnd: function(){ 24646 if(++this._finished > this._animations.length){ 24647 this._fire("onEnd"); 24648 } 24649 }, 24650 _call: function(action, args){ 24651 var t = this._pseudoAnimation; 24652 t[action].apply(t, args); 24653 }, 24654 play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ 24655 this._finished = 0; 24656 this._doAction("play", arguments); 24657 this._call("play", arguments); 24658 return this; 24659 }, 24660 pause: function(){ 24661 this._doAction("pause", arguments); 24662 this._call("pause", arguments); 24663 return this; 24664 }, 24665 gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ 24666 var ms = this.duration * percent; 24667 arrayUtil.forEach(this._animations, function(a){ 24668 a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay); 24669 }); 24670 this._call("gotoPercent", arguments); 24671 return this; 24672 }, 24673 stop: function(/*boolean?*/ gotoEnd){ 24674 this._doAction("stop", arguments); 24675 this._call("stop", arguments); 24676 return this; 24677 }, 24678 status: function(){ 24679 return this._pseudoAnimation.status(); 24680 }, 24681 destroy: function(){ 24682 this.stop(); 24683 arrayUtil.forEach(this._connects, function(handle){ 24684 handle.remove(); 24685 }); 24686 } 24687 }); 24688 lang.extend(_combine, _baseObj); 24689 24690 coreFx.combine = function(/*dojo/_base/fx.Animation[]*/ animations){ 24691 // summary: 24692 // Combine a list of `dojo/_base/fx.Animation`s to run in parallel 24693 // 24694 // description: 24695 // Combine an array of `dojo/_base/fx.Animation`s to run in parallel, 24696 // providing a new `dojo/_base/fx.Animation` instance encompasing each 24697 // animation, firing standard animation events. 24698 // 24699 // example: 24700 // Fade out `node` while fading in `otherNode` simultaneously 24701 // | require(["dojo/fx"], function(fx){ 24702 // | fx.combine([ 24703 // | fx.fadeIn({ node:node }),
24704 // | fx.fadeOut({ node:otherNode }) 24705 // | ]).play(); 24706 // | }); 24707 // 24708 // example: 24709 // When the longest animation ends, execute a function: 24710 // | require(["dojo/fx"], function(fx){ 24711 // | var anim = fx.combine([ 24712 // | fx.fadeIn({ node: n, duration:700 }), 24713 // | fx.fadeOut({ node: otherNode, duration: 300 }) 24714 // | ]); 24715 // | aspect.after(anim, "onEnd", function(){ 24716 // | // overall animation is done. 24717 // | }, true); 24718 // | anim.play(); // play the animation 24719 // | }); 24720 // 24721 return new _combine(animations); // dojo/_base/fx.Animation 24722 }; 24723 24724 coreFx.wipeIn = function(/*Object*/ args){ 24725 // summary: 24726 // Expand a node to it's natural height. 24727 // 24728 // description: 24729 // Returns an animation that will expand the 24730 // node defined in 'args' object from it's current height to 24731 // it's natural height (with no scrollbar). 24732 // Node must have no margin/border/padding. 24733 // 24734 // args: Object 24735 // A hash-map of standard `dojo/_base/fx.Animation` constructor properties 24736 // (such as easing: node: duration: and so on) 24737 // 24738 // example: 24739 // | require(["dojo/fx"], function(fx){ 24740 // | fx.wipeIn({ 24741 // | node:"someId" 24742 // | }).play() 24743 // | }); 24744 24745 var node = args.node = dom.byId(args.node), s = node.style, o; 24746 24747 var anim = baseFx.animateProperty(lang.mixin({ 24748 properties: { 24749 height: { 24750 // wrapped in functions so we wait till the last second to query (in case value has changed) 24751 start: function(){ 24752 // start at current [computed] height, but use 1px rather than 0 24753 // because 0 causes IE to display the whole panel 24754 o = s.overflow; 24755 s.overflow = "hidden"; 24756 if(s.visibility == "hidden" || s.display == "none"){ 24757 s.height = "1px"; 24758 s.display = ""; 24759 s.visibility = ""; 24760 return 1; 24761 }else{ 24762 var height = domStyle.get(node, "height"); 24763 return Math.max(height, 1); 24764 } 24765 }, 24766 end: function(){ 24767 return node.scrollHeight; 24768 } 24769 } 24770 } 24771 }, args)); 24772 24773 var fini = function(){ 24774 s.height = "auto"; 24775 s.overflow = o; 24776 }; 24777 aspect.after(anim, "onStop", fini, true); 24778 aspect.after(anim, "onEnd", fini, true); 24779 24780 return anim; // dojo/_base/fx.Animation 24781 }; 24782 24783 coreFx.wipeOut = function(/*Object*/ args){ 24784 // summary: 24785 // Shrink a node to nothing and hide it. 24786 // 24787 // description: 24788 // Returns an animation that will shrink node defined in "args" 24789 // from it's current height to 1px, and then hide it. 24790 // 24791 // args: Object 24792 // A hash-map of standard `dojo/_base/fx.Animation` constructor properties 24793 // (such as easing: node: duration: and so on) 24794 // 24795 // example: 24796 // | require(["dojo/fx"], function(fx){ 24797 // | fx.wipeOut({ node:"someId" }).play() 24798 // | }); 24799 24800 var node = args.node = dom.byId(args.node), s = node.style, o; 24801 24802 var anim = baseFx.animateProperty(lang.mixin({ 24803 properties: { 24804 height: { 24805 end: 1 // 0 causes IE to display the whole panel 24806 } 24807 } 24808 }, args)); 24809 24810 aspect.after(anim, "beforeBegin", function(){ 24811 o = s.overflow; 24812 s.overflow = "hidden"; 24813 s.display = ""; 24814 }, true); 24815 var fini = function(){ 24816 s.overflow = o; 24817 s.height = "auto"; 24818 s.display = "none"; 24819 }; 24820 aspect.after(anim, "onStop", fini, true); 24821 aspect.after(anim, "onEnd", fini, true); 24822 24823 return anim; // dojo/_base/fx.Animation 24824 }; 24825 24826 coreFx.slideTo = function(/*Object*/ args){ 24827 // summary: 24828 // Slide a node to a new top/left position 24829 // 24830 // description: 24831 // Returns an animation that will slide "node" 24832 // defined in args Object from its current position to 24833 // the position defined by (args.left, args.top). 24834 // 24835 // args: Object 24836 // A hash-map of standard `dojo/_base/fx.Animation` constructor properties 24837 // (such as easing: node: duration: and so on). Special args members 24838 // are `top` and `left`, which indicate the new position to slide to. 24839 // 24840 // example: 24841 // | .slideTo({ node: node, left:"40", top:"50", units:"px" }).play() 24842 24843 var node = args.node = dom.byId(args.node), 24844 top = null, left = null; 24845 24846 var init = (function(n){ 24847 return function(){ 24848 var cs = domStyle.getComputedStyle(n); 24849 var pos = cs.position; 24850 top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0); 24851 left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0); 24852 if(pos != 'absolute' && pos != 'relative'){ 24853 var ret = geom.position(n, true); 24854 top = ret.y; 24855 left = ret.x; 24856 n.style.position="absolute"; 24857 n.style.top=top+"px"; 24858 n.style.left=left+"px"; 24859 } 24860 }; 24861 })(node); 24862 init(); 24863 24864 var anim = baseFx.animateProperty(lang.mixin({ 24865 properties: { 24866 top: args.top || 0, 24867 left: args.left || 0 24868 } 24869 }, args)); 24870 aspect.after(anim, "beforeBegin", init, true); 24871 24872 return anim; // dojo/_base/fx.Animation 24873 }; 24874 24875 return coreFx; 24876}); 24877 24878}, 24879'dijit/_Widget':function(){ 24880define([ 24881 "dojo/aspect", // aspect.around 24882 "dojo/_base/config", // config.isDebug 24883 "dojo/_base/connect", // connect.connect 24884 "dojo/_base/declare", // declare 24885 "dojo/has", 24886 "dojo/_base/kernel", // kernel.deprecated 24887 "dojo/_base/lang", // lang.hitch 24888 "dojo/query", 24889 "dojo/ready", 24890 "./registry", // registry.byNode 24891 "./_WidgetBase", 24892 "./_OnDijitClickMixin", 24893 "./_FocusMixin", 24894 "dojo/uacss", // browser sniffing (included for back-compat; subclasses may be using) 24895 "./hccss" // high contrast mode sniffing (included to set CSS classes on <body>, module ret value unused) 24896], function(aspect, config, connect, declare, has, kernel, lang, query, ready, 24897 registry, _WidgetBase, _OnDijitClickMixin, _FocusMixin){ 24898 24899 24900// module: 24901// dijit/_Widget 24902 24903 24904function connectToDomNode(){ 24905 // summary: 24906 // If user connects to a widget method === this function, then they will 24907 // instead actually be connecting the equivalent event on this.domNode 24908} 24909 24910// Trap dojo.connect() calls to connectToDomNode methods, and redirect to _Widget.on() 24911function aroundAdvice(originalConnect){ 24912 return function(obj, event, scope, method){ 24913 if(obj && typeof event == "string" && obj[event] == connectToDomNode){ 24914 return obj.on(event.substring(2).toLowerCase(), lang.hitch(scope, method)); 24915 } 24916 return originalConnect.apply(connect, arguments); 24917 }; 24918} 24919aspect.around(connect, "connect", aroundAdvice); 24920if(kernel.connect){ 24921 aspect.around(kernel, "connect", aroundAdvice); 24922} 24923 24924var _Widget = declare("dijit._Widget", [_WidgetBase, _OnDijitClickMixin, _FocusMixin], { 24925 // summary: 24926 // Old base class for widgets. New widgets should extend `dijit/_WidgetBase` instead 24927 // description: 24928 // Old Base class for Dijit widgets. 24929 // 24930 // Extends _WidgetBase, adding support for: 24931 // 24932 // - declaratively/programatically specifying widget initialization parameters like 24933 // onMouseMove="foo" that call foo when this.domNode gets a mousemove event 24934 // - ondijitclick: 24935 // Support new data-dojo-attach-event="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress 24936 // - focus related functions: 24937 // In particular, the onFocus()/onBlur() callbacks. Driven internally by 24938 // dijit/_base/focus.js. 24939 // - deprecated methods 24940 // - onShow(), onHide(), onClose() 24941 // 24942 // Also, by loading code in dijit/_base, turns on: 24943 // 24944 // - browser sniffing (putting browser class like `dj_ie` on `<html>` node) 24945 // - high contrast mode sniffing (add `dijit_a11y` class to `<body>` if machine is in high contrast mode) 24946 24947 24948 ////////////////// DEFERRED CONNECTS /////////////////// 24949 24950 onClick: connectToDomNode, 24951 /*===== 24952 onClick: function(event){ 24953 // summary: 24954 // Connect to this function to receive notifications of mouse click events. 24955 // event:
24956 // mouse Event 24957 // tags: 24958 // callback 24959 }, 24960 =====*/ 24961 onDblClick: connectToDomNode, 24962 /*===== 24963 onDblClick: function(event){ 24964 // summary: 24965 // Connect to this function to receive notifications of mouse double click events. 24966 // event: 24967 // mouse Event 24968 // tags: 24969 // callback 24970 }, 24971 =====*/ 24972 onKeyDown: connectToDomNode, 24973 /*===== 24974 onKeyDown: function(event){ 24975 // summary: 24976 // Connect to this function to receive notifications of keys being pressed down. 24977 // event: 24978 // key Event 24979 // tags: 24980 // callback 24981 }, 24982 =====*/ 24983 onKeyPress: connectToDomNode, 24984 /*===== 24985 onKeyPress: function(event){ 24986 // summary: 24987 // Connect to this function to receive notifications of printable keys being typed. 24988 // event: 24989 // key Event 24990 // tags: 24991 // callback 24992 }, 24993 =====*/ 24994 onKeyUp: connectToDomNode, 24995 /*===== 24996 onKeyUp: function(event){ 24997 // summary: 24998 // Connect to this function to receive notifications of keys being released. 24999 // event: 25000 // key Event 25001 // tags: 25002 // callback 25003 }, 25004 =====*/ 25005 onMouseDown: connectToDomNode, 25006 /*===== 25007 onMouseDown: function(event){ 25008 // summary: 25009 // Connect to this function to receive notifications of when the mouse button is pressed down. 25010 // event: 25011 // mouse Event 25012 // tags: 25013 // callback 25014 }, 25015 =====*/ 25016 onMouseMove: connectToDomNode, 25017 /*===== 25018 onMouseMove: function(event){ 25019 // summary: 25020 // Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget. 25021 // event: 25022 // mouse Event 25023 // tags: 25024 // callback 25025 }, 25026 =====*/ 25027 onMouseOut: connectToDomNode, 25028 /*===== 25029 onMouseOut: function(event){ 25030 // summary: 25031 // Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget. 25032 // event: 25033 // mouse Event 25034 // tags: 25035 // callback 25036 }, 25037 =====*/ 25038 onMouseOver: connectToDomNode, 25039 /*===== 25040 onMouseOver: function(event){ 25041 // summary: 25042 // Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget. 25043 // event: 25044 // mouse Event 25045 // tags: 25046 // callback 25047 }, 25048 =====*/ 25049 onMouseLeave: connectToDomNode, 25050 /*===== 25051 onMouseLeave: function(event){ 25052 // summary: 25053 // Connect to this function to receive notifications of when the mouse moves off of this widget. 25054 // event: 25055 // mouse Event 25056 // tags: 25057 // callback 25058 }, 25059 =====*/ 25060 onMouseEnter: connectToDomNode, 25061 /*===== 25062 onMouseEnter: function(event){ 25063 // summary: 25064 // Connect to this function to receive notifications of when the mouse moves onto this widget. 25065 // event: 25066 // mouse Event 25067 // tags: 25068 // callback 25069 }, 25070 =====*/ 25071 onMouseUp: connectToDomNode, 25072 /*===== 25073 onMouseUp: function(event){ 25074 // summary: 25075 // Connect to this function to receive notifications of when the mouse button is released. 25076 // event: 25077 // mouse Event 25078 // tags: 25079 // callback 25080 }, 25081 =====*/ 25082 25083 constructor: function(params /*===== ,srcNodeRef =====*/){ 25084 // summary: 25085 // Create the widget. 25086 // params: Object|null 25087 // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) 25088 // and functions, typically callbacks like onClick. 25089 // The hash can contain any of the widget's properties, excluding read-only properties. 25090 // srcNodeRef: DOMNode|String? 25091 // If a srcNodeRef (DOM node) is specified: 25092 // 25093 // - use srcNodeRef.innerHTML as my contents 25094 // - if this is a behavioral widget then apply behavior to that srcNodeRef 25095 // - otherwise, replace srcNodeRef with my generated DOM tree 25096 25097 // extract parameters like onMouseMove that should connect directly to this.domNode 25098 this._toConnect = {}; 25099 for(var name in params){ 25100 if(this[name] === connectToDomNode){ 25101 this._toConnect[name.replace(/^on/, "").toLowerCase()] = params[name]; 25102 delete params[name]; 25103 } 25104 } 25105 }, 25106 25107 postCreate: function(){ 25108 this.inherited(arguments); 25109 25110 // perform connection from this.domNode to user specified handlers (ex: onMouseMove) 25111 for(var name in this._toConnect){ 25112 this.on(name, this._toConnect[name]); 25113 } 25114 delete this._toConnect; 25115 }, 25116 25117 on: function(/*String|Function*/ type, /*Function*/ func){ 25118 if(this[this._onMap(type)] === connectToDomNode){ 25119 // Use connect.connect() rather than on() to get handling for "onmouseenter" on non-IE, 25120 // normalization of onkeypress/onkeydown to behave like firefox, etc. 25121 // Also, need to specify context as "this" rather than the default context of the DOMNode 25122 // Remove in 2.0.
25123 return connect.connect(this.domNode, type.toLowerCase(), this, func); 25124 } 25125 return this.inherited(arguments); 25126 }, 25127 25128 _setFocusedAttr: function(val){ 25129 // Remove this method in 2.0 (or sooner), just here to set _focused == focused, for back compat 25130 // (but since it's a private variable we aren't required to keep supporting it). 25131 this._focused = val; 25132 this._set("focused", val); 25133 }, 25134 25135 ////////////////// DEPRECATED METHODS /////////////////// 25136 25137 setAttribute: function(/*String*/ attr, /*anything*/ value){ 25138 // summary: 25139 // Deprecated. Use set() instead. 25140 // tags: 25141 // deprecated 25142 kernel.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0"); 25143 this.set(attr, value); 25144 }, 25145 25146 attr: function(/*String|Object*/name, /*Object?*/value){ 25147 // summary: 25148 // This method is deprecated, use get() or set() directly. 25149 // name: 25150 // The property to get or set. If an object is passed here and not 25151 // a string, its keys are used as names of attributes to be set 25152 // and the value of the object as values to set in the widget. 25153 // value: 25154 // Optional. If provided, attr() operates as a setter. If omitted, 25155 // the current value of the named property is returned. 25156 // tags: 25157 // deprecated 25158 25159 var args = arguments.length; 25160 if(args >= 2 || typeof name === "object"){ // setter 25161 return this.set.apply(this, arguments); 25162 }else{ // getter 25163 return this.get(name); 25164 } 25165 }, 25166 25167 getDescendants: function(){ 25168 // summary: 25169 // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode. 25170 // This method should generally be avoided as it returns widgets declared in templates, which are 25171 // supposed to be internal/hidden, but it's left here for back-compat reasons. 25172 25173 kernel.deprecated(this.declaredClass+"::getDescendants() is deprecated. Use getChildren() instead.", "", "2.0"); 25174 return this.containerNode ? query('[widgetId]', this.containerNode).map(registry.byNode) : []; // dijit/_WidgetBase[] 25175 }, 25176 25177 ////////////////// MISCELLANEOUS METHODS /////////////////// 25178 25179 _onShow: function(){ 25180 // summary: 25181 // Internal method called when this widget is made visible. 25182 // See `onShow` for details. 25183 this.onShow(); 25184 }, 25185 25186 onShow: function(){ 25187 // summary: 25188 // Called when this widget becomes the selected pane in a 25189 // `dijit/layout/TabContainer`, `dijit/layout/StackContainer`, 25190 // `dijit/layout/AccordionContainer`, etc. 25191 // 25192 // Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`. 25193 // tags: 25194 // callback 25195 }, 25196 25197 onHide: function(){ 25198 // summary: 25199 // Called when another widget becomes the selected pane in a 25200 // `dijit/layout/TabContainer`, `dijit/layout/StackContainer`, 25201 // `dijit/layout/AccordionContainer`, etc. 25202 // 25203 // Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`. 25204 // tags: 25205 // callback 25206 }, 25207 25208 onClose: function(){ 25209 // summary: 25210 // Called when this widget is being displayed as a popup (ex: a Calendar popped 25211 // up from a DateTextBox), and it is hidden. 25212 // This is called from the dijit.popup code, and should not be called directly. 25213 // 25214 // Also used as a parameter for children of `dijit/layout/StackContainer` or subclasses. 25215 // Callback if a user tries to close the child. Child will be closed if this function returns true. 25216 // tags: 25217 // extension 25218 25219 return true; // Boolean 25220 } 25221}); 25222 25223// For back-compat, remove in 2.0. 25224if(has("dijit-legacy-requires")){ 25225 ready(0, function(){ 25226 var requires = ["dijit/_base"]; 25227 require(requires); // use indirection so modules not rolled into a build 25228 }); 25229} 25230return _Widget; 25231}); 25232 25233}, 25234'dijit/_OnDijitClickMixin':function(){ 25235define([ 25236 "dojo/on", 25237 "dojo/_base/array", // array.forEach 25238 "dojo/keys", // keys.ENTER keys.SPACE 25239 "dojo/_base/declare", // declare 25240 "dojo/has", // has("dom-addeventlistener") 25241 "./a11yclick" 25242], function(on, array, keys, declare, has, a11yclick){ 25243 25244 // module: 25245 // dijit/_OnDijitClickMixin 25246 25247 var ret = declare("dijit._OnDijitClickMixin", null, { 25248 // summary: 25249 // Deprecated. New code should access the dijit/a11yclick event directly, ex: 25250 // | this.own(on(node, a11yclick, function(){ ... })); 25251 // 25252 // Mixing in this class will make _WidgetBase.connect(node, "ondijitclick", ...) work. 25253 // It also used to be necessary to make templates with ondijitclick work, but now you can just require 25254 // dijit/a11yclick. 25255 25256 connect: function(obj, event, method){ 25257 // override _WidgetBase.connect() to make this.connect(node, "ondijitclick", ...) work 25258 return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]); 25259 } 25260 }); 25261 25262 ret.a11yclick = a11yclick; // back compat 25263 25264 return ret; 25265}); 25266 25267}, 25268'dijit/a11yclick':function(){ 25269define([ 25270 "dojo/keys", // keys.ENTER keys.SPACE 25271 "dojo/mouse", 25272 "dojo/on", 25273 "dojo/touch" // touch support for click is now there 25274], function(keys, mouse, on, touch){ 25275 25276 // module: 25277 // dijit/a11yclick 25278 25279 /*===== 25280 return { 25281 // summary: 25282 // Custom press, release, and click synthetic events
25283 // which trigger on a left mouse click, touch, or space/enter keyup. 25284 25285 click: function(node, listener){ 25286 // summary: 25287 // Logical click operation for mouse, touch, or keyboard (space/enter key) 25288 }, 25289 press: function(node, listener){ 25290 // summary: 25291 // Mousedown (left button), touchstart, or keydown (space or enter) corresponding to logical click operation. 25292 }, 25293 release: function(node, listener){ 25294 // summary: 25295 // Mouseup (left button), touchend, or keyup (space or enter) corresponding to logical click operation. 25296 }, 25297 move: function(node, listener){ 25298 // summary: 25299 // Mouse cursor or a finger is dragged over the given node. 25300 } 25301 }; 25302 =====*/ 25303 25304 function clickKey(/*Event*/ e){ 25305 // Test if this keyboard event should be tracked as the start (if keydown) or end (if keyup) of a click event. 25306 // Only track for nodes marked to be tracked, and not for buttons or inputs, 25307 // since buttons handle keyboard click natively, and text inputs should not 25308 // prevent typing spaces or newlines. 25309 if((e.keyCode === keys.ENTER || e.keyCode === keys.SPACE) && !/input|button|textarea/i.test(e.target.nodeName)){ 25310 25311 // Test if a node or its ancestor has been marked with the dojoClick property to indicate special processing 25312 for(var node = e.target; node; node = node.parentNode){ 25313 if(node.dojoClick){ return true; } 25314 } 25315 } 25316 } 25317 25318 var lastKeyDownNode; 25319 25320 on(document, "keydown", function(e){ 25321 //console.log("a11yclick: onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode)); 25322 if(clickKey(e)){
25323 // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work 25324 lastKeyDownNode = e.target; 25325 25326 // Prevent viewport scrolling on space key in IE<9. 25327 // (Reproducible on test_Button.html on any of the first dijit/form/Button examples) 25328 e.preventDefault(); 25329 }else{ 25330 lastKeyDownNode = null; 25331 } 25332 }); 25333 25334 on(document, "keyup", function(e){ 25335 //console.log("a11yclick: onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode)); 25336 if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey 25337 //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert 25338 lastKeyDownNode = null; 25339 25340 on.emit(e.target, "click", { 25341 cancelable: true, 25342 bubbles: true, 25343 ctrlKey: e.ctrlKey, 25344 shiftKey: e.shiftKey, 25345 metaKey: e.metaKey, 25346 altKey: e.altKey, 25347 _origType: e.type 25348 }); 25349 } 25350 }); 25351 25352 // I want to return a hash of the synthetic events, but for backwards compatibility the main return value 25353 // needs to be the click event. Change for 2.0. 25354 25355 var click = function(node, listener){ 25356 // Set flag on node so that keydown/keyup above emits click event. 25357 // Also enables fast click processing from dojo/touch. 25358 node.dojoClick = true; 25359 25360 return on(node, "click", listener); 25361 }; 25362 click.click = click; // forward compatibility with 2.0 25363 25364 click.press = function(node, listener){ 25365 var touchListener = on(node, touch.press, function(evt){ 25366 if(evt.type == "mousedown" && !mouse.isLeft(evt)){ 25367 // Ignore right click 25368 return; 25369 } 25370 listener(evt); 25371 }), keyListener = on(node, "keydown", function(evt){ 25372 if(evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE){ 25373 listener(evt); 25374 } 25375 }); 25376 return { 25377 remove: function(){ 25378 touchListener.remove(); 25379 keyListener.remove(); 25380 } 25381 }; 25382 }; 25383 25384 click.release = function(node, listener){ 25385 var touchListener = on(node, touch.release, function(evt){ 25386 if(evt.type == "mouseup" && !mouse.isLeft(evt)){ 25387 // Ignore right click 25388 return; 25389 } 25390 listener(evt); 25391 }), keyListener = on(node, "keyup", function(evt){ 25392 if(evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE){ 25393 listener(evt); 25394 } 25395 }); 25396 return { 25397 remove: function(){ 25398 touchListener.remove(); 25399 keyListener.remove(); 25400 } 25401 }; 25402 }; 25403 25404 click.move = touch.move; // just for convenience 25405 25406 return click; 25407}); 25408 25409}, 25410'dojo/touch':function(){ 25411define(["./_base/kernel", "./aspect", "./dom", "./dom-class", "./_base/lang", "./on", "./has", "./mouse", "./domReady", "./_base/window"], 25412function(dojo, aspect, dom, domClass, lang, on, has, mouse, domReady, win){ 25413 25414 // module: 25415 // dojo/touch 25416 25417 var ios4 = has("ios") < 5; 25418 25419 // Detect if platform supports Pointer Events, and if so, the names of the events (pointerdown vs. MSPointerDown). 25420 var hasPointer = has("pointer-events") || has("MSPointer"), 25421 pointer = (function () { 25422 var pointer = {}; 25423 for (var type in { down: 1, move: 1, up: 1, cancel: 1, over: 1, out: 1 }) { 25424 pointer[type] = has("MSPointer") ? 25425 "MSPointer" + type.charAt(0).toUpperCase() + type.slice(1) : 25426 "pointer" + type; 25427 } 25428 return pointer; 25429 })(); 25430 25431 // Detect if platform supports the webkit touchstart/touchend/... events 25432 var hasTouch = has("touch-events"); 25433 25434 // Click generation variables 25435 var clicksInited, clickTracker, useTarget = false, clickTarget, clickX, clickY, clickDx, clickDy, clickTime; 25436 25437 // Time of most recent touchstart, touchmove, or touchend event 25438 var lastTouch; 25439 25440 function dualEvent(mouseType, touchType, pointerType){ 25441 // Returns synthetic event that listens for both the specified mouse event and specified touch event. 25442 // But ignore fake mouse events that were generated due to the user touching the screen. 25443 if(hasPointer && pointerType){ 25444 // IE10+: MSPointer* events are designed to handle both mouse and touch in a uniform way, 25445 // so just use that regardless of hasTouch. 25446 return function(node, listener){ 25447 return on(node, pointerType, listener); 25448 } 25449 }else if(hasTouch){ 25450 return function(node, listener){ 25451 var handle1 = on(node, touchType, function(evt){ 25452 listener.call(this, evt); 25453 25454 // On slow mobile browsers (see https://bugs.dojotoolkit.org/ticket/17634), 25455 // a handler for a touch event may take >1s to run. That time shouldn't 25456 // be included in the calculation for lastTouch. 25457 lastTouch = (new Date()).getTime(); 25458 }), 25459 handle2 = on(node, mouseType, function(evt){ 25460 if(!lastTouch || (new Date()).getTime() > lastTouch + 1000){ 25461 listener.call(this, evt); 25462 } 25463 });
vendor: 4,847 bytes, lines 25464-25582
25464 return { 25465 remove: function(){ 25466 handle1.remove(); 25467 handle2.remove(); 25468 } 25469 }; 25470 }; 25471 }else{ 25472 // Avoid creating listeners for touch events on performance sensitive older browsers like IE6 25473 return function(node, listener){ 25474 return on(node, mouseType, listener); 25475 } 25476 } 25477 } 25478 25479 function marked(/*DOMNode*/ node){ 25480 // Search for node ancestor has been marked with the dojoClick property to indicate special processing. 25481 // Returns marked ancestor. 25482 do{ 25483 if(node.dojoClick !== undefined){ return node; } 25484 }while(node = node.parentNode); 25485 } 25486 25487 function doClicks(e, moveType, endType){ 25488 // summary: 25489 // Setup touch listeners to generate synthetic clicks immediately (rather than waiting for the browser 25490 // to generate clicks after the double-tap delay) and consistently (regardless of whether event.preventDefault() 25491 // was called in an event listener. Synthetic clicks are generated only if a node or one of its ancestors has 25492 // its dojoClick property set to truthy. If a node receives synthetic clicks because one of its ancestors has its 25493 // dojoClick property set to truthy, you can disable synthetic clicks on this node by setting its own dojoClick property 25494 // to falsy. 25495 25496 var markedNode = marked(e.target); 25497 clickTracker = !e.target.disabled && markedNode && markedNode.dojoClick; // click threshold = true, number, x/y object, or "useTarget" 25498 if(clickTracker){ 25499 useTarget = (clickTracker == "useTarget"); 25500 clickTarget = (useTarget?markedNode:e.target); 25501 if(useTarget){ 25502 // We expect a click, so prevent any other 25503 // default action on "touchpress" 25504 e.preventDefault(); 25505 } 25506 clickX = e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX; 25507 clickY = e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY; 25508 clickDx = (typeof clickTracker == "object" ? clickTracker.x : (typeof clickTracker == "number" ? clickTracker : 0)) || 4; 25509 clickDy = (typeof clickTracker == "object" ? clickTracker.y : (typeof clickTracker == "number" ? clickTracker : 0)) || 4; 25510 25511 // add move/end handlers only the first time a node with dojoClick is seen, 25512 // so we don't add too much overhead when dojoClick is never set. 25513 if(!clicksInited){ 25514 clicksInited = true; 25515 25516 function updateClickTracker(e){ 25517 if(useTarget){ 25518 clickTracker = dom.isDescendant( 25519 win.doc.elementFromPoint( 25520 (e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX), 25521 (e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY)), 25522 clickTarget); 25523 }else{ 25524 clickTracker = clickTracker && 25525 (e.changedTouches ? e.changedTouches[0].target : e.target) == clickTarget && 25526 Math.abs((e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX) - clickX) <= clickDx && 25527 Math.abs((e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY) - clickY) <= clickDy; 25528 } 25529 } 25530 25531 win.doc.addEventListener(moveType, function(e){ 25532 updateClickTracker(e); 25533 if(useTarget){ 25534 // prevent native scroll event and ensure touchend is 25535 // fire after touch moves between press and release. 25536 e.preventDefault(); 25537 } 25538 }, true); 25539 25540 win.doc.addEventListener(endType, function(e){ 25541 updateClickTracker(e); 25542 if(clickTracker){ 25543 clickTime = (new Date()).getTime(); 25544 var target = (useTarget?clickTarget:e.target); 25545 if(target.tagName === "LABEL"){ 25546 // when clicking on a label, forward click to its associated input if any 25547 target = dom.byId(target.getAttribute("for")) || target; 25548 } 25549 //some attributes can be on the Touch object, not on the Event: 25550 //http://www.w3.org/TR/touch-events/#touch-interface 25551 var src = (e.changedTouches) ? e.changedTouches[0] : e; 25552 //create the synthetic event. 25553 //http://www.w3.org/TR/DOM-Level-3-Events/#widl-MouseEvent-initMouseEvent 25554 var clickEvt = document.createEvent("MouseEvents"); 25555 clickEvt._dojo_click = true; 25556 clickEvt.initMouseEvent("click", 25557 true, //bubbles 25558 true, //cancelable 25559 e.view, 25560 e.detail, 25561 src.screenX, 25562 src.screenY, 25563 src.clientX, 25564 src.clientY, 25565 e.ctrlKey, 25566 e.altKey, 25567 e.shiftKey, 25568 e.metaKey, 25569 0, //button 25570 null //related target 25571 ); 25572 setTimeout(function(){ 25573 on.emit(target, "click", clickEvt); 25574 25575 // refresh clickTime in case app-defined click handler took a long time to run 25576 clickTime = (new Date()).getTime(); 25577 }, 0); 25578 } 25579 }, true); 25580 25581 function stopNativeEvents(type){ 25582 win.doc.addEventListener(type, function(e){
25583 // Stop native events when we emitted our own click event. Note that the native click may occur 25584 // on a different node than the synthetic click event was generated on. For example, 25585 // click on a menu item, causing the menu to disappear, and then (~300ms later) the browser 25586 // sends a click event to the node that was *underneath* the menu. So stop all native events 25587 // sent shortly after ours, similar to what is done in dualEvent. 25588 // The INPUT.dijitOffScreen test is for offscreen inputs used in dijit/form/Button, on which 25589 // we call click() explicitly, we don't want to stop this event. 25590 if(!e._dojo_click && 25591 (new Date()).getTime() <= clickTime + 1000 && 25592 !(e.target.tagName == "INPUT" && domClass.contains(e.target, "dijitOffScreen"))){ 25593 e.stopPropagation(); 25594 e.stopImmediatePropagation && e.stopImmediatePropagation(); 25595 if(type == "click" && (e.target.tagName != "INPUT" || e.target.type == "radio" || e.target.type == "checkbox") 25596 && e.target.tagName != "TEXTAREA" && e.target.tagName != "AUDIO" && e.target.tagName != "VIDEO"){ 25597 // preventDefault() breaks textual <input>s on android, keyboard doesn't popup, 25598 // but it is still needed for checkboxes and radio buttons, otherwise in some cases 25599 // the checked state becomes inconsistent with the widget's state 25600 e.preventDefault(); 25601 } 25602 } 25603 }, true); 25604 } 25605 25606 stopNativeEvents("click"); 25607 25608 // We also stop mousedown/up since these would be sent well after with our "fast" click (300ms), 25609 // which can confuse some dijit widgets. 25610 stopNativeEvents("mousedown"); 25611 stopNativeEvents("mouseup"); 25612 } 25613 } 25614 } 25615 25616 var hoveredNode; 25617 25618 if(hasPointer){ 25619 // MSPointer (IE10+) already has support for over and out, so we just need to init click support 25620 domReady(function(){ 25621 win.doc.addEventListener(pointer.down, function(evt){ 25622 doClicks(evt, pointer.move, pointer.up); 25623 }, true); 25624 }); 25625 }else if(hasTouch){ 25626 domReady(function(){ 25627 // Keep track of currently hovered node 25628 hoveredNode = win.body(); // currently hovered node 25629 25630 win.doc.addEventListener("touchstart", function(evt){ 25631 lastTouch = (new Date()).getTime(); 25632 25633 // Precede touchstart event with touch.over event. DnD depends on this. 25634 // Use addEventListener(cb, true) to run cb before any touchstart handlers on node run, 25635 // and to ensure this code runs even if the listener on the node does event.stop(). 25636 var oldNode = hoveredNode; 25637 hoveredNode = evt.target; 25638 on.emit(oldNode, "dojotouchout", { 25639 relatedTarget: hoveredNode, 25640 bubbles: true 25641 }); 25642 on.emit(hoveredNode, "dojotouchover", { 25643 relatedTarget: oldNode, 25644 bubbles: true 25645 }); 25646 25647 doClicks(evt, "touchmove", "touchend"); // init click generation 25648 }, true); 25649 25650 function copyEventProps(evt){ 25651 // Make copy of event object and also set bubbles:true. Used when calling on.emit(). 25652 var props = lang.delegate(evt, { 25653 bubbles: true 25654 }); 25655 25656 if(has("ios") >= 6){ 25657 // On iOS6 "touches" became a non-enumerable property, which 25658 // is not hit by for...in. Ditto for the other properties below. 25659 props.touches = evt.touches; 25660 props.altKey = evt.altKey; 25661 props.changedTouches = evt.changedTouches; 25662 props.ctrlKey = evt.ctrlKey; 25663 props.metaKey = evt.metaKey; 25664 props.shiftKey = evt.shiftKey; 25665 props.targetTouches = evt.targetTouches; 25666 } 25667 25668 return props; 25669 } 25670 25671 on(win.doc, "touchmove", function(evt){ 25672 lastTouch = (new Date()).getTime(); 25673 25674 var newNode = win.doc.elementFromPoint( 25675 evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords 25676 evt.pageY - (ios4 ? 0 : win.global.pageYOffset) 25677 ); 25678 25679 if(newNode){ 25680 // Fire synthetic touchover and touchout events on nodes since the browser won't do it natively. 25681 if(hoveredNode !== newNode){ 25682 // touch out on the old node 25683 on.emit(hoveredNode, "dojotouchout", { 25684 relatedTarget: newNode, 25685 bubbles: true 25686 });
vendor: 1,748 bytes, lines 25687-25728
25687 25688 // touchover on the new node 25689 on.emit(newNode, "dojotouchover", { 25690 relatedTarget: hoveredNode, 25691 bubbles: true 25692 }); 25693 25694 hoveredNode = newNode; 25695 } 25696 25697 // Unlike a listener on "touchmove", on(node, "dojotouchmove", listener) fires when the finger 25698 // drags over the specified node, regardless of which node the touch started on. 25699 if(!on.emit(newNode, "dojotouchmove", copyEventProps(evt))){ 25700 // emit returns false when synthetic event "dojotouchmove" is cancelled, so we prevent the 25701 // default behavior of the underlying native event "touchmove". 25702 evt.preventDefault(); 25703 } 25704 } 25705 }); 25706 25707 // Fire a dojotouchend event on the node where the finger was before it was removed from the screen. 25708 // This is different than the native touchend, which fires on the node where the drag started. 25709 on(win.doc, "touchend", function(evt){ 25710 lastTouch = (new Date()).getTime(); 25711 var node = win.doc.elementFromPoint( 25712 evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords 25713 evt.pageY - (ios4 ? 0 : win.global.pageYOffset) 25714 ) || win.body(); // if out of the screen 25715 25716 on.emit(node, "dojotouchend", copyEventProps(evt)); 25717 }); 25718 }); 25719 } 25720 25721 //device neutral events - touch.press|move|release|cancel/over/out 25722 var touch = { 25723 press: dualEvent("mousedown", "touchstart", pointer.down), 25724 move: dualEvent("mousemove", "dojotouchmove", pointer.move), 25725 release: dualEvent("mouseup", "dojotouchend", pointer.up), 25726 cancel: dualEvent(mouse.leave, "touchcancel", hasPointer ? pointer.cancel : null), 25727 over: dualEvent("mouseover", "dojotouchover", pointer.over), 25728 out: dualEvent("mouseout", "dojotouchout", pointer.out),
25729 enter: mouse._eventHandler(dualEvent("mouseover","dojotouchover", pointer.over)), 25730 leave: mouse._eventHandler(dualEvent("mouseout", "dojotouchout", pointer.out)) 25731 }; 25732 25733 /*===== 25734 touch = { 25735 // summary: 25736 // This module provides unified touch event handlers by exporting 25737 // press, move, release and cancel which can also run well on desktop. 25738 // Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html 25739 // Also, if the dojoClick property is set to truthy on a DOM node, dojo/touch generates 25740 // click events immediately for this node and its descendants (except for descendants that 25741 // have a dojoClick property set to falsy), to avoid the delay before native browser click events, 25742 // and regardless of whether evt.preventDefault() was called in a touch.press event listener. 25743 // 25744 // example: 25745 // Used with dojo/on 25746 // | define(["dojo/on", "dojo/touch"], function(on, touch){ 25747 // | on(node, touch.press, function(e){}); 25748 // | on(node, touch.move, function(e){}); 25749 // | on(node, touch.release, function(e){}); 25750 // | on(node, touch.cancel, function(e){}); 25751 // example: 25752 // Used with touch.* directly 25753 // | touch.press(node, function(e){}); 25754 // | touch.move(node, function(e){}); 25755 // | touch.release(node, function(e){}); 25756 // | touch.cancel(node, function(e){}); 25757 // example: 25758 // Have dojo/touch generate clicks without delay, with a default move threshold of 4 pixels 25759 // | node.dojoClick = true; 25760 // example: 25761 // Have dojo/touch generate clicks without delay, with a move threshold of 10 pixels horizontally and vertically 25762 // | node.dojoClick = 10; 25763 // example: 25764 // Have dojo/touch generate clicks without delay, with a move threshold of 50 pixels horizontally and 10 pixels vertically 25765 // | node.dojoClick = {x:50, y:5}; 25766 // example: 25767 // Disable clicks without delay generated by dojo/touch on a node that has an ancestor with property dojoClick set to truthy 25768 // | node.dojoClick = false; 25769 25770 press: function(node, listener){ 25771 // summary: 25772 // Register a listener to 'touchstart'|'mousedown' for the given node 25773 // node: Dom 25774 // Target node to listen to 25775 // listener: Function 25776 // Callback function 25777 // returns: 25778 // A handle which will be used to remove the listener by handle.remove() 25779 }, 25780 move: function(node, listener){ 25781 // summary:
25782 // Register a listener that fires when the mouse cursor or a finger is dragged over the given node. 25783 // node: Dom 25784 // Target node to listen to 25785 // listener: Function 25786 // Callback function 25787 // returns: 25788 // A handle which will be used to remove the listener by handle.remove() 25789 }, 25790 release: function(node, listener){ 25791 // summary: 25792 // Register a listener to releasing the mouse button while the cursor is over the given node 25793 // (i.e. "mouseup") or for removing the finger from the screen while touching the given node. 25794 // node: Dom 25795 // Target node to listen to 25796 // listener: Function 25797 // Callback function 25798 // returns: 25799 // A handle which will be used to remove the listener by handle.remove() 25800 }, 25801 cancel: function(node, listener){ 25802 // summary: 25803 // Register a listener to 'touchcancel'|'mouseleave' for the given node 25804 // node: Dom 25805 // Target node to listen to 25806 // listener: Function 25807 // Callback function 25808 // returns: 25809 // A handle which will be used to remove the listener by handle.remove() 25810 }, 25811 over: function(node, listener){ 25812 // summary: 25813 // Register a listener to 'mouseover' or touch equivalent for the given node 25814 // node: Dom 25815 // Target node to listen to 25816 // listener: Function 25817 // Callback function 25818 // returns: 25819 // A handle which will be used to remove the listener by handle.remove() 25820 }, 25821 out: function(node, listener){ 25822 // summary: 25823 // Register a listener to 'mouseout' or touch equivalent for the given node 25824 // node: Dom 25825 // Target node to listen to 25826 // listener: Function 25827 // Callback function 25828 // returns: 25829 // A handle which will be used to remove the listener by handle.remove() 25830 },
25831 enter: function(node, listener){ 25832 // summary: 25833 // Register a listener to mouse.enter or touch equivalent for the given node 25834 // node: Dom 25835 // Target node to listen to 25836 // listener: Function 25837 // Callback function 25838 // returns: 25839 // A handle which will be used to remove the listener by handle.remove() 25840 }, 25841 leave: function(node, listener){ 25842 // summary: 25843 // Register a listener to mouse.leave or touch equivalent for the given node 25844 // node: Dom 25845 // Target node to listen to 25846 // listener: Function 25847 // Callback function 25848 // returns: 25849 // A handle which will be used to remove the listener by handle.remove() 25850 } 25851 }; 25852 =====*/ 25853 25854 1 && (dojo.touch = touch); 25855 25856 return touch; 25857}); 25858 25859}, 25860'dijit/_FocusMixin':function(){ 25861define([ 25862 "./focus", 25863 "./_WidgetBase", 25864 "dojo/_base/declare", // declare 25865 "dojo/_base/lang" // lang.extend 25866], function(focus, _WidgetBase, declare, lang){ 25867 25868 // module: 25869 // dijit/_FocusMixin 25870 25871 // We don't know where _FocusMixin will occur in the inheritance chain, but we need the _onFocus()/_onBlur() below 25872 // to be last in the inheritance chain, so mixin to _WidgetBase. 25873 lang.extend(_WidgetBase, { 25874 // focused: [readonly] Boolean 25875 // This widget or a widget it contains has focus, or is "active" because 25876 // it was recently clicked. 25877 focused: false, 25878 25879 onFocus: function(){ 25880 // summary: 25881 // Called when the widget becomes "active" because 25882 // it or a widget inside of it either has focus, or has recently 25883 // been clicked. 25884 // tags: 25885 // callback 25886 }, 25887 25888 onBlur: function(){ 25889 // summary: 25890 // Called when the widget stops being "active" because 25891 // focus moved to something outside of it, or the user 25892 // clicked somewhere outside of it, or the widget was 25893 // hidden. 25894 // tags: 25895 // callback 25896 }, 25897 25898 _onFocus: function(){ 25899 // summary: 25900 // This is where widgets do processing for when they are active, 25901 // such as changing CSS classes. See onFocus() for more details. 25902 // tags: 25903 // protected 25904 this.onFocus(); 25905 }, 25906 25907 _onBlur: function(){ 25908 // summary: 25909 // This is where widgets do processing for when they stop being active, 25910 // such as changing CSS classes. See onBlur() for more details. 25911 // tags: 25912 // protected 25913 this.onBlur(); 25914 } 25915 }); 25916 25917 return declare("dijit._FocusMixin", null, { 25918 // summary: 25919 // Mixin to widget to provide _onFocus() and _onBlur() methods that
25920 // fire when a widget or its descendants get/lose focus 25921 25922 // flag that I want _onFocus()/_onBlur() notifications from focus manager 25923 _focusManager: focus 25924 }); 25925 25926}); 25927 25928}, 25929'dijit/focus':function(){ 25930define([ 25931 "dojo/aspect", 25932 "dojo/_base/declare", // declare 25933 "dojo/dom", // domAttr.get dom.isDescendant 25934 "dojo/dom-attr", // domAttr.get dom.isDescendant 25935 "dojo/dom-class", 25936 "dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy 25937 "dojo/Evented", 25938 "dojo/_base/lang", // lang.hitch 25939 "dojo/on", 25940 "dojo/domReady", 25941 "dojo/sniff", // has("ie") 25942 "dojo/Stateful", 25943 "dojo/_base/window", // win.body 25944 "dojo/window", // winUtils.get 25945 "./a11y", // a11y.isTabNavigable 25946 "./registry", // registry.byId 25947 "./main" // to set dijit.focus 25948], function(aspect, declare, dom, domAttr, domClass, domConstruct, Evented, lang, on, domReady, has, Stateful, win, winUtils, 25949 a11y, registry, dijit){ 25950 25951 // module: 25952 // dijit/focus 25953 25954 // Time of the last focusin event 25955 var lastFocusin; 25956 25957 // Time of the last touch/mousedown or focusin event 25958 var lastTouchOrFocusin; 25959 25960 var FocusManager = declare([Stateful, Evented], { 25961 // summary: 25962 // Tracks the currently focused node, and which widgets are currently "active". 25963 // Access via require(["dijit/focus"], function(focus){ ... }). 25964 // 25965 // A widget is considered active if it or a descendant widget has focus, 25966 // or if a non-focusable node of this widget or a descendant was recently clicked. 25967 // 25968 // Call focus.watch("curNode", callback) to track the current focused DOMNode, 25969 // or focus.watch("activeStack", callback) to track the currently focused stack of widgets. 25970 // 25971 // Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when 25972 // when widgets become active/inactive 25973 // 25974 // Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist. 25975 25976 // curNode: DomNode 25977 // Currently focused item on screen 25978 curNode: null, 25979 25980 // activeStack: dijit/_WidgetBase[] 25981 // List of currently active widgets (focused widget and it's ancestors) 25982 activeStack: [], 25983 25984 constructor: function(){ 25985 // Don't leave curNode/prevNode pointing to bogus elements 25986 var check = lang.hitch(this, function(node){ 25987 if(dom.isDescendant(this.curNode, node)){ 25988 this.set("curNode", null); 25989 } 25990 if(dom.isDescendant(this.prevNode, node)){ 25991 this.set("prevNode", null); 25992 } 25993 }); 25994 aspect.before(domConstruct, "empty", check); 25995 aspect.before(domConstruct, "destroy", check); 25996 }, 25997 25998 registerIframe: function(/*DomNode*/ iframe){ 25999 // summary: 26000 // Registers listeners on the specified iframe so that any click 26001 // or focus event on that iframe (or anything in it) is reported 26002 // as a focus/click event on the `<iframe>` itself. 26003 // description: 26004 // Currently only used by editor. 26005 // returns: 26006 // Handle with remove() method to deregister. 26007 return this.registerWin(iframe.contentWindow, iframe); 26008 }, 26009 26010 registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){ 26011 // summary: 26012 // Registers listeners on the specified window (either the main 26013 // window or an iframe's window) to detect when the user has clicked somewhere 26014 // or focused somewhere. 26015 // description: 26016 // Users should call registerIframe() instead of this method. 26017 // targetWindow: 26018 // If specified this is the window associated with the iframe, 26019 // i.e. iframe.contentWindow. 26020 // effectiveNode: 26021 // If specified, report any focus events inside targetWindow as 26022 // an event on effectiveNode, rather than on evt.target. 26023 // returns: 26024 // Handle with remove() method to deregister. 26025 26026 // TODO: make this function private in 2.0; Editor/users should call registerIframe(), 26027 26028 // Listen for blur and focus events on targetWindow's document. 26029 var _this = this, 26030 body = targetWindow.document && targetWindow.document.body; 26031 26032 if(body){ 26033 // Listen for touches or mousedowns... could also use dojo/touch.press here. 26034 var event = has("pointer-events") ? "pointerdown" : has("MSPointer") ? "MSPointerDown" : 26035 has("touch-events") ? "mousedown, touchstart" : "mousedown"; 26036 var mdh = on(targetWindow.document, event, function(evt){ 26037 // workaround weird IE bug where the click is on an orphaned node 26038 // (first time clicking a Select/DropDownButton inside a TooltipDialog). 26039 // actually, strangely this is happening on latest chrome too. 26040 if(evt && evt.target && evt.target.parentNode == null){ 26041 return; 26042 } 26043 26044 _this._onTouchNode(effectiveNode || evt.target, "mouse"); 26045 }); 26046 26047 var fih = on(body, 'focusin', function(evt){ 26048 // When you refocus the browser window, IE gives an event with an empty srcElement 26049 if(!evt.target.tagName) { return; } 26050 26051 // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1, 26052 // ignore those events 26053 var tag = evt.target.tagName.toLowerCase(); 26054 if(tag == "#document" || tag == "body"){ return; } 26055 26056 if(a11y.isFocusable(evt.target)){ 26057 _this._onFocusNode(effectiveNode || evt.target); 26058 }else{ 26059 // Previous code called _onTouchNode() for any activate event on a non-focusable node. Can 26060 // probably just ignore such an event as it will be handled by onmousedown handler above, but 26061 // leaving the code for now. 26062 _this._onTouchNode(effectiveNode || evt.target); 26063 } 26064 }); 26065 26066 var foh = on(body, 'focusout', function(evt){ 26067 _this._onBlurNode(effectiveNode || evt.target); 26068 }); 26069 26070 return { 26071 remove: function(){ 26072 mdh.remove(); 26073 fih.remove(); 26074 foh.remove(); 26075 mdh = fih = foh = null; 26076 body = null; // prevent memory leak (apparent circular reference via closure) 26077 } 26078 }; 26079 } 26080 }, 26081 26082 _onBlurNode: function(/*DomNode*/ node){ 26083 // summary:
26084 // Called when focus leaves a node. 26085 // Usually ignored, _unless_ it *isn't* followed by touching another node, 26086 // which indicates that we tabbed off the last field on the page, 26087 // in which case every widget is marked inactive 26088 26089 var now = (new Date()).getTime(); 26090 26091 // IE9+ and chrome have a problem where focusout events come after the corresponding focusin event. 26092 // For chrome problem see https://bugs.dojotoolkit.org/ticket/17668. 26093 // IE problem happens when moving focus from the Editor's <iframe> to a normal DOMNode. 26094 if(now < lastFocusin + 100){ 26095 return; 26096 } 26097 26098 // If the blur event isn't followed by a focus event, it means the user clicked on something unfocusable, 26099 // so clear focus. 26100 if(this._clearFocusTimer){ 26101 clearTimeout(this._clearFocusTimer); 26102 } 26103 this._clearFocusTimer = setTimeout(lang.hitch(this, function(){ 26104 this.set("prevNode", this.curNode); 26105 this.set("curNode", null); 26106 }), 0); 26107 26108 // Unset timer to zero-out widget stack; we'll reset it below if appropriate. 26109 if(this._clearActiveWidgetsTimer){ 26110 clearTimeout(this._clearActiveWidgetsTimer); 26111 } 26112 26113 if(now < lastTouchOrFocusin + 100){ 26114 // This blur event is coming late (after the call to _onTouchNode() rather than before. 26115 // So let _onTouchNode() handle setting the widget stack. 26116 // See https://bugs.dojotoolkit.org/ticket/17668 26117 return; 26118 } 26119 26120 // If the blur event isn't followed (or preceded) by a focus or touch event then mark all widgets as inactive. 26121 this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){ 26122 delete this._clearActiveWidgetsTimer; 26123 this._setStack([]); 26124 }), 0); 26125 }, 26126 26127 _onTouchNode: function(/*DomNode*/ node, /*String*/ by){ 26128 // summary: 26129 // Callback when node is focused or touched. 26130 // Note that _onFocusNode() calls _onTouchNode(). 26131 // node: 26132 // The node that was touched. 26133 // by: 26134 // "mouse" if the focus/touch was caused by a mouse down event 26135 26136 // Keep track of time of last focusin or touch event. 26137 lastTouchOrFocusin = (new Date()).getTime(); 26138 26139 if(this._clearActiveWidgetsTimer){ 26140 // forget the recent blur event 26141 clearTimeout(this._clearActiveWidgetsTimer); 26142 delete this._clearActiveWidgetsTimer; 26143 } 26144 26145 // if the click occurred on the scrollbar of a dropdown, treat it as a click on the dropdown, 26146 // even though the scrollbar is technically on the popup wrapper (see #10631) 26147 if(domClass.contains(node, "dijitPopup")){ 26148 node = node.firstChild; 26149 } 26150 26151 // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem) 26152 var newStack=[]; 26153 try{ 26154 while(node){ 26155 var popupParent = domAttr.get(node, "dijitPopupParent"); 26156 if(popupParent){ 26157 node=registry.byId(popupParent).domNode; 26158 }else if(node.tagName && node.tagName.toLowerCase() == "body"){ 26159 // is this the root of the document or just the root of an iframe? 26160 if(node === win.body()){ 26161 // node is the root of the main document 26162 break; 26163 } 26164 // otherwise, find the iframe this node refers to (can't access it via parentNode, 26165 // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit 26166 node=winUtils.get(node.ownerDocument).frameElement; 26167 }else{ 26168 // if this node is the root node of a widget, then add widget id to stack, 26169 // except ignore clicks on disabled widgets (actually focusing a disabled widget still works, 26170 // to support MenuItem) 26171 var id = node.getAttribute && node.getAttribute("widgetId"), 26172 widget = id && registry.byId(id); 26173 if(widget && !(by == "mouse" && widget.get("disabled"))){ 26174 newStack.unshift(id); 26175 } 26176 node=node.parentNode; 26177 } 26178 } 26179 }catch(e){ /* squelch */ } 26180 26181 this._setStack(newStack, by); 26182 }, 26183 26184 _onFocusNode: function(/*DomNode*/ node){ 26185 // summary: 26186 // Callback when node is focused 26187 26188 if(!node){ 26189 return; 26190 } 26191 26192 if(node.nodeType == 9){ 26193 // Ignore focus events on the document itself. This is here so that 26194 // (for example) clicking the up/down arrows of a spinner 26195 // (which don't get focus) won't cause that widget to blur. (FF issue) 26196 return; 26197 } 26198 26199 // Keep track of time of last focusin event. 26200 lastFocusin = (new Date()).getTime(); 26201 26202 // There was probably a blur event right before this event, but since we have a new focu
26202s, 26203 // forget about the blur 26204 if(this._clearFocusTimer){ 26205 clearTimeout(this._clearFocusTimer); 26206 delete this._clearFocusTimer; 26207 } 26208 26209 this._onTouchNode(node); 26210 26211 if(node == this.curNode){ return; } 26212 this.set("prevNode", this.curNode); 26213 this.set("curNode", node); 26214 }, 26215 26216 _setStack: function(/*String[]*/ newStack, /*String*/ by){ 26217 // summary: 26218 // The stack of active widgets has changed. Send out appropriate events and records new stack. 26219 // newStack: 26220 // array of widget id's, starting from the top (outermost) widget 26221 // by: 26222 // "mouse" if the focus/touch was caused by a mouse down event 26223 26224 var oldStack = this.activeStack, lastOldIdx = oldStack.length - 1, lastNewIdx = newStack.length - 1; 26225 26226 if(newStack[lastNewIdx] == oldStack[lastOldIdx]){ 26227 // no changes, return now to avoid spurious notifications about changes to activeStack 26228 return; 26229 } 26230 26231 this.set("activeStack", newStack); 26232 26233 var widget, i; 26234 26235 // for all elements that have gone out of focus, set focused=false 26236 for(i = lastOldIdx; i >= 0 && oldStack[i] != newStack[i]; i--){ 26237 widget = registry.byId(oldStack[i]); 26238 if(widget){ 26239 widget._hasBeenBlurred = true; // TODO: used by form widgets, should be moved there 26240 widget.set("focused", false); 26241 if(widget._focusManager == this){ 26242 widget._onBlur(by); 26243 } 26244 this.emit("widget-blur", widget, by); 26245 } 26246 } 26247 26248 // for all element that have come into focus, set focused=true 26249 for(i++; i <= lastNewIdx; i++){ 26250 widget = registry.byId(newStack[i]); 26251 if(widget){ 26252 widget.set("focused", true); 26253 if(widget._focusManager == this){ 26254 widget._onFocus(by); 26255 } 26256 this.emit("widget-focus", widget, by); 26257 } 26258 } 26259 }, 26260 26261 focus: function(node){ 26262 // summary: 26263 // Focus the specified node, suppressing errors if they occur 26264 if(node){ 26265 try{ node.focus(); }catch(e){/*quiet*/} 26266 } 26267 } 26268 }); 26269 26270 var singleton = new FocusManager(); 26271 26272 // register top window and all the iframes it contains 26273 domReady(function(){ 26274 var handle = singleton.registerWin(winUtils.get(document)); 26275 if(has("ie")){ 26276 on(window, "unload", function(){ 26277 if(handle){ // because this gets called twice when doh.robot is running 26278 handle.remove(); 26279 handle = null; 26280 } 26281 }); 26282 } 26283 }); 26284 26285 // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility) 26286 // as a function to set focus. Remove for 2.0. 26287 dijit.focus = function(node){ 26288 singleton.focus(node); // indirection here allows dijit/_base/focus.js to override behavior 26289 }; 26290 for(var attr in singleton){ 26291 if(!/^_/.test(attr)){ 26292 dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr]; 26293 } 26294 } 26295 singleton.watch(function(attr, oldVal, newVal){ 26296 dijit.focus[attr] = newVal; 26297 }); 26298 26299 return singleton; 26300}); 26301 26302}, 26303'dijit/a11y':function(){ 26304define([ 26305 "dojo/_base/array", // array.forEach array.map 26306 "dojo/dom", // dom.byId 26307 "dojo/dom-attr", // domAttr.attr domAttr.has 26308 "dojo/dom-style", // domStyle.style 26309 "dojo/_base/lang", // lang.mixin() 26310 "dojo/sniff", // has("ie") 1 26311 "./main" // for exporting methods to dijit namespace 26312], function(array, dom, domAttr, domStyle, lang, has, dijit){ 26313 26314 // module: 26315 // dijit/a11y 26316 26317 var undefined; 26318 26319 var a11y = { 26320 // summary: 26321 // Accessibility utility functions (keyboard, tab stops, etc.) 26322 26323 _isElementShown: function(/*Element*/ elem){ 26324 var s = domStyle.get(elem); 26325 return (s.visibility != "hidden") 26326 && (s.visibility != "collapsed") 26327 && (s.display != "none") 26328 && (domAttr.get(elem, "type") != "hidden"); 26329 }, 26330 26331 hasDefaultTabStop: function(/*Element*/ elem){ 26332 // summary: 26333 // Tests if element is tab-navigable even without an explicit tabIndex setting 26334 26335 // No explicit tabIndex setting, need to investigate node type 26336 switch(elem.nodeName.toLowerCase()){ 26337 case "a": 26338 // An <a> w/out a tabindex is only navigable if it has an href 26339 return domAttr.has(elem, "href"); 26340 case "area": 26341 case "button": 26342 case "input": 26343 case "object": 26344 case "select": 26345 case "textarea": 26346 // These are navigable by default 26347 return true; 26348 case "iframe": 26349 // If it's an editor <iframe> then it's tab navigable. 26350 var body; 26351 try{ 26352 // non-IE 26353 var contentDocument = elem.contentDocument; 26354 if("designMode" in contentDocument && contentDocument.designMode == "on"){ 26355 return true; 26356 } 26357 body = contentDocument.body; 26358 }catch(e1){
26359 // contentWindow.document isn't accessible within IE7/8 26360 // if the iframe.src points to a foreign url and this 26361 // page contains an element, that could get focus 26362 try{ 26363 body = elem.contentWindow.document.body; 26364 }catch(e2){ 26365 return false; 26366 } 26367 } 26368 return body && (body.contentEditable == 'true' || 26369 (body.firstChild && body.firstChild.contentEditable == 'true')); 26370 default: 26371 return elem.contentEditable == 'true'; 26372 } 26373 }, 26374 26375 effectiveTabIndex: function(/*Element*/ elem){ 26376 // summary: 26377 // Returns effective tabIndex of an element, either a number, or undefined if element isn't focusable. 26378 26379 if(domAttr.get(elem, "disabled")){ 26380 return undefined; 26381 }else if(domAttr.has(elem, "tabIndex")){ 26382 // Explicit tab index setting 26383 return +domAttr.get(elem, "tabIndex");// + to convert string --> number 26384 }else{ 26385 // No explicit tabIndex setting, so depends on node type 26386 return a11y.hasDefaultTabStop(elem) ? 0 : undefined; 26387 } 26388 }, 26389 26390 isTabNavigable: function(/*Element*/ elem){ 26391 // summary: 26392 // Tests if an element is tab-navigable 26393 26394 return a11y.effectiveTabIndex(elem) >= 0; 26395 }, 26396 26397 isFocusable: function(/*Element*/ elem){ 26398 // summary: 26399 // Tests if an element is focusable by tabbing to it, or clicking it with the mouse. 26400 26401 return a11y.effectiveTabIndex(elem) >= -1; 26402 }, 26403 26404 _getTabNavigable: function(/*DOMNode*/ root){ 26405 // summary: 26406 // Finds descendants of the specified root node. 26407 // description: 26408 // Finds the following descendants of the specified root node: 26409 // 26410 // - the first tab-navigable element in document order 26411 // without a tabIndex or with tabIndex="0" 26412 // - the last tab-navigable element in document order 26413 // without a tabIndex or with tabIndex="0" 26414 // - the first element in document order with the lowest 26415 // positive tabIndex value 26416 // - the last element in document order with the highest 26417 // positive tabIndex value 26418 var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {}; 26419 26420 function radioName(node){ 26421 // If this element is part of a radio button group, return the name for that group. 26422 return node && node.tagName.toLowerCase() == "input" && 26423 node.type && node.type.toLowerCase() == "radio" && 26424 node.name && node.name.toLowerCase(); 26425 } 26426 26427 var shown = a11y._isElementShown, effectiveTabIndex = a11y.effectiveTabIndex; 26428 var walkTree = function(/*DOMNode*/ parent){ 26429 for(var child = parent.firstChild; child; child = child.nextSibling){ 26430 // Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE, 26431 // since show() invokes getAttribute("type"), which crash on VML nodes in IE. 26432 if(child.nodeType != 1 || (has("ie") <= 9 && child.scopeName !== "HTML") || !shown(child)){ 26433 continue; 26434 } 26435 26436 var tabindex = effectiveTabIndex(child); 26437 if(tabindex >= 0){ 26438 if(tabindex == 0){ 26439 if(!first){ 26440 first = child; 26441 } 26442 last = child; 26443 }else if(tabindex > 0){ 26444 if(!lowest || tabindex < lowestTabindex){ 26445 lowestTabindex = tabindex; 26446 lowest = child; 26447 } 26448 if(!highest || tabindex >= highestTabindex){ 26449 highestTabindex = tabindex; 26450 highest = child; 26451 } 26452 } 26453 var rn = radioName(child); 26454 if(domAttr.get(child, "checked") && rn){ 26455 radioSelected[rn] = child; 26456 } 26457 } 26458 if(child.nodeName.toUpperCase() != 'SELECT'){ 26459 walkTree(child); 26460 } 26461 } 26462 }; 26463 if(shown(root)){ 26464 walkTree(root); 26465 } 26466 function rs(node){ 26467 // substitute checked radio button for unchecked one, if there is a checked one with the same name. 26468 return radioSelected[radioName(node)] || node; 26469 } 26470 26471 return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) }; 26472 }, 26473 26474 getFirstInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){ 26475 // summary: 26476 // Finds the descendant of the specified root node 26477 // that is first in the tabbing order 26478 var elems = a11y._getTabNavigable(dom.byId(root, doc)); 26479 return elems.lowest ? elems.lowest : elems.first; // DomNode 26480 }, 26481 26482 getLastInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){ 26483 // summary: 26484 // Finds the descendant of the specified root node 26485 // that is last in the tabbing order 26486 var elems = a11y._getTabNavigable(dom.byId(root, doc)); 26487 return elems.last ? elems.last : elems.highest; // DomNode 26488 } 26489 }; 26490 26491 1 && lang.mixin(dijit, a11y); 26492 26493 return a11y; 26494}); 26495 26496}, 26497'dojo/uacss':function(){ 26498define(["./dom-geometry", "./_base/lang", "./domReady", "./sniff", "./_base/window"], 26499 function(geometry, lang, domReady, has, baseWindow){ 26500 26501 // module: 26502 // dojo/uacss 26503 26504 /*===== 26505 return { 26506 // summary: 26507 // Applies pre-set CSS classes to the top-level HTML node, based on: 26508 // 26509 // - browser (ex: dj_ie) 26510 // - browser version (ex: dj_ie6) 26511 // - box model (ex: dj_contentBox) 26512 // - text direction (ex: dijitRtl) 26513 // 26514 // In addition, browser, browser version, and box model are 26515 // combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl. 26516 // 26517 // Returns the has() method. 26518 }; 26519 =====*/ 26520 26521 var 26522 html = baseWindow.doc.documentElement, 26523 ie = has("ie"), 26524 opera = has("opera"), 26525 maj = Math.floor, 26526 ff = has("ff"), 26527 boxModel = geometry.boxModel.replace(/-/,''), 26528 26529 classes = {
26530 "dj_quirks": has("quirks"), 26531 26532 // NOTE: Opera not supported by dijit 26533 "dj_opera": opera, 26534 26535 "dj_khtml": has("khtml"), 26536 26537 "dj_webkit": has("webkit"), 26538 "dj_safari": has("safari"), 26539 "dj_chrome": has("chrome"), 26540 26541 "dj_gecko": has("mozilla"), 26542 26543 "dj_ios": has("ios"), 26544 "dj_android": has("android") 26545 }; // no dojo unsupported browsers 26546 26547 if(ie){ 26548 classes["dj_ie"] = true; 26549 classes["dj_ie" + maj(ie)] = true; 26550 classes["dj_iequirks"] = has("quirks"); 26551 } 26552 if(ff){ 26553 classes["dj_ff" + maj(ff)] = true; 26554 } 26555 26556 classes["dj_" + boxModel] = true; 26557 26558 // apply browser, browser version, and box model class names 26559 var classStr = ""; 26560 for(var clz in classes){ 26561 if(classes[clz]){ 26562 classStr += clz + " "; 26563 } 26564 } 26565 html.className = lang.trim(html.className + " " + classStr); 26566 26567 // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension. 26568 // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl). 26569 domReady(function(){ 26570 if(!geometry.isBodyLtr()){ 26571 var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "); 26572 html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ")); 26573 } 26574 }); 26575 return has; 26576}); 26577 26578}, 26579'dijit/hccss':function(){ 26580define(["dojo/dom-class", "dojo/hccss", "dojo/domReady", "dojo/_base/window"], function(domClass, has, domReady, win){ 26581 26582 // module: 26583 // dijit/hccss 26584 26585 /*===== 26586 return function(){ 26587 // summary: 26588 // Test if computer is in high contrast mode, and sets `dijit_a11y` flag on `<body>` if it is. 26589 // Deprecated, use ``dojo/hccss`` instead. 26590 }; 26591 =====*/ 26592 26593 domReady(function(){ 26594 if(has("highcontrast")){ 26595 domClass.add(win.body(), "dijit_a11y"); 26596 } 26597 }); 26598 26599 return has; 26600}); 26601 26602}, 26603'dojo/hccss':function(){ 26604define([ 26605 "require", // require, require.toUrl 26606 "./_base/config", // config.blankGif 26607 "./dom-class", // domClass.add 26608 "./dom-style", // domStyle.getComputedStyle 26609 "./has", 26610 "./domReady", 26611 "./_base/window" // win.body 26612], function(require, config, domClass, domStyle, has, domReady, win){ 26613 26614 // module: 26615 // dojo/hccss 26616 26617 /*===== 26618 return function(){ 26619 // summary: 26620 // Test if computer is in high contrast mode (i.e. if browser is not displaying background images). 26621 // Defines `has("highcontrast")` and sets `dj_a11y` CSS class on `<body>` if machine is in high contrast mode. 26622 // Returns `has()` method; 26623 }; 26624 =====*/ 26625 26626 // Has() test for when background images aren't displayed. Don't call has("highcontrast") before dojo/domReady!. 26627 has.add("highcontrast", function(){ 26628 // note: if multiple documents, doesn't matter which one we use 26629 var div = win.doc.createElement("div"); 26630 div.style.cssText = "border: 1px solid; border-color:red green; position: absolute; height: 5px; top: -999px;" + 26631 "background-image: url(\"" + (config.blankGif || require.toUrl("./resources/blank.gif")) + "\");"; 26632 win.body().appendChild(div); 26633 26634 var cs = domStyle.getComputedStyle(div), 26635 bkImg = cs.backgroundImage, 26636 hc = (cs.borderTopColor == cs.borderRightColor) || 26637 (bkImg && (bkImg == "none" || bkImg == "url(invalid-url:)" )); 26638 26639 if(has("ie") <= 8){ 26640 div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014 26641 }else{ 26642 win.body().removeChild(div); 26643 } 26644 26645 return hc; 26646 }); 26647 26648 domReady(function(){ 26649 if(has("highcontrast")){ 26650 domClass.add(win.body(), "dj_a11y"); 26651 } 26652 }); 26653 26654 return has; 26655}); 26656 26657}, 26658'dijit/_TemplatedMixin':function(){ 26659define([ 26660 "dojo/cache", // dojo.cache 26661 "dojo/_base/declare", // declare 26662 "dojo/dom-construct", // domConstruct.destroy, domConstruct.toDom 26663 "dojo/_base/lang", // lang.getObject 26664 "dojo/on", 26665 "dojo/sniff", // has("ie") 26666 "dojo/string", // string.substitute string.trim 26667 "./_AttachMixin" 26668], function(cache, declare, domConstruct, lang, on, has, string, _AttachMixin){ 26669 26670 // module: 26671 // dijit/_TemplatedMixin 26672 26673 var _TemplatedMixin = declare("dijit._TemplatedMixin", _AttachMixin, { 26674 // summary: 26675 // Mixin for widgets that are instantiated from a template 26676 26677 // templateString: [protected] String
26678 // A string that represents the widget template. 26679 // Use in conjunction with dojo.cache() to load from a file. 26680 templateString: null, 26681 26682 // templatePath: [protected deprecated] String 26683 // Path to template (HTML file) for this widget relative to dojo.baseUrl. 26684 // Deprecated: use templateString with require([... "dojo/text!..."], ...) instead 26685 templatePath: null, 26686 26687 // skipNodeCache: [protected] Boolean 26688 // If using a cached widget template nodes poses issues for a 26689 // particular widget class, it can set this property to ensure 26690 // that its template is always re-built from a string 26691 _skipNodeCache: false, 26692 26693/*===== 26694 // _rendered: Boolean 26695 // Not normally use, but this flag can be set by the app if the server has already rendered the template, 26696 // i.e. already inlining the template for the widget into the main page. Reduces _TemplatedMixin to 26697 // just function like _AttachMixin. 26698 _rendered: false, 26699=====*/ 26700 26701 // Set _AttachMixin.searchContainerNode to true for back-compat for widgets that have data-dojo-attach-point's 26702 // and events inside this.containerNode. Remove for 2.0. 26703 searchContainerNode: true, 26704 26705 _stringRepl: function(tmpl){ 26706 // summary: 26707 // Does substitution of ${foo} type properties in template string 26708 // tags: 26709 // private 26710 var className = this.declaredClass, _this = this; 26711 // Cache contains a string because we need to do property replacement 26712 // do the property replacement 26713 return string.substitute(tmpl, this, function(value, key){ 26714 if(key.charAt(0) == '!'){ value = lang.getObject(key.substr(1), false, _this); } 26715 if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide 26716 if(value == null){ return ""; } 26717 26718 // Substitution keys beginning with ! will skip the transform step, 26719 // in case a user wishes to insert unescaped markup, e.g. ${!foo} 26720 return key.charAt(0) == "!" ? value : this._escapeValue("" + value); 26721 }, this); 26722 }, 26723 26724 _escapeValue: function(/*String*/ val){ 26725 // summary: 26726 // Escape a value to be inserted into the template, either into an attribute value 26727 // (ex: foo="${bar}") or as inner text of an element (ex: <span>${foo}</span>) 26728 26729 // Safer substitution, see heading "Attribute values" in 26730 // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2 26731 // and also https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content 26732 return val.replace(/["'<>&]/g, function(val){ 26733 return { 26734 "&": "&", 26735 "<": "<", 26736 ">": ">", 26737 "\"": """, 26738 "'": "'" 26739 }[val]; 26740 }); 26741 }, 26742 26743 buildRendering: function(){ 26744 // summary: 26745 // Construct the UI for this widget from a template, setting this.domNode. 26746 // tags: 26747 // protected 26748 26749 if(!this._rendered){ 26750 if(!this.templateString){ 26751 this.templateString = cache(this.templatePath, {sanitize: true}); 26752 } 26753 26754 // Lookup cached version of template, and download to cache if it 26755 // isn't there already. Returns either a DomNode or a string, depending on 26756 // whether or not the template contains ${foo} replacement parameters. 26757 var cached = _TemplatedMixin.getCachedTemplate(this.templateString, this._skipNodeCache, this.ownerDocument); 26758 26759 var node; 26760 if(lang.isString(cached)){ 26761 node = domConstruct.toDom(this._stringRepl(cached), this.ownerDocument); 26762 if(node.nodeType != 1){ 26763 // Flag common problems such as templates with multiple top level nodes (nodeType == 11) 26764 throw new Error("Invalid template: " + cached); 26765 } 26766 }else{ 26767 // if it's a node, all we have to do is clone it 26768 node = cached.cloneNode(true); 26769 } 26770 26771 this.domNode = node; 26772 } 26773 26774 // Call down to _WidgetBase.buildRendering() to get base classes assigned 26775 // TODO: change the baseClass assignment to _setBaseClassAttr 26776 this.inherited(arguments); 26777 26778 if(!this._rendered){ 26779 this._fillContent(this.srcNodeRef); 26780 } 26781 26782 this._rendered = true; 26783 }, 26784 26785 _fillContent: function(/*DomNode*/ source){ 26786 // summary: 26787 // Relocate source contents to templated container node.
26788 // this.containerNode must be able to receive children, or exceptions will be thrown. 26789 // tags: 26790 // protected 26791 var dest = this.containerNode; 26792 if(source && dest){ 26793 while(source.hasChildNodes()){ 26794 dest.appendChild(source.firstChild); 26795 } 26796 } 26797 } 26798 26799 }); 26800 26801 // key is templateString; object is either string or DOM tree 26802 _TemplatedMixin._templateCache = {}; 26803 26804 _TemplatedMixin.getCachedTemplate = function(templateString, alwaysUseString, doc){ 26805 // summary: 26806 // Static method to get a template based on the templatePath or 26807 // templateString key 26808 // templateString: String 26809 // The template 26810 // alwaysUseString: Boolean 26811 // Don't cache the DOM tree for this template, even if it doesn't have any variables 26812 // doc: Document? 26813 // The target document. Defaults to document global if unspecified. 26814 // returns: Mixed 26815 // Either string (if there are ${} variables that need to be replaced) or just 26816 // a DOM tree (if the node can be cloned directly) 26817 26818 // is it already cached? 26819 var tmplts = _TemplatedMixin._templateCache; 26820 var key = templateString; 26821 var cached = tmplts[key]; 26822 if(cached){ 26823 try{ 26824 // if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the 26825 // current document, then use the current cached value 26826 if(!cached.ownerDocument || cached.ownerDocument == (doc || document)){ 26827 // string or node of the same document 26828 return cached; 26829 } 26830 }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded 26831 domConstruct.destroy(cached); 26832 } 26833 26834 templateString = string.trim(templateString); 26835 26836 if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){ 26837 // there are variables in the template so all we can do is cache the string 26838 return (tmplts[key] = templateString); //String 26839 }else{ 26840 // there are no variables in the template so we can cache the DOM tree 26841 var node = domConstruct.toDom(templateString, doc); 26842 if(node.nodeType != 1){ 26843 throw new Error("Invalid template: " + templateString); 26844 } 26845 return (tmplts[key] = node); //Node 26846 } 26847 }; 26848 26849 if(has("ie")){ 26850 on(window, "unload", function(){ 26851 var cache = _TemplatedMixin._templateCache; 26852 for(var key in cache){ 26853 var value = cache[key]; 26854 if(typeof value == "object"){ // value is either a string or a DOM node template 26855 domConstruct.destroy(value); 26856 } 26857 delete cache[key]; 26858 } 26859 }); 26860 } 26861 26862 return _TemplatedMixin; 26863}); 26864 26865}, 26866'dojo/cache':function(){ 26867define(["./_base/kernel", "./text"], function(dojo){ 26868 // module: 26869 // dojo/cache 26870 26871 // dojo.cache is defined in dojo/text 26872 return dojo.cache; 26873}); 26874 26875}, 26876'dojo/text':function(){ 26877define(["./_base/kernel", "require", "./has", "./request"], function(dojo, require, has, request){ 26878 // module: 26879 // dojo/text 26880 26881 var getText; 26882 if( 1 ){ 26883 getText= function(url, sync, load){ 26884 request(url, {sync:!!sync, headers: { 'X-Requested-With': null } }).then(load); 26885 }; 26886 }else{ 26887 // Path for node.js and rhino, to load from local file system. 26888 // TODO: use node.js native methods rather than depending on a require.getText() method to exist. 26889 if(require.getText){ 26890 getText= require.getText; 26891 }else{ 26892 console.error("dojo/text plugin failed to load because loader does not support getText"); 26893 } 26894 } 26895 26896 var 26897 theCache = {}, 26898 26899 strip= function(text){ 26900 //Strips <?xml ...?> declarations so that external SVG and XML 26901 //documents can be added to a document without worry. Also, if the string 26902 //is an HTML document, only the part inside the body tag is returned. 26903 if(text){ 26904 text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, ""); 26905 var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im); 26906 if(matches){ 26907 text= matches[1]; 26908 } 26909 }else{ 26910 text = ""; 26911 } 26912 return text; 26913 }, 26914 26915 notFound = {}, 26916 26917 pending = {}; 26918 26919 dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){ 26920 // summary: 26921 // A getter and setter for storing the string content associated with the 26922 // module and url arguments. 26923 // description: 26924 // If module is a string that contains slashes, then it is interpretted as a fully 26925 // resolved path (typically a result returned by require.toUrl), and url should not be 26926 // provided. This is the preferred signature. If module is a string that does not 26927 // contain slashes, then url must also be provided and module and url are used to 26928 // call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated. 26929 // If value is specified, the cache value for the moduleUrl will be set to 26930 // that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
vendor: 4,197 bytes, lines 26931-27003
26931 // in its internal cache and return that cached value for the URL. To clear 26932 // a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the 26933 // the URL contents, only modules on the same domain of the page can use this capability. 26934 // The build system can inline the cache values though, to allow for xdomain hosting. 26935 // module: String||Object 26936 // If a String with slashes, a fully resolved path; if a String without slashes, the 26937 // module name to use for the base part of the URL, similar to module argument 26938 // to `dojo.moduleUrl`. If an Object, something that has a .toString() method that 26939 // generates a valid path for the cache item. For example, a dojo._Url object. 26940 // url: String 26941 // The rest of the path to append to the path derived from the module argument. If 26942 // module is an object, then this second argument should be the "value" argument instead. 26943 // value: String||Object? 26944 // If a String, the value to use in the cache for the module/url combination. 26945 // If an Object, it can have two properties: value and sanitize. The value property 26946 // should be the value to use in the cache, and sanitize can be set to true or false, 26947 // to indicate if XML declarations should be removed from the value and if the HTML 26948 // inside a body tag in the value should be extracted as the real value. The value argument 26949 // or the value property on the value argument are usually only used by the build system 26950 // as it inlines cache content. 26951 // example: 26952 // To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style 26953 // of call is used to avoid an issue with the build system erroneously trying to intern 26954 // this example. To get the build system to intern your dojo.cache calls, use the 26955 // "dojo.cache" style of call): 26956 // | //If template.html contains "<h1>Hello</h1>" that will be 26957 // | //the value for the text variable. 26958 // | //Note: This is pre-AMD, deprecated syntax 26959 // | var text = dojo["cache"]("my.module", "template.html"); 26960 // example: 26961 // To ask dojo.cache to fetch content and store it in the cache, and sanitize the input 26962 // (the dojo["cache"] style of call is used to avoid an issue with the build system 26963 // erroneously trying to intern this example. To get the build system to intern your 26964 // dojo.cache calls, use the "dojo.cache" style of call): 26965 // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the 26966 // | //text variable will contain just "<h1>Hello</h1>". 26967 // | //Note: This is pre-AMD, deprecated syntax 26968 // | var text = dojo["cache"]("my.module", "template.html", {sanitize: true}); 26969 // example: 26970 // Same example as previous, but demonstrates how an object can be passed in as 26971 // the first argument, then the value argument can then be the second argument. 26972 // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the 26973 // | //text variable will contain just "<h1>Hello</h1>". 26974 // | //Note: This is pre-AMD, deprecated syntax 26975 // | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true}); 26976 26977 // * (string string [value]) => (module, url, value) 26978 // * (object [value]) => (module, value), url defaults to "" 26979 // 26980 // * if module is an object, then it must be convertable to a string 26981 // * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl 26982 // * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize" 26983 var key; 26984 if(typeof module=="string"){ 26985 if(/\//.test(module)){ 26986 // module is a version 1.7+ resolved path 26987 key = module; 26988 value = url; 26989 }else{ 26990 // module is a version 1.6- argument to dojo.moduleUrl 26991 key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : "")); 26992 } 26993 }else{ 26994 key = module + ""; 26995 value = url; 26996 } 26997 var 26998 val = (value != undefined && typeof value != "string") ? value.value : value, 26999 sanitize = value && value.sanitize; 27000 27001 if(typeof val == "string"){ 27002 //We have a string, set cache value 27003 theCache[key] = val;
27004 return sanitize ? strip(val) : val; 27005 }else if(val === null){ 27006 //Remove cached value 27007 delete theCache[key]; 27008 return null; 27009 }else{ 27010 //Allow cache values to be empty strings. If key property does 27011 //not exist, fetch it. 27012 if(!(key in theCache)){ 27013 getText(key, true, function(text){ 27014 theCache[key]= text; 27015 }); 27016 } 27017 return sanitize ? strip(theCache[key]) : theCache[key]; 27018 } 27019 }; 27020 27021 return { 27022 // summary: 27023 // This module implements the dojo/text! plugin and the dojo.cache API. 27024 // description: 27025 // We choose to include our own plugin to leverage functionality already contained in dojo 27026 // and thereby reduce the size of the plugin compared to various foreign loader implementations. 27027 // Also, this allows foreign AMD loaders to be used without their plugins. 27028 // 27029 // CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous 27030 // loader. This feature is outside the scope of the CommonJS plugins specification. 27031 27032 // the dojo/text caches it's own resources because of dojo.cache 27033 dynamic: true, 27034 27035 normalize: function(id, toAbsMid){ 27036 // id is something like (path may be relative): 27037 // 27038 // "path/to/text.html" 27039 // "path/to/text.html!strip" 27040 var parts= id.split("!"), 27041 url= parts[0]; 27042 return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : ""); 27043 }, 27044 27045 load: function(id, require, load){ 27046 // id: String 27047 // Path to the resource. 27048 // require: Function 27049 // Object that include the function toUrl with given id returns a valid URL from which to load the text. 27050 // load: Function 27051 // Callback function which will be called, when the loading finished. 27052 27053 // id is something like (path is always absolute): 27054 // 27055 // "path/to/text.html" 27056 // "path/to/text.html!strip" 27057 var 27058 parts= id.split("!"), 27059 stripFlag= parts.length>1, 27060 absMid= parts[0], 27061 url = require.toUrl(parts[0]), 27062 requireCacheUrl = "url:" + url, 27063 text = notFound, 27064 finish = function(text){ 27065 load(stripFlag ? strip(text) : text); 27066 }; 27067 if(absMid in theCache){ 27068 text = theCache[absMid]; 27069 }else if(require.cache && requireCacheUrl in require.cache){ 27070 text = require.cache[requireCacheUrl]; 27071 }else if(url in theCache){ 27072 text = theCache[url]; 27073 } 27074 if(text===notFound){ 27075 if(pending[url]){ 27076 pending[url].push(finish); 27077 }else{ 27078 var pendingList = pending[url] = [finish]; 27079 getText(url, !require.async, function(text){ 27080 theCache[absMid]= theCache[url]= text; 27081 for(var i = 0; i<pendingList.length;){ 27082 pendingList[i++](text); 27083 } 27084 delete pending[url]; 27085 }); 27086 } 27087 }else{ 27088 finish(text); 27089 } 27090 } 27091 }; 27092 27093}); 27094 27095 27096}, 27097'dojo/request':function(){ 27098define([ 27099 './request/default!'/*=====, 27100 './_base/declare', 27101 './promise/Promise' =====*/ 27102], function(request/*=====, declare, Promise =====*/){ 27103 /*===== 27104 request = function(url, options){ 27105 // summary: 27106 // Send a request using the default transport for the current platform. 27107 // url: String 27108 // The URL to request. 27109 // options: dojo/request.__Options? 27110 // Options for the request. 27111 // returns: dojo/request.__Promise 27112 }; 27113 request.__Promise = declare(Promise, { 27114 // response: dojo/promise/Promise 27115 // A promise resolving to an object representing 27116 // the response from the server. 27117 }); 27118 request.__BaseOptions = declare(null, { 27119 // query: String|Object? 27120 // Query parameters to append to the URL. 27121 // data: String|Object? 27122 // Data to transfer. This is ignored for GET and DELETE 27123 // requests. 27124 // preventCache: Boolean? 27125 // Whether to append a cache-busting parameter to the URL. 27126 // timeout: Integer? 27127 // Milliseconds to wait for the response. If this time 27128 // passes, the then the promise is rejected. 27129 // handleAs: String? 27130 // How to handle the response from the server. Default is 27131 // 'text'. Other values are 'json', 'javascript', and 'xml'. 27132 }); 27133 request.__MethodOptions = declare(null, { 27134 // method: String? 27135 // The HTTP method to use to make the request. Must be 27136 // uppercase. 27137 }); 27138 request.__Options = declare([request.__BaseOptions, request.__MethodOptions]); 27139 27140 request.get = function(url, options){ 27141 // summary: 27142 // Send an HTTP GET request using the default transport for the current platform. 27143 // url: String 27144 // URL to request 27145 // options: dojo/request.__BaseOptions? 27146 // Options for the request. 27147 // returns: dojo/request.__Promise 27148 }; 27149 request.post = function(url, options){ 27150 // summary: 27151 // Send an HTTP POST request using the default transport for the current platform. 27152 // url: String 27153 // URL to request 27154 // options: dojo/request.__BaseOptions? 27155 // Options for the request. 27156 // returns: dojo/request.__Promise 27157 }; 27158 request.put = function(url, options){ 27159 // summary: 27160 // Send an HTTP POST request using the default transport for the current platform. 27161 // url: String 27162 // URL to request 27163 // options: dojo/request.__BaseOptions? 27164 // Options for the request. 27165 // returns: dojo/request.__Promise 27166 }; 27167 request.del = function(url, options){ 27168 // summary: 27169 // Send an HTTP DELETE request using the default transport for the current platform. 27170 // url: String 27171 // URL to request 27172 // options: dojo/request.__BaseOptions? 27173 // Options for the request. 27174 // returns: dojo/request.__Promise 27175 }; 27176 =====*/ 27177 return request; 27178}); 27179 27180}, 27181'dojo/request/default':function(){ 27182define([ 27183 'exports', 27184 'require', 27185 '../has' 27186], function(exports, require, has){ 27187 var defId = has('config-requestProvider'), 27188 platformId; 27189 27190 if( 1 || has('host-webworker')){ 27191 platformId = './xhr'; 27192 }else if( 0 ){ 27193 platformId = './node'; 27194 /* TODO: 27195 }else if( 0 ){ 27196 platformId = './rhino'; 27197 */ 27198 } 27199 27200 if(!defId){ 27201 defId = platformId; 27202 } 27203 27204 exports.getPlatformDefaultId = function(){ 27205 return platformId; 27206 }; 27207 27208 exports.load = function(id, parentRequire, loaded, config){ 27209 require([id == 'platform' ? platformId : defId], function(provider){ 27210 loaded(provider); 27211 }); 27212 }; 27213}); 27214 27215}, 27216'dijit/_AttachMixin':function(){ 27217define([ 27218 "require", 27219 "dojo/_base/array", // array.forEach 27220 "dojo/_base/connect", // remove for 2.0 27221 "dojo/_base/declare", // declare 27222 "dojo/_base/lang", // lang.getObject 27223 "dojo/mouse", 27224 "dojo/on", 27225 "dojo/touch", 27226 "./_WidgetBase" 27227], function(require, array, connect, declare, lang, mouse, on, touch, _WidgetBase){ 27228 27229 // module: 27230 // dijit/_AttachMixin 27231 27232 // Map from string name like "mouseenter" to synthetic event like mouse.enter 27233 var synthEvents = lang.delegate(touch, { 27234 "mouseenter": mouse.enter, 27235 "mouseleave": mouse.leave, 27236 "keypress": connect._keypress // remove for 2.0 27237 }); 27238 27239 // To be lightweight, _AttachMixin doesn't require() dijit/a11yclick. 27240 // If the subclass has a template using "ondijitclick", it must load dijit/a11yclick itself. 27241 // In that case, the a11yclick variable below will get set to point to that synthetic event. 27242 var a11yclick; 27243 27244 var _AttachMixin = declare("dijit._AttachMixin", null, { 27245 // summary: 27246 // Mixin for widgets to attach to dom nodes and setup events via 27247 // convenient data-dojo-attach-point and data-dojo-attach-event DOM attributes. 27248 // 27249 // Superclass of _TemplatedMixin, and can also be used standalone when templates are pre-rendered on the 27250 // server.
27251 // 27252 // Does not [yet] handle widgets like ContentPane with this.containerNode set. It should skip 27253 // scanning for data-dojo-attach-point and data-dojo-attach-event inside this.containerNode, but it 27254 // doesn't. 27255 27256/*===== 27257 // _attachPoints: [private] String[] 27258 // List of widget attribute names associated with data-dojo-attach-point=... in the 27259 // template, ex: ["containerNode", "labelNode"] 27260 _attachPoints: [], 27261 27262 // _attachEvents: [private] Handle[] 27263 // List of connections associated with data-dojo-attach-event=... in the 27264 // template 27265 _attachEvents: [], 27266 27267 // attachScope: [public] Object 27268 // Object to which attach points and events will be scoped. Defaults 27269 // to 'this'. 27270 attachScope: undefined, 27271 27272 // searchContainerNode: [protected] Boolean 27273 // Search descendants of this.containerNode for data-dojo-attach-point and data-dojo-attach-event. 27274 // Should generally be left false (the default value) both for performance and to avoid failures when 27275 // this.containerNode holds other _AttachMixin instances with their own attach points and events. 27276 searchContainerNode: false, 27277 =====*/ 27278 27279 constructor: function(/*===== params, srcNodeRef =====*/){ 27280 // summary: 27281 // Create the widget. 27282 // params: Object|null 27283 // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) 27284 // and functions, typically callbacks like onClick. 27285 // The hash can contain any of the widget's properties, excluding read-only properties. 27286 // srcNodeRef: DOMNode|String? 27287 // If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree. 27288 27289 this._attachPoints = []; 27290 this._attachEvents = []; 27291 }, 27292 27293 27294 buildRendering: function(){ 27295 // summary: 27296 // Attach to DOM nodes marked with special attributes. 27297 // tags: 27298 // protected 27299 27300 this.inherited(arguments); 27301 27302 // recurse through the node, looking for, and attaching to, our 27303 // attachment points and events, which should be defined on the template node. 27304 this._attachTemplateNodes(this.domNode); 27305 27306 this._beforeFillContent(); // hook for _WidgetsInTemplateMixin 27307 }, 27308 27309 _beforeFillContent: function(){ 27310 }, 27311 27312 _attachTemplateNodes: function(rootNode){ 27313 // summary: 27314 // Iterate through the dom nodes and attach functions and nodes accordingly. 27315 // description: 27316 // Map widget properties and functions to the handlers specified in 27317 // the dom node and it's descendants. This function iterates over all 27318 // nodes and looks for these properties: 27319 // 27320 // - dojoAttachPoint/data-dojo-attach-point 27321 // - dojoAttachEvent/data-dojo-attach-event 27322 // rootNode: DomNode 27323 // The node to search for properties. All descendants will be searched. 27324 // tags: 27325 // private 27326 27327 // DFS to process all nodes except those inside of this.containerNode 27328 var node = rootNode; 27329 while(true){ 27330 if(node.nodeType == 1 && (this._processTemplateNode(node, function(n,p){ return n.getAttribute(p); }, 27331 this._attach) || this.searchContainerNode) && node.firstChild){ 27332 node = node.firstChild; 27333 }else{ 27334 if(node == rootNode){ return; } 27335 while(!node.nextSibling){ 27336 node = node.parentNode; 27337 if(node == rootNode){ return; } 27338 } 27339 node = node.nextSibling; 27340 } 27341 } 27342 }, 27343 27344 _processTemplateNode: function(/*DOMNode|Widget*/ baseNode, getAttrFunc, attachFunc){ 27345 // summary: 27346 // Process data-dojo-attach-point and data-dojo-attach-event for given node or widget. 27347 // Returns true if caller should process baseNode's children too. 27348 27349 var ret = true; 27350 27351 // Process data-dojo-attach-point 27352 var _attachScope = this.attachScope || this, 27353 attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point"); 27354 if(attachPoint){ 27355 var point, points = attachPoint.split(/\s*,\s*/); 27356 while((point = points.shift())){ 27357 if(lang.isArray(_attachScope[point])){ 27358 _attachScope[point].push(baseNode); 27359 }else{ 27360 _attachScope[point] = baseNode; 27361 } 27362 ret = (point != "containerNode"); 27363 this._attachPoints.push(point); 27364 } 27365 } 27366 27367 // Process data-dojo-attach-event 27368 var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event"); 27369 if(attachEvent){
27370 // NOTE: we want to support attributes that have the form 27371 // "domEvent: nativeEvent; ..." 27372 var event, events = attachEvent.split(/\s*,\s*/); 27373 var trim = lang.trim; 27374 while((event = events.shift())){ 27375 if(event){ 27376 var thisFunc = null; 27377 if(event.indexOf(":") != -1){ 27378 // oh, if only JS had tuple assignment 27379 var funcNameArr = event.split(":"); 27380 event = trim(funcNameArr[0]); 27381 thisFunc = trim(funcNameArr[1]); 27382 }else{ 27383 event = trim(event); 27384 } 27385 if(!thisFunc){ 27386 thisFunc = event; 27387 } 27388 27389 this._attachEvents.push(attachFunc(baseNode, event, lang.hitch(_attachScope, thisFunc))); 27390 } 27391 } 27392 } 27393 27394 return ret; 27395 }, 27396 27397 _attach: function(node, type, func){ 27398 // summary: 27399 // Roughly corresponding to dojo/on, this is the default function for processing a 27400 // data-dojo-attach-event. Meant to attach to DOMNodes, not to widgets. 27401 // node: DOMNode 27402 // The node to setup a listener on. 27403 // type: String 27404 // Event name like "click". 27405 // getAttrFunc: Function 27406 // Function to get the specified property for a given DomNode/Widget. 27407 // attachFunc: Function? 27408 // Attaches an event handler from the specified node/widget to specified function. 27409 27410 // Map special type names like "mouseenter" to synthetic events. 27411 // Subclasses are responsible to require() dijit/a11yclick if they want to use it. 27412 type = type.replace(/^on/, "").toLowerCase(); 27413 if(type == "dijitclick"){ 27414 type = a11yclick || (a11yclick = require("./a11yclick")); 27415 }else{ 27416 type = synthEvents[type] || type; 27417 } 27418 27419 return on(node, type, func); 27420 }, 27421 27422 _detachTemplateNodes: function() { 27423 // summary: 27424 // Detach and clean up the attachments made in _attachtempalteNodes. 27425 27426 // Delete all attach points to prevent IE6 memory leaks. 27427 var _attachScope = this.attachScope || this; 27428 array.forEach(this._attachPoints, function(point){ 27429 delete _attachScope[point]; 27430 }); 27431 this._attachPoints = []; 27432 27433 // And same for event handlers 27434 array.forEach(this._attachEvents, function(handle){ handle.remove(); }); 27435 this._attachEvents = []; 27436 }, 27437 27438 destroyRendering: function(){ 27439 this._detachTemplateNodes(); 27440 this.inherited(arguments); 27441 } 27442 }); 27443 27444 // These arguments can be specified for widgets which are used in templates. 27445 // Since any widget can be specified as sub widgets in template, mix it 27446 // into the base widget class. (This is a hack, but it's effective.). 27447 // Remove for 2.0. Also, hide from API doc parser. 27448 lang.extend(_WidgetBase, /*===== {} || =====*/ { 27449 dojoAttachEvent: "", 27450 dojoAttachPoint: "" 27451 }); 27452 27453 return _AttachMixin; 27454}); 27455 27456}, 27457'dojo/parser':function(){ 27458define([ 27459 "require", "./_base/kernel", "./_base/lang", "./_base/array", "./_base/config", "./dom", "./_base/window", 27460 "./_base/url", "./aspect", "./promise/all", "./date/stamp", "./Deferred", "./has", "./query", "./on", "./ready" 27461], function(require, dojo, dlang, darray, config, dom, dwindow, _Url, aspect, all, dates, Deferred, has, query, don, ready){ 27462 27463 // module: 27464 // dojo/parser 27465 27466 new Date("X"); // workaround for #11279, new Date("") == NaN 27467 27468 // data-dojo-props etc. is not restricted to JSON, it can be any javascript 27469 function myEval(text){ 27470 return eval("(" + text + ")"); 27471 } 27472 27473 // Widgets like BorderContainer add properties to _Widget via dojo.extend(). 27474 // If BorderContainer is loaded after _Widget's parameter list has been cached, 27475 // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget). 27476 var extendCnt = 0; 27477 aspect.after(dlang, "extend", function(){ 27478 extendCnt++; 27479 }, true); 27480 27481 function getNameMap(ctor){ 27482 // summary: 27483 // Returns map from lowercase name to attribute name in class, ex: {onclick: "onClick"} 27484 var map = ctor._nameCaseMap, proto = ctor.prototype; 27485 27486 // Create the map if it's undefined. 27487 // Refresh the map if a superclass was possibly extended with new methods since the map was created. 27488 if(!map || map._extendCnt < extendCnt){ 27489 map = ctor._nameCaseMap = {}; 27490 for(var name in proto){ 27491 if(name.charAt(0) === "_"){ 27492 continue; 27493 } // skip internal properties 27494 map[name.toLowerCase()] = name; 27495 } 27496 map._extendCnt = extendCnt; 27497 } 27498 return map; 27499 } 27500 27501 // Map from widget name or list of widget names(ex: "dijit/form/Button,acme/MyMixin") to a constructor. 27502 var _ctorMap = {}; 27503 27504 function getCtor(/*String[]*/ types, /*Function?*/ contextRequire){ 27505 // summary: 27506 // Retrieves a constructor. If the types array contains more than one class/MID then the 27507 // subsequent classes will be mixed into the first class and a unique constructor will be 27508 // returned for that array. 27509 27510 var ts = types.join(); 27511 if(!_ctorMap[ts]){ 27512 var mixins = []; 27513 for(var i = 0, l = types.length; i < l; i++){ 27514 var t = types[i];
vendor: 31,491 bytes, lines 27515-28309
27515 // TODO: Consider swapping getObject and require in the future 27516 mixins[mixins.length] = (_ctorMap[t] = _ctorMap[t] || (dlang.getObject(t) || (~t.indexOf('/') && 27517 (contextRequire ? contextRequire(t) : require(t))))); 27518 } 27519 var ctor = mixins.shift(); 27520 _ctorMap[ts] = mixins.length ? (ctor.createSubclass ? ctor.createSubclass(mixins) : ctor.extend.apply(ctor, mixins)) : ctor; 27521 } 27522 27523 return _ctorMap[ts]; 27524 } 27525 27526 var parser = { 27527 // summary: 27528 // The Dom/Widget parsing package 27529 27530 _clearCache: function(){ 27531 // summary: 27532 // Clear cached data. Used mainly for benchmarking. 27533 extendCnt++; 27534 _ctorMap = {}; 27535 }, 27536 27537 _functionFromScript: function(script, attrData){ 27538 // summary: 27539 // Convert a `<script type="dojo/method" args="a, b, c"> ... </script>` 27540 // into a function 27541 // script: DOMNode 27542 // The `<script>` DOMNode 27543 // attrData: String 27544 // For HTML5 compliance, searches for attrData + "args" (typically 27545 // "data-dojo-args") instead of "args" 27546 var preamble = "", 27547 suffix = "", 27548 argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args")), 27549 withStr = script.getAttribute("with"); 27550 27551 // Convert any arguments supplied in script tag into an array to be passed to the 27552 var fnArgs = (argsStr || "").split(/\s*,\s*/); 27553 27554 if(withStr && withStr.length){ 27555 darray.forEach(withStr.split(/\s*,\s*/), function(part){ 27556 preamble += "with(" + part + "){"; 27557 suffix += "}"; 27558 }); 27559 } 27560 27561 return new Function(fnArgs, preamble + script.innerHTML + suffix); 27562 }, 27563 27564 instantiate: function(nodes, mixin, options){ 27565 // summary: 27566 // Takes array of nodes, and turns them into class instances and 27567 // potentially calls a startup method to allow them to connect with 27568 // any children. 27569 // nodes: Array 27570 // Array of DOM nodes 27571 // mixin: Object? 27572 // An object that will be mixed in with each node in the array. 27573 // Values in the mixin will override values in the node, if they 27574 // exist. 27575 // options: Object? 27576 // An object used to hold kwArgs for instantiation. 27577 // See parse.options argument for details. 27578 // returns: 27579 // Array of instances. 27580 27581 mixin = mixin || {}; 27582 options = options || {}; 27583 27584 var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType" 27585 attrData = "data-" + (options.scope || dojo._scopeName) + "-", // typically "data-dojo-" 27586 dataDojoType = attrData + "type", // typically "data-dojo-type" 27587 dataDojoMixins = attrData + "mixins"; // typically "data-dojo-mixins" 27588 27589 var list = []; 27590 darray.forEach(nodes, function(node){ 27591 var type = dojoType in mixin ? mixin[dojoType] : node.getAttribute(dataDojoType) || node.getAttribute(dojoType); 27592 if(type){ 27593 var mixinsValue = node.getAttribute(dataDojoMixins), 27594 types = mixinsValue ? [type].concat(mixinsValue.split(/\s*,\s*/)) : [type]; 27595 27596 list.push({ 27597 node: node, 27598 types: types 27599 }); 27600 } 27601 }); 27602 27603 // Instantiate the nodes and return the list of instances. 27604 return this._instantiate(list, mixin, options); 27605 }, 27606 27607 _instantiate: function(nodes, mixin, options, returnPromise){ 27608 // summary: 27609 // Takes array of objects representing nodes, and turns them into class instances and 27610 // potentially calls a startup method to allow them to connect with 27611 // any children. 27612 // nodes: Array 27613 // Array of objects like 27614 // | { 27615 // | ctor: Function (may be null) 27616 // | types: ["dijit/form/Button", "acme/MyMixin"] (used if ctor not specified) 27617 // | node: DOMNode, 27618 // | scripts: [ ... ], // array of <script type="dojo/..."> children of node 27619 // | inherited: { ... } // settings inherited from ancestors like dir, theme, etc. 27620 // | } 27621 // mixin: Object 27622 // An object that will be mixed in with each node in the array. 27623 // Values in the mixin will override values in the node, if they 27624 // exist. 27625 // options: Object 27626 // An options object used to hold kwArgs for instantiation. 27627 // See parse.options argument for details. 27628 // returnPromise: Boolean 27629 // Return a Promise rather than the instance; supports asynchronous widget creation. 27630 // returns: 27631 // Array of instances, or if returnPromise is true, a promise for array of instances 27632 // that resolves when instances have finished initializing. 27633 27634 // Call widget constructors. Some may be asynchronous and return promises. 27635 var thelist = darray.map(nodes, function(obj){ 27636 var ctor = obj.ctor || getCtor(obj.types, options.contextRequire); 27637 // If we still haven't resolved a ctor, it is fatal now 27638 if(!ctor){ 27639 throw new Error("Unable to resolve constructor for: '" + obj.types.join() + "'"); 27640 } 27641 return this.construct(ctor, obj.node, mixin, options, obj.scripts, obj.inherited); 27642 }, this); 27643 27644 // After all widget construction finishes, call startup on each top level instance if it makes sense (as for 27645 // widgets). Parent widgets will recursively call startup on their (non-top level) children 27646 function onConstruct(thelist){ 27647 if(!mixin._started && !options.noStart){ 27648 darray.forEach(thelist, function(instance){ 27649 if(typeof instance.startup === "function" && !instance._started){ 27650 instance.startup(); 27651 } 27652 }); 27653 } 27654 27655 return thelist; 27656 } 27657 27658 if(returnPromise){ 27659 return all(thelist).then(onConstruct); 27660 }else{ 27661 // Back-compat path, remove for 2.0 27662 return onConstruct(thelist); 27663 } 27664 }, 27665 27666 construct: function(ctor, node, mixin, options, scripts, inherited){ 27667 // summary: 27668 // Calls new ctor(params, node), where params is the hash of parameters specified on the node, 27669 // excluding data-dojo-type and data-dojo-mixins. Does not call startup(). 27670 // ctor: Function 27671 // Widget constructor. 27672 // node: DOMNode 27673 // This node will be replaced/attached to by the widget. It also specifies the arguments to pass to ctor. 27674 // mixin: Object? 27675 // Attributes in this object will be passed as parameters to ctor, 27676 // overriding attributes specified on the node. 27677 // options: Object? 27678 // An options object used to hold kwArgs for instantiation. See parse.options argument for details. 27679 // scripts: DomNode[]? 27680 // Array of `<script type="dojo/*">` DOMNodes. If not specified, will search for `<script>` tags inside node. 27681 // inherited: Object? 27682 // Settings from dir=rtl or lang=... on a node above this node. Overrides options.inherited. 27683 // returns: 27684 // Instance or Promise for the instance, if markupFactory() itself returned a promise 27685 27686 var proto = ctor && ctor.prototype; 27687 options = options || {}; 27688 27689 // Setup hash to hold parameter settings for this widget. Start with the parameter 27690 // settings inherited from ancestors ("dir" and "lang"). 27691 // Inherited setting may later be overridden by explicit settings on node itself. 27692 var params = {}; 27693 27694 if(options.defaults){ 27695 // settings for the document itself (or whatever subtree is being parsed) 27696 dlang.mixin(params, options.defaults); 27697 } 27698 if(inherited){ 27699 // settings from dir=rtl or lang=... on a node above this node 27700 dlang.mixin(params, inherited); 27701 } 27702 27703 // Get list of attributes explicitly listed in the markup 27704 var attributes; 27705 if(has("dom-attributes-explicit")){ 27706 // Standard path to get list of user specified attributes 27707 attributes = node.attributes; 27708 }else if(has("dom-attributes-specified-flag")){ 27709 // Special processing needed for IE8, to skip a few faux values in attributes[] 27710 attributes = darray.filter(node.attributes, function(a){ 27711 return a.specified; 27712 }); 27713 }else{ 27714 // Special path for IE6-7, avoid (sometimes >100) bogus entries in node.attributes 27715 var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false), 27716 attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z0-9]*\s*/, "").replace(/\s*>.*$/, ""); 27717 27718 attributes = darray.map(attrs.split(/\s+/), function(name){ 27719 var lcName = name.toLowerCase(); 27720 return { 27721 name: name, 27722 // getAttribute() doesn't work for button.value, returns innerHTML of button. 27723 // but getAttributeNode().value doesn't work for the form.encType or li.value 27724 value: (node.nodeName == "LI" && name == "value") || lcName == "enctype" ? 27725 node.getAttribute(lcName) : node.getAttributeNode(lcName).value 27726 }; 27727 }); 27728 } 27729 27730 // Hash to convert scoped attribute name (ex: data-dojo17-params) to something friendly (ex: data-dojo-params) 27731 // TODO: remove scope for 2.0 27732 var scope = options.scope || dojo._scopeName, 27733 attrData = "data-" + scope + "-", // typically "data-dojo-" 27734 hash = {}; 27735 if(scope !== "dojo"){ 27736 hash[attrData + "props"] = "data-dojo-props"; 27737 hash[attrData + "type"] = "data-dojo-type"; 27738 hash[attrData + "mixins"] = "data-dojo-mixins"; 27739 hash[scope + "type"] = "dojoType"; 27740 hash[attrData + "id"] = "data-dojo-id"; 27741 } 27742 27743 // Read in attributes and process them, including data-dojo-props, data-dojo-type, 27744 // dojoAttachPoint, etc., as well as normal foo=bar attributes. 27745 var i = 0, item, funcAttrs = [], jsname, extra; 27746 while(item = attributes[i++]){ 27747 var name = item.name, 27748 lcName = name.toLowerCase(), 27749 value = item.value; 27750 27751 switch(hash[lcName] || lcName){ 27752 // Already processed, just ignore 27753 case "data-dojo-type": 27754 case "dojotype": 27755 case "data-dojo-mixins": 27756 break; 27757 27758 // Data-dojo-props. Save for later to make sure it overrides direct foo=bar settings 27759 case "data-dojo-props": 27760 extra = value; 27761 break; 27762 27763 // data-dojo-id or jsId. TODO: drop jsId in 2.0 27764 case "data-dojo-id": 27765 case "jsid": 27766 jsname = value; 27767 break; 27768 27769 // For the benefit of _Templated 27770 case "data-dojo-attach-point": 27771 case "dojoattachpoint": 27772 params.dojoAttachPoint = value; 27773 break; 27774 case "data-dojo-attach-event": 27775 case "dojoattachevent": 27776 params.dojoAttachEvent = value; 27777 break; 27778 27779 // Special parameter handling needed for IE 27780 case "class": 27781 params["class"] = node.className; 27782 break; 27783 case "style": 27784 params["style"] = node.style && node.style.cssText; 27785 break; 27786 default: 27787 // Normal attribute, ex: value="123" 27788 27789 // Find attribute in widget corresponding to specified name. 27790 // May involve case conversion, ex: onclick --> onClick 27791 if(!(name in proto)){ 27792 var map = getNameMap(ctor); 27793 name = map[lcName] || name; 27794 } 27795 27796 // Set params[name] to value, doing type conversion 27797 if(name in proto){ 27798 switch(typeof proto[name]){ 27799 case "string": 27800 params[name] = value; 27801 break; 27802 case "number": 27803 params[name] = value.length ? Number(value) : NaN; 27804 break; 27805 case "boolean": 27806 // for checked/disabled value might be "" or "checked". interpret as true. 27807 params[name] = value.toLowerCase() != "false"; 27808 break; 27809 case "function": 27810 if(value === "" || value.search(/[^\w\.]+/i) != -1){ 27811 // The user has specified some text for a function like "return x+5" 27812 params[name] = new Function(value); 27813 }else{ 27814 // The user has specified the name of a global function like "myOnClick" 27815 // or a single word function "return" 27816 params[name] = dlang.getObject(value, false) || new Function(value); 27817 } 27818 funcAttrs.push(name); // prevent "double connect", see #15026 27819 break; 27820 default: 27821 var pVal = proto[name]; 27822 params[name] = 27823 (pVal && "length" in pVal) ? (value ? value.split(/\s*,\s*/) : []) : // array 27824 (pVal instanceof Date) ? 27825 (value == "" ? new Date("") : // the NaN of dates 27826 value == "now" ? new Date() : // current date 27827 dates.fromISOString(value)) : 27828 (pVal instanceof _Url) ? (dojo.baseUrl + value) : 27829 myEval(value); 27830 } 27831 }else{ 27832 params[name] = value; 27833 } 27834 } 27835 } 27836 27837 // Remove function attributes from DOMNode to prevent "double connect" problem, see #15026. 27838 // Do this as a separate loop since attributes[] is often a live collection (depends on the browser though). 27839 for(var j = 0; j < funcAttrs.length; j++){ 27840 var lcfname = funcAttrs[j].toLowerCase(); 27841 node.removeAttribute(lcfname); 27842 node[lcfname] = null; 27843 } 27844 27845 // Mix things found in data-dojo-props into the params, overriding any direct settings 27846 if(extra){ 27847 try{ 27848 extra = myEval.call(options.propsThis, "{" + extra + "}"); 27849 dlang.mixin(params, extra); 27850 }catch(e){ 27851 // give the user a pointer to their invalid parameters. FIXME: can we kill this in production? 27852 throw new Error(e.toString() + " in data-dojo-props='" + extra + "'"); 27853 } 27854 } 27855 27856 // Any parameters specified in "mixin" override everything else. 27857 dlang.mixin(params, mixin); 27858 27859 // Get <script> nodes associated with this widget, if they weren't specified explicitly 27860 if(!scripts){ 27861 scripts = (ctor && (ctor._noScript || proto._noScript) ? [] : query("> script[type^='dojo/']", node)); 27862 } 27863 27864 // Process <script type="dojo/*"> script tags 27865 // <script type="dojo/method" data-dojo-event="foo"> tags are added to params, and passed to 27866 // the widget on instantiation. 27867 // <script type="dojo/method"> tags (with no event) are executed after instantiation 27868 // <script type="dojo/connect" data-dojo-event="foo"> tags are dojo.connected after instantiation, 27869 // and likewise with <script type="dojo/aspect" data-dojo-method="foo"> 27870 // <script type="dojo/watch" data-dojo-prop="foo"> tags are dojo.watch after instantiation 27871 // <script type="dojo/on" data-dojo-event="foo"> tags are dojo.on after instantiation 27872 // note: dojo/* script tags cannot exist in self closing widgets, like <input /> 27873 var aspects = [], // aspects to connect after instantiation 27874 calls = [], // functions to call after instantiation 27875 watches = [], // functions to watch after instantiation 27876 ons = []; // functions to on after instantiation 27877 27878 if(scripts){ 27879 for(i = 0; i < scripts.length; i++){ 27880 var script = scripts[i]; 27881 node.removeChild(script); 27882 // FIXME: drop event="" support in 2.0. use data-dojo-event="" instead 27883 var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")), 27884 prop = script.getAttribute(attrData + "prop"), 27885 method = script.getAttribute(attrData + "method"), 27886 advice = script.getAttribute(attrData + "advice"), 27887 scriptType = script.getAttribute("type"), 27888 nf = this._functionFromScript(script, attrData); 27889 if(event){ 27890 if(scriptType == "dojo/connect"){ 27891 aspects.push({ method: event, func: nf }); 27892 }else if(scriptType == "dojo/on"){ 27893 ons.push({ event: event, func: nf }); 27894 }else{ 27895 // <script type="dojo/method" data-dojo-event="foo"> 27896 // TODO for 2.0: use data-dojo-method="foo" instead (also affects dijit/Declaration) 27897 params[event] = nf; 27898 } 27899 }else if(scriptType == "dojo/aspect"){ 27900 aspects.push({ method: method, advice: advice, func: nf }); 27901 }else if(scriptType == "dojo/watch"){ 27902 watches.push({ prop: prop, func: nf }); 27903 }else{ 27904 calls.push(nf); 27905 } 27906 } 27907 } 27908 27909 // create the instance 27910 var markupFactory = ctor.markupFactory || proto.markupFactory; 27911 var instance = markupFactory ? markupFactory(params, node, ctor) : new ctor(params, node); 27912 27913 function onInstantiate(instance){ 27914 // map it to the JS namespace if that makes sense 27915 if(jsname){ 27916 dlang.setObject(jsname, instance); 27917 } 27918 27919 // process connections and startup functions 27920 for(i = 0; i < aspects.length; i++){ 27921 aspect[aspects[i].advice || "after"](instance, aspects[i].method, dlang.hitch(instance, aspects[i].func), true); 27922 } 27923 for(i = 0; i < calls.length; i++){ 27924 calls[i].call(instance); 27925 } 27926 for(i = 0; i < watches.length; i++){ 27927 instance.watch(watches[i].prop, watches[i].func); 27928 } 27929 for(i = 0; i < ons.length; i++){ 27930 don(instance, ons[i].event, ons[i].func); 27931 } 27932 27933 return instance; 27934 } 27935 27936 if(instance.then){ 27937 return instance.then(onInstantiate); 27938 }else{ 27939 return onInstantiate(instance); 27940 } 27941 }, 27942 27943 scan: function(root, options){ 27944 // summary: 27945 // Scan a DOM tree and return an array of objects representing the DOMNodes 27946 // that need to be turned into widgets. 27947 // description: 27948 // Search specified node (or document root node) recursively for class instances 27949 // and return an array of objects that represent potential widgets to be 27950 // instantiated. Searches for either data-dojo-type="MID" or dojoType="MID" where 27951 // "MID" is a module ID like "dijit/form/Button" or a fully qualified Class name 27952 // like "dijit/form/Button". If the MID is not currently available, scan will 27953 // attempt to require() in the module. 27954 // 27955 // See parser.parse() for details of markup. 27956 // root: DomNode? 27957 // A default starting root node from which to start the parsing. Can be 27958 // omitted, defaulting to the entire document. If omitted, the `options` 27959 // object can be passed in this place. If the `options` object has a 27960 // `rootNode` member, that is used. 27961 // options: Object 27962 // a kwArgs options object, see parse() for details 27963 // 27964 // returns: Promise 27965 // A promise that is resolved with the nodes that have been parsed. 27966 27967 var list = [], // Output List 27968 mids = [], // An array of modules that are not yet loaded 27969 midsHash = {}; // Used to keep the mids array unique 27970 27971 var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType" 27972 attrData = "data-" + (options.scope || dojo._scopeName) + "-", // typically "data-dojo-" 27973 dataDojoType = attrData + "type", // typically "data-dojo-type" 27974 dataDojoTextDir = attrData + "textdir", // typically "data-dojo-textdir" 27975 dataDojoMixins = attrData + "mixins"; // typically "data-dojo-mixins" 27976 27977 // Info on DOMNode currently being processed 27978 var node = root.firstChild; 27979 27980 // Info on parent of DOMNode currently being processed 27981 // - inherited: dir, lang, and textDir setting of parent, or inherited by parent 27982 // - parent: pointer to identical structure for my parent (or null if no parent) 27983 // - scripts: if specified, collects <script type="dojo/..."> type nodes from children 27984 var inherited = options.inherited; 27985 if(!inherited){ 27986 function findAncestorAttr(node, attr){ 27987 return (node.getAttribute && node.getAttribute(attr)) || 27988 (node.parentNode && findAncestorAttr(node.parentNode, attr)); 27989 } 27990 27991 inherited = { 27992 dir: findAncestorAttr(root, "dir"), 27993 lang: findAncestorAttr(root, "lang"), 27994 textDir: findAncestorAttr(root, dataDojoTextDir) 27995 }; 27996 for(var key in inherited){ 27997 if(!inherited[key]){ 27998 delete inherited[key]; 27999 } 28000 } 28001 } 28002 28003 // Metadata about parent node 28004 var parent = { 28005 inherited: inherited 28006 }; 28007 28008 // For collecting <script type="dojo/..."> type nodes (when null, we don't need to collect) 28009 var scripts; 28010 28011 // when true, only look for <script type="dojo/..."> tags, and don't recurse to children 28012 var scriptsOnly; 28013 28014 function getEffective(parent){ 28015 // summary: 28016 // Get effective dir, lang, textDir settings for specified obj 28017 // (matching "parent" object structure above), and do caching. 28018 // Take care not to return null entries. 28019 if(!parent.inherited){ 28020 parent.inherited = {}; 28021 var node = parent.node, 28022 grandparent = getEffective(parent.parent); 28023 var inherited = { 28024 dir: node.getAttribute("dir") || grandparent.dir, 28025 lang: node.getAttribute("lang") || grandparent.lang, 28026 textDir: node.getAttribute(dataDojoTextDir) || grandparent.textDir 28027 }; 28028 for(var key in inherited){ 28029 if(inherited[key]){ 28030 parent.inherited[key] = inherited[key]; 28031 } 28032 } 28033 } 28034 return parent.inherited; 28035 } 28036 28037 // DFS on DOM tree, collecting nodes with data-dojo-type specified. 28038 while(true){ 28039 if(!node){ 28040 // Finished this level, continue to parent's next sibling 28041 if(!parent || !parent.node){ 28042 break; 28043 } 28044 node = parent.node.nextSibling; 28045 scriptsOnly = false; 28046 parent = parent.parent; 28047 scripts = parent.scripts; 28048 continue; 28049 } 28050 28051 if(node.nodeType != 1){ 28052 // Text or comment node, skip to next sibling 28053 node = node.nextSibling; 28054 continue; 28055 } 28056 28057 if(scripts && node.nodeName.toLowerCase() == "script"){ 28058 // Save <script type="dojo/..."> for parent, then continue to next sibling 28059 type = node.getAttribute("type"); 28060 if(type && /^dojo\/\w/i.test(type)){ 28061 scripts.push(node); 28062 } 28063 node = node.nextSibling; 28064 continue; 28065 } 28066 if(scriptsOnly){ 28067 // scriptsOnly flag is set, we have already collected scripts if the parent wants them, so now we shouldn't 28068 // continue further analysis of the node and will continue to the next sibling 28069 node = node.nextSibling; 28070 continue; 28071 } 28072 28073 // Check for data-dojo-type attribute, fallback to backward compatible dojoType 28074 // TODO: Remove dojoType in 2.0 28075 var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType); 28076 28077 // Short circuit for leaf nodes containing nothing [but text] 28078 var firstChild = node.firstChild; 28079 if(!type && (!firstChild || (firstChild.nodeType == 3 && !firstChild.nextSibling))){ 28080 node = node.nextSibling; 28081 continue; 28082 } 28083 28084 // Meta data about current node 28085 var current; 28086 28087 var ctor = null; 28088 if(type){ 28089 // If dojoType/data-dojo-type specified, add to output array of nodes to instantiate. 28090 var mixinsValue = node.getAttribute(dataDojoMixins), 28091 types = mixinsValue ? [type].concat(mixinsValue.split(/\s*,\s*/)) : [type]; 28092 28093 // Note: won't find classes declared via dojo/Declaration or any modules that haven't been 28094 // loaded yet so use try/catch to avoid throw from require() 28095 try{ 28096 ctor = getCtor(types, options.contextRequire); 28097 }catch(e){} 28098 28099 // If the constructor was not found, check to see if it has modules that can be loaded 28100 if(!ctor){ 28101 darray.forEach(types, function(t){ 28102 if(~t.indexOf('/') && !midsHash[t]){ 28103 // If the type looks like a MID and it currently isn't in the array of MIDs to load, add it. 28104 midsHash[t] = true; 28105 mids[mids.length] = t; 28106 } 28107 }); 28108 } 28109 28110 var childScripts = ctor && !ctor.prototype._noScript ? [] : null; // <script> nodes that are parent's children 28111 28112 // Setup meta data about this widget node, and save it to list of nodes to instantiate 28113 current = { 28114 types: types, 28115 ctor: ctor, 28116 parent: parent, 28117 node: node, 28118 scripts: childScripts 28119 }; 28120 current.inherited = getEffective(current); // dir & lang settings for current node, explicit or inherited 28121 list.push(current); 28122 }else{ 28123 // Meta data about this non-widget node 28124 current = { 28125 node: node, 28126 scripts: scripts, 28127 parent: parent 28128 }; 28129 } 28130 28131 // Recurse, collecting <script type="dojo/..."> children, and also looking for 28132 // descendant nodes with dojoType specified (unless the widget has the stopParser flag). 28133 // When finished with children, go to my next sibling. 28134 scripts = childScripts; 28135 scriptsOnly = node.stopParser || (ctor && ctor.prototype.stopParser && !(options.template)); 28136 parent = current; 28137 node = firstChild; 28138 } 28139 28140 var d = new Deferred(); 28141 28142 // If there are modules to load then require them in 28143 if(mids.length){ 28144 // Warn that there are modules being auto-required 28145 if( 0 ){ 28146 console.warn("WARNING: Modules being Auto-Required: " + mids.join(", ")); 28147 } 28148 var r = options.contextRequire || require; 28149 r(mids, function(){ 28150 // Go through list of widget nodes, filling in missing constructors, and filtering out nodes that shouldn't 28151 // be instantiated due to a stopParser flag on an ancestor that we belatedly learned about due to 28152 // auto-require of a module like ContentPane. Assumes list is in DFS order. 28153 d.resolve(darray.filter(list, function(widget){ 28154 if(!widget.ctor){ 28155 // Attempt to find the constructor again. Still won't find classes defined via 28156 // dijit/Declaration so need to try/catch. 28157 try{ 28158 widget.ctor = getCtor(widget.types, options.contextRequire); 28159 }catch(e){} 28160 } 28161 28162 // Get the parent widget 28163 var parent = widget.parent; 28164 while(parent && !parent.types){ 28165 parent = parent.parent; 28166 } 28167 28168 // Return false if this node should be skipped due to stopParser on an ancestor. 28169 // Since list[] is in DFS order, this loop will always set parent.instantiateChildren before 28170 // trying to compute widget.instantiate. 28171 var proto = widget.ctor && widget.ctor.prototype; 28172 widget.instantiateChildren = !(proto && proto.stopParser && !(options.template)); 28173 widget.instantiate = !parent || (parent.instantiate && parent.instantiateChildren); 28174 return widget.instantiate; 28175 })); 28176 }); 28177 }else{ 28178 // There were no modules to load, so just resolve with the parsed nodes. This separate code path is for 28179 // efficiency, to avoid running the require() and the callback code above. 28180 d.resolve(list); 28181 } 28182 28183 // Return the promise 28184 return d.promise; 28185 }, 28186 28187 _require: function(/*DOMNode*/ script, /*Object?*/ options){ 28188 // summary: 28189 // Helper for _scanAMD(). Takes a `<script type=dojo/require>bar: "acme/bar", ...</script>` node, 28190 // calls require() to load the specified modules and (asynchronously) assign them to the specified global 28191 // variables, and returns a Promise for when that operation completes. 28192 // 28193 // In the example above, it is effectively doing a require(["acme/bar", ...], function(a){ bar = a; }). 28194 28195 var hash = myEval("{" + script.innerHTML + "}"), // can't use dojo/json::parse() because maybe no quotes 28196 vars = [], 28197 mids = [], 28198 d = new Deferred(); 28199 28200 var contextRequire = (options && options.contextRequire) || require; 28201 28202 for(var name in hash){ 28203 vars.push(name); 28204 mids.push(hash[name]); 28205 } 28206 28207 contextRequire(mids, function(){ 28208 for(var i = 0; i < vars.length; i++){ 28209 dlang.setObject(vars[i], arguments[i]); 28210 } 28211 d.resolve(arguments); 28212 }); 28213 28214 return d.promise; 28215 }, 28216 28217 _scanAmd: function(root, options){ 28218 // summary: 28219 // Scans the DOM for any declarative requires and returns their values. 28220 // description: 28221 // Looks for `<script type=dojo/require>bar: "acme/bar", ...</script>` node, calls require() to load the 28222 // specified modules and (asynchronously) assign them to the specified global variables, 28223 // and returns a Promise for when those operations complete. 28224 // root: DomNode 28225 // The node to base the scan from. 28226 // options: Object? 28227 // a kwArgs options object, see parse() for details 28228 28229 // Promise that resolves when all the <script type=dojo/require> nodes have finished loading. 28230 var deferred = new Deferred(), 28231 promise = deferred.promise; 28232 deferred.resolve(true); 28233 28234 var self = this; 28235 query("script[type='dojo/require']", root).forEach(function(node){ 28236 // Fire off require() call for specified modules. Chain this require to fire after 28237 // any previous requires complete, so that layers can be loaded before individual module require()'s fire. 28238 promise = promise.then(function(){ 28239 return self._require(node, options); 28240 }); 28241 28242 // Remove from DOM so it isn't seen again 28243 node.parentNode.removeChild(node); 28244 }); 28245 28246 return promise; 28247 }, 28248 28249 parse: function(rootNode, options){ 28250 // summary: 28251 // Scan the DOM for class instances, and instantiate them. 28252 // description: 28253 // Search specified node (or root node) recursively for class instances, 28254 // and instantiate them. Searches for either data-dojo-type="Class" or 28255 // dojoType="Class" where "Class" is a a fully qualified class name, 28256 // like `dijit/form/Button` 28257 // 28258 // Using `data-dojo-type`: 28259 // Attributes using can be mixed into the parameters used to instantiate the 28260 // Class by using a `data-dojo-props` attribute on the node being converted. 28261 // `data-dojo-props` should be a string attribute to be converted from JSON. 28262 // 28263 // Using `dojoType`: 28264 // Attributes are read from the original domNode and converted to appropriate 28265 // types by looking up the Class prototype values. This is the default behavior 28266 // from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will 28267 // go away in Dojo 2.0. 28268 // rootNode: DomNode? 28269 // A default starting root node from which to start the parsing. Can be 28270 // omitted, defaulting to the entire document. If omitted, the `options` 28271 // object can be passed in this place. If the `options` object has a 28272 // `rootNode` member, that is used. 28273 // options: Object? 28274 // A hash of options. 28275 // 28276 // - noStart: Boolean?: 28277 // when set will prevent the parser from calling .startup() 28278 // when locating the nodes. 28279 // - rootNode: DomNode?: 28280 // identical to the function's `rootNode` argument, though 28281 // allowed to be passed in via this `options object. 28282 // - template: Boolean: 28283 // If true, ignores ContentPane's stopParser flag and parses contents inside of 28284 // a ContentPane inside of a template. This allows dojoAttachPoint on widgets/nodes 28285 // nested inside the ContentPane to work. 28286 // - inherited: Object: 28287 // Hash possibly containing dir and lang settings to be applied to 28288 // parsed widgets, unless there's another setting on a sub-node that overrides 28289 // - scope: String: 28290 // Root for attribute names to search for. If scopeName is dojo, 28291 // will search for data-dojo-type (or dojoType). For backwards compatibility 28292 // reasons defaults to dojo._scopeName (which is "dojo" except when 28293 // multi-version support is used, when it will be something like dojo16, dojo20, etc.) 28294 // - propsThis: Object: 28295 // If specified, "this" referenced from data-dojo-props will refer to propsThis. 28296 // Intended for use from the widgets-in-template feature of `dijit._WidgetsInTemplateMixin` 28297 // - contextRequire: Function: 28298 // If specified, this require is utilised for looking resolving modules instead of the 28299 // `dojo/parser` context `require()`. Intended for use from the widgets-in-template feature of 28300 // `dijit._WidgetsInTemplateMixin`. 28301 // returns: Mixed 28302 // Returns a blended object that is an array of the instantiated objects, but also can include 28303 // a promise that is resolved with the instantiated objects. This is done for backwards 28304 // compatibility. If the parser auto-requires modules, it will always behave in a promise 28305 // fashion and `parser.parse().then(function(instances){...})` should be used. 28306 // example: 28307 // Parse all widgets on a page: 28308 // | parser.parse(); 28309 // example:
28310 // Parse all classes within the node with id="foo" 28311 // | parser.parse(dojo.byId('foo')); 28312 // example: 28313 // Parse all classes in a page, but do not call .startup() on any 28314 // child 28315 // | parser.parse({ noStart: true }) 28316 // example: 28317 // Parse all classes in a node, but do not call .startup() 28318 // | parser.parse(someNode, { noStart:true }); 28319 // | // or 28320 // | parser.parse({ noStart:true, rootNode: someNode }); 28321 28322 // determine the root node and options based on the passed arguments. 28323 var root; 28324 if(!options && rootNode && rootNode.rootNode){ 28325 options = rootNode; 28326 root = options.rootNode; 28327 }else if(rootNode && dlang.isObject(rootNode) && !("nodeType" in rootNode)){ 28328 options = rootNode; 28329 }else{ 28330 root = rootNode; 28331 } 28332 root = root ? dom.byId(root) : dwindow.body(); 28333 28334 options = options || {}; 28335 28336 var mixin = options.template ? { template: true } : {}, 28337 instances = [], 28338 self = this; 28339 28340 // First scan for any <script type=dojo/require> nodes, and execute. 28341 // Then scan for all nodes with data-dojo-type, and load any unloaded modules. 28342 // Then build the object instances. Add instances to already existing (but empty) instances[] array, 28343 // which may already have been returned to caller. Also, use otherwise to collect and throw any errors 28344 // that occur during the parse(). 28345 var p = 28346 this._scanAmd(root, options).then(function(){ 28347 return self.scan(root, options); 28348 }).then(function(parsedNodes){
28349 return self._instantiate(parsedNodes, mixin, options, true); 28350 }).then(function(_instances){ 28351 // Copy the instances into the instances[] array we declared above, and are accessing as 28352 // our return value. 28353 return instances = instances.concat(_instances); 28354 }).otherwise(function(e){ 28355 // TODO Modify to follow better pattern for promise error management when available 28356 console.error("dojo/parser::parse() error", e); 28357 throw e; 28358 }); 28359 28360 // Blend the array with the promise 28361 dlang.mixin(instances, p); 28362 return instances; 28363 } 28364 }; 28365 28366 if( 1 ){ 28367 dojo.parser = parser; 28368 } 28369 28370 // Register the parser callback. It should be the first callback 28371 // after the a11y test. 28372 if(config.parseOnLoad){ 28373 ready(100, parser, "parse"); 28374 } 28375 28376 return parser; 28377}); 28378 28379}, 28380'dojo/_base/url':function(){ 28381define(["./kernel"], function(dojo){ 28382 // module: 28383 // dojo/url 28384 28385 var 28386 ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"), 28387 ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"), 28388 _Url = function(){ 28389 var n = null, 28390 _a = arguments, 28391 uri = [_a[0]]; 28392 // resolve uri components relative to each other 28393 for(var i = 1; i<_a.length; i++){ 28394 if(!_a[i]){ continue; } 28395 28396 // Safari doesn't support this.constructor so we have to be explicit 28397 // FIXME: Tracked (and fixed) in Webkit bug 3537. 28398 // http://bugs.webkit.org/show_bug.cgi?id=3537 28399 var relobj = new _Url(_a[i]+""), 28400 uriobj = new _Url(uri[0]+""); 28401 28402 if( 28403 relobj.path == "" && 28404 !relobj.scheme && 28405 !relobj.authority && 28406 !relobj.query 28407 ){ 28408 if(relobj.fragment != n){ 28409 uriobj.fragment = relobj.fragment; 28410 } 28411 relobj = uriobj; 28412 }else if(!relobj.scheme){ 28413 relobj.scheme = uriobj.scheme; 28414 28415 if(!relobj.authority){ 28416 relobj.authority = uriobj.authority; 28417 28418 if(relobj.path.charAt(0) != "/"){ 28419 var path = uriobj.path.substring(0, 28420 uriobj.path.lastIndexOf("/") + 1) + relobj.path; 28421 28422 var segs = path.split("/"); 28423 for(var j = 0; j < segs.length; j++){ 28424 if(segs[j] == "."){ 28425 // flatten "./" references 28426 if(j == segs.length - 1){ 28427 segs[j] = ""; 28428 }else{ 28429 segs.splice(j, 1); 28430 j--; 28431 } 28432 }else if(j > 0 && !(j == 1 && segs[0] == "") && 28433 segs[j] == ".." && segs[j-1] != ".."){ 28434 // flatten "../" references 28435 if(j == (segs.length - 1)){ 28436 segs.splice(j, 1); 28437 segs[j - 1] = ""; 28438 }else{ 28439 segs.splice(j - 1, 2); 28440 j -= 2; 28441 } 28442 } 28443 } 28444 relobj.path = segs.join("/"); 28445 } 28446 } 28447 } 28448 28449 uri = []; 28450 if(relobj.scheme){ 28451 uri.push(relobj.scheme, ":"); 28452 } 28453 if(relobj.authority){ 28454 uri.push("//", relobj.authority); 28455 } 28456 uri.push(relobj.path); 28457 if(relobj.query){ 28458 uri.push("?", relobj.query); 28459 } 28460 if(relobj.fragment){ 28461 uri.push("#", relobj.fragment); 28462 } 28463 } 28464 28465 this.uri = uri.join(""); 28466 28467 // break the uri into its main components 28468 var r = this.uri.match(ore); 28469 28470 this.scheme = r[2] || (r[1] ? "" : n); 28471 this.authority = r[4] || (r[3] ? "" : n); 28472 this.path = r[5]; // can never be undefined 28473 this.query = r[7] || (r[6] ? "" : n); 28474 this.fragment = r[9] || (r[8] ? "" : n); 28475 28476 if(this.authority != n){ 28477 // server based naming authority 28478 r = this.authority.match(ire); 28479 28480 this.user = r[3] || n; 28481 this.password = r[4] || n; 28482 this.host = r[6] || r[7]; // ipv6 || ipv4 28483 this.port = r[9] || n; 28484 } 28485 }; 28486 _Url.prototype.toString = function(){ return this.uri; }; 28487 28488 return dojo._Url = _Url; 28489}); 28490 28491}, 28492'dojo/promise/all':function(){ 28493define([ 28494 "../_base/array", 28495 "../Deferred", 28496 "../when" 28497], function(array, Deferred, when){ 28498 "use strict"; 28499 28500 // module: 28501 // dojo/promise/all 28502 28503 var some = array.some; 28504 28505 return function all(objectOrArray){ 28506 // summary: 28507 // Takes multiple promises and returns a new promise that is fulfilled 28508 // when all promises have been resolved or one has been rejected. 28509 // description: 28510 // Takes multiple promises and returns a new promise that is fulfilled 28511 // when all promises have been resolved or one has been rejected. If one of 28512 // the promises is rejected, the returned promise is also rejected. Canceling 28513 // the returned promise will *not* cancel any passed promises. 28514 // objectOrArray: Object|Array? 28515 // The promise will be fulfilled with a list of results if invoked with an 28516 // array, or an object of results when passed an object (using the same 28517 // keys). If passed neither an object or array it is resolved with an 28518 // undefined value. 28519 // returns: dojo/promise/Promise 28520 28521 var object, array; 28522 if(objectOrArray instanceof Array){ 28523 array = objectOrArray; 28524 }else if(objectOrArray && typeof objectOrArray === "object"){ 28525 object = objectOrArray; 28526 } 28527 28528 var results; 28529 var keyLookup = []; 28530 if(object){ 28531 array = []; 28532 for(var key in object){ 28533 if(Object.hasOwnProperty.call(object, key)){ 28534 keyLookup.push(key); 28535 array.push(object[key]); 28536 } 28537 } 28538 results = {}; 28539 }else if(array){ 28540 results = []; 28541 } 28542 28543 if(!array || !array.length){ 28544 return new Deferred().resolve(results); 28545 } 28546 28547 var deferred = new Deferred(); 28548 deferred.promise.always(function(){ 28549 results = keyLookup = null; 28550 }); 28551 var waiting = array.length; 28552 some(array, function(valueOrPromise, index){ 28553 if(!object){ 28554 keyLookup.push(index); 28555 } 28556 when(valueOrPromise, function(value){ 28557 if(!deferred.isFulfilled()){ 28558 results[keyLookup[index]] = value; 28559 if(--waiting === 0){ 28560 deferred.resolve(results); 28561 } 28562 } 28563 }, deferred.reject); 28564 return deferred.isFulfilled(); 28565 }); 28566 return deferred.promise; // dojo/promise/Promise 28567 }; 28568}); 28569 28570}, 28571'dpage/widgets/Dialog':function(){ 28572define([ 28573 "dojo/_base/declare" 28574 , "dojo/on" 28575 , "dojo/_base/event" 28576 , "jQueryPrivate"
28577 28578 /*, "xstyle/css!jquery-ui/themes/smoothness/jquery-ui.css", "xstyle/css!dpage/widgets/Dialog.css"*/ 28579 , "jquery-ui/ui/dialog" 28580 , "dpage/widgets/Page" 28581], 28582 function (declare, on, event, $) { 28583 /** 28584 * @namespace dpage 28585 */ 28586 /** 28587 * @namespace widgets 28588 * @memberOf dpage 28589 */ 28590 /** 28591 * Base Class for building or displaying Dialogs 28592 * @class Dialog 28593 * @param {Object} [options] Optional options for the widget 28594 * @param {String} [options.title] The title to display in the title bar of the dialog. 28595 * @param {bool} [options.noDefaultCSS] Default false. If true, no css will be required in for the widget. 28596 * @param {Number} [options.height] The height of the dialog. 28597 * @param {Number} [options.width] The width of the dialog. 28598 * @param {bool} [options.OKButton] Display an OK button or not that will close the dialog. Default is false for no button. 28599 * @param {Object} [options.model] Data destined for Container child controls. This is an object where each property value is a dpage.modules.TabularModel *or* 28600 * an object that conforms to the structure that can be used to pass to the dpage.modules.TabularModel constructor in the model property. 28601 * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady. 28602 * @param {function} [options.widgetsParsedCallback] callback function for when widgets in this container are parsed. 28603 * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided 28604 * markup. As with all containers, the markup can contain widgets that can be accessed through 28605 * getWidget() or getWidgets(). 28606 * @param {dpage.widgets.Container} [options.container] The container of the widget. 28607 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 28608 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 28609 * is created. 28610 * @param {Object} [containerNode] Optional container node to tie the widget to. 28611 * @memberOf dpage.widgets 28612 * @extends {dpage.widgets.Container} 28613 */ 28614 return declare("dpage.widgets.Dialog", [dpage.widgets.Container], /** @lends dpage.widgets.Dialog.prototype */ { 28615 _dialog: null, 28616 _height: null, 28617 _width: null, 28618 _displayOKButton : false, 28619 constructor: function (options, srcNodeRef) { 28620 28621 if (options != null) { 28622 if (options.height != null) 28623 this._height = options.height; 28624 if (options.width != null) 28625 this._width = options.width; 28626 if (options.templateString != null) 28627 this.templateString = options.templateString; 28628 if (options.OKButton) 28629 this._displayOKButton = true; 28630 else 28631 this._displayOKButton = false; 28632 } 28633 28634 if (this._containerNode.nodeName == "SPAN" && this._containerNode.style.display == "" && 28635 (this._width != null || this._height != null)) { 28636 this._containerNode.style.display = "inline-block"; 28637 } 28638 28639 if (options == null || !options.noDefaultCSS) { 28640 //register with the page obj that we have pending css. 28641 dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Dialog", false); 28642 28643 require(["xstyle/css!jquery-ui/themes/smoothness/jquery-ui.css", "xstyle/css!dpage/widgets/Dialog.css"], function () { 28644 //register with the page that we are done loading css. 28645 dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Dialog", true); 28646 }); 28647 } 28648 28649 }, 28650 buildRendering: function () { 28651 return this.inherited(arguments); 28652 }, 28653 postCreate: function () 28654 { 28655 var self = this; 28656 var options = { 28657 autoOpen: false, 28658 modal: true, 28659 buttons: { 28660 }, 28661 close: function () { 28662 self.close(); 28663 } 28664 }; 28665 28666 if (this._displayOKButton) 28667 options.buttons.OK = function () { self.close(); } 28668 28669 if (this._height) 28670 options.height = this._height; 28671 if (this._width) 28672 options.width = this._width; 28673 28674 this._dialog = $(this.domNode).dialog(options); 28675 }, 28676 /**
28677 * Display the dialog. 28678 * @returns {void} 28679 */ 28680 show: function () 28681 { 28682 this._dialog.dialog("open"); 28683 if (this.getDomNode().parentNode.style.zIndex == "") 28684 this.getDomNode().parentNode.style.zIndex = 101; 28685 }, 28686 /** 28687 * Close (hide) the dialog 28688 * @returns {void} 28689 */ 28690 close: function () 28691 { 28692 $(this._dialog).dialog("destroy").remove(); 28693 this.clearWidgets(); 28694 }, 28695 widgetsInTemplate: true 28696 }); 28697 } 28698); 28699}, 28700'jQueryPrivate/jQueryPrivate':function(){ 28701define(['jquery'], function (jq) { 28702 return jq.noConflict(true); 28703}); 28704}, 28705'jquery/jquery':function(){ 28706/*! 28707 * jQuery JavaScript Library v2.1.3 28708 * http://jquery.com/ 28709 * 28710 * Includes Sizzle.js 28711 * http://sizzlejs.com/ 28712 * 28713 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors 28714 * Released under the MIT license 28715 * http://jquery.org/license 28716 * 28717 * Date: 2014-12-18T15:11Z 28718 */ 28719 28720(function( global, factory ) { 28721 28722 if ( typeof module === "object" && typeof module.exports === "object" ) { 28723 // For CommonJS and CommonJS-like environments where a proper `window` 28724 // is present, execute the factory and get jQuery. 28725 // For environments that do not have a `window` with a `document` 28726 // (such as Node.js), expose a factory as module.exports. 28727 // This accentuates the need for the creation of a real `window`. 28728 // e.g. var jQuery = require("jquery")(window); 28729 // See ticket #14549 for more info. 28730 module.exports = global.document ? 28731 factory( global, true ) : 28732 function( w ) { 28733 if ( !w.document ) { 28734 throw new Error( "jQuery requires a window with a document" ); 28735 } 28736 return factory( w ); 28737 }; 28738 } else { 28739 factory( global ); 28740 } 28741 28742// Pass this if window is not defined yet 28743}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { 28744 28745// Support: Firefox 18+ 28746// Can't be in strict mode, several libs including ASP.NET trace 28747// the stack via arguments.caller.callee and Firefox dies if 28748// you try to trace through "use strict" call chains. (#13335) 28749// 28750 28751var arr = []; 28752 28753var slice = arr.slice; 28754 28755var concat = arr.concat; 28756 28757var push = arr.push; 28758 28759var indexOf = arr.indexOf; 28760 28761var class2type = {}; 28762 28763var toString = class2type.toString; 28764 28765var hasOwn = class2type.hasOwnProperty; 28766 28767var support = {}; 28768 28769 28770 28771var 28772 // Use the correct document accordingly with window argument (sandbox) 28773 document = window.document, 28774 28775 version = "2.1.3", 28776 28777 // Define a local copy of jQuery 28778 jQuery = function( selector, context ) { 28779 // The jQuery object is actually just the init constructor 'enhanced' 28780 // Need init if jQuery is called (just allow error to be thrown if not included) 28781 return new jQuery.fn.init( selector, context ); 28782 }, 28783 28784 // Support: Android<4.1 28785 // Make sure we trim BOM and NBSP 28786 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, 28787 28788 // Matches dashed string for camelizing 28789 rmsPrefix = /^-ms-/, 28790 rdashAlpha = /-([\da-z])/gi, 28791 28792 // Used by jQuery.camelCase as callback to replace() 28793 fcamelCase = function( all, letter ) { 28794 return letter.toUpperCase(); 28795 }; 28796 28797jQuery.fn = jQuery.prototype = { 28798 // The current version of jQuery being used 28799 jquery: version, 28800 28801 constructor: jQuery, 28802 28803 // Start with an empty selector 28804 selector: "", 28805 28806 // The default length of a jQuery object is 0 28807 length: 0, 28808 28809 toArray: function() { 28810 return slice.call( this ); 28811 }, 28812 28813 // Get the Nth element in the matched element set OR 28814 // Get the whole matched element set as a clean array 28815 get: function( num ) { 28816 return num != null ? 28817 28818 // Return just the one element from the set 28819 ( num < 0 ? this[ num + this.length ] : this[ num ] ) : 28820 28821 // Return all the elements in a clean array 28822 slice.call( this ); 28823 }, 28824 28825 // Take an array of elements and push it onto the stack 28826 // (returning the new matched element set) 28827 pushStack: function( elems ) { 28828 28829 // Build a new jQuery matched element set 28830 var ret = jQuery.merge( this.constructor(), elems ); 28831 28832 // Add the old object onto the stack (as a reference)
28833 ret.prevObject = this; 28834 ret.context = this.context; 28835 28836 // Return the newly-formed element set 28837 return ret; 28838 }, 28839 28840 // Execute a callback for every element in the matched set. 28841 // (You can seed the arguments with an array of args, but this is 28842 // only used internally.) 28843 each: function( callback, args ) { 28844 return jQuery.each( this, callback, args ); 28845 }, 28846 28847 map: function( callback ) { 28848 return this.pushStack( jQuery.map(this, function( elem, i ) { 28849 return callback.call( elem, i, elem ); 28850 })); 28851 }, 28852 28853 slice: function() { 28854 return this.pushStack( slice.apply( this, arguments ) ); 28855 }, 28856 28857 first: function() { 28858 return this.eq( 0 ); 28859 }, 28860 28861 last: function() { 28862 return this.eq( -1 ); 28863 }, 28864 28865 eq: function( i ) { 28866 var len = this.length, 28867 j = +i + ( i < 0 ? len : 0 ); 28868 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); 28869 }, 28870 28871 end: function() { 28872 return this.prevObject || this.constructor(null); 28873 }, 28874 28875 // For internal use only. 28876 // Behaves like an Array's method, not like a jQuery method. 28877 push: push, 28878 sort: arr.sort, 28879 splice: arr.splice 28880}; 28881 28882jQuery.extend = jQuery.fn.extend = function() { 28883 var options, name, src, copy, copyIsArray, clone, 28884 target = arguments[0] || {}, 28885 i = 1, 28886 length = arguments.length, 28887 deep = false; 28888 28889 // Handle a deep copy situation 28890 if ( typeof target === "boolean" ) { 28891 deep = target; 28892 28893 // Skip the boolean and the target 28894 target = arguments[ i ] || {}; 28895 i++; 28896 } 28897 28898 // Handle case when target is a string or something (possible in deep copy) 28899 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 28900 target = {}; 28901 } 28902 28903 // Extend jQuery itself if only one argument is passed 28904 if ( i === length ) { 28905 target = this; 28906 i--; 28907 } 28908 28909 for ( ; i < length; i++ ) { 28910 // Only deal with non-null/undefined values 28911 if ( (options = arguments[ i ]) != null ) { 28912 // Extend the base object 28913 for ( name in options ) { 28914 src = target[ name ]; 28915 copy = options[ name ]; 28916 28917 // Prevent never-ending loop 28918 if ( target === copy ) { 28919 continue; 28920 } 28921 28922 // Recurse if we're merging plain objects or arrays 28923 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 28924 if ( copyIsArray ) { 28925 copyIsArray = false; 28926 clone = src && jQuery.isArray(src) ? src : []; 28927 28928 } else { 28929 clone = src && jQuery.isPlainObject(src) ? src : {}; 28930 } 28931 28932 // Never move original objects, clone them 28933 target[ name ] = jQuery.extend( deep, clone, copy ); 28934 28935 // Don't bring in undefined values 28936 } else if ( copy !== undefined ) { 28937 target[ name ] = copy; 28938 } 28939 } 28940 } 28941 } 28942 28943 // Return the modified object 28944 return target; 28945}; 28946 28947jQuery.extend({ 28948 // Unique for each copy of jQuery on the page 28949 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), 28950 28951 // Assume jQuery is ready without the ready module 28952 isReady: true, 28953 28954 error: function( msg ) { 28955 throw new Error( msg ); 28956 }, 28957 28958 noop: function() {}, 28959 28960 isFunction: function( obj ) { 28961 return jQuery.type(obj) === "function"; 28962 }, 28963 28964 isArray: Array.isArray, 28965 28966 isWindow: function( obj ) { 28967 return obj != null && obj === obj.window; 28968 }, 28969 28970 isNumeric: function( obj ) { 28971 // parseFloat NaNs numeric-cast false positives (null|true|false|"") 28972 // ...but misinterprets leading-number strings, particularly hex literals ("0x...") 28973 // subtraction forces infinities to NaN 28974 // adding 1 corrects loss of precision from parseFloat (#15100) 28975 return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; 28976 }, 28977 28978 isPlainObject: function( obj ) { 28979 // Not plain objects: 28980 // - Any object or value whose internal [[Class]] property is not "[object Object]" 28981 // - DOM nodes 28982 // - window 28983 if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 28984 return false; 28985 } 28986 28987 if ( obj.constructor && 28988 !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { 28989 return false; 28990 } 28991 28992 // If the function hasn't returned already, we're confident that 28993 // |obj| is a plain object, created by {} or constructed with new Object 28994 return true; 28995 }, 28996 28997 isEmptyObject: function( obj ) { 28998 var name; 28999 for ( name in obj ) { 29000 return false; 29001 } 29002 return true; 29003 }, 29004 29005 type: function( obj ) { 29006 if ( obj == null ) { 29007 return obj + ""; 29008 }
29009 // Support: Android<4.0, iOS<6 (functionish RegExp) 29010 return typeof obj === "object" || typeof obj === "function" ? 29011 class2type[ toString.call(obj) ] || "object" : 29012 typeof obj; 29013 }, 29014 29015 // Evaluates a script in a global context 29016 globalEval: function( code ) { 29017 var script, 29018 indirect = eval; 29019 29020 code = jQuery.trim( code ); 29021 29022 if ( code ) { 29023 // If the code includes a valid, prologue position 29024 // strict mode pragma, execute code by injecting a 29025 // script tag into the document. 29026 if ( code.indexOf("use strict") === 1 ) { 29027 script = document.createElement("script"); 29028 script.text = code; 29029 document.head.appendChild( script ).parentNode.removeChild( script ); 29030 } else { 29031 // Otherwise, avoid the DOM node creation, insertion 29032 // and removal by using an indirect global eval 29033 indirect( code ); 29034 } 29035 } 29036 }, 29037 29038 // Convert dashed to camelCase; used by the css and data modules 29039 // Support: IE9-11+ 29040 // Microsoft forgot to hump their vendor prefix (#9572) 29041 camelCase: function( string ) { 29042 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 29043 }, 29044 29045 nodeName: function( elem, name ) { 29046 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 29047 }, 29048 29049 // args is for internal usage only 29050 each: function( obj, callback, args ) { 29051 var value, 29052 i = 0, 29053 length = obj.length, 29054 isArray = isArraylike( obj ); 29055 29056 if ( args ) { 29057 if ( isArray ) { 29058 for ( ; i < length; i++ ) { 29059 value = callback.apply( obj[ i ], args ); 29060 29061 if ( value === false ) { 29062 break; 29063 } 29064 } 29065 } else { 29066 for ( i in obj ) { 29067 value = callback.apply( obj[ i ], args ); 29068 29069 if ( value === false ) { 29070 break; 29071 } 29072 } 29073 } 29074 29075 // A special, fast, case for the most common use of each 29076 } else { 29077 if ( isArray ) { 29078 for ( ; i < length; i++ ) { 29079 value = callback.call( obj[ i ], i, obj[ i ] ); 29080 29081 if ( value === false ) { 29082 break; 29083 } 29084 } 29085 } else { 29086 for ( i in obj ) { 29087 value = callback.call( obj[ i ], i, obj[ i ] ); 29088 29089 if ( value === false ) { 29090 break; 29091 } 29092 } 29093 } 29094 } 29095 29096 return obj; 29097 }, 29098 29099 // Support: Android<4.1 29100 trim: function( text ) { 29101 return text == null ? 29102 "" : 29103 ( text + "" ).replace( rtrim, "" ); 29104 }, 29105 29106 // results is for internal usage only 29107 makeArray: function( arr, results ) { 29108 var ret = results || []; 29109 29110 if ( arr != null ) { 29111 if ( isArraylike( Object(arr) ) ) { 29112 jQuery.merge( ret, 29113 typeof arr === "string" ? 29114 [ arr ] : arr 29115 ); 29116 } else { 29117 push.call( ret, arr ); 29118 } 29119 } 29120 29121 return ret; 29122 }, 29123 29124 inArray: function( elem, arr, i ) { 29125 return arr == null ? -1 : indexOf.call( arr, elem, i ); 29126 }, 29127 29128 merge: function( first, second ) { 29129 var len = +second.length, 29130 j = 0, 29131 i = first.length; 29132 29133 for ( ; j < len; j++ ) { 29134 first[ i++ ] = second[ j ]; 29135 } 29136 29137 first.length = i; 29138 29139 return first; 29140 }, 29141 29142 grep: function( elems, callback, invert ) { 29143 var callbackInverse, 29144 matches = [], 29145 i = 0, 29146 length = elems.length, 29147 callbackExpect = !invert; 29148 29149 // Go through the array, only saving the items 29150 // that pass the validator function 29151 for ( ; i < length; i++ ) { 29152 callbackInverse = !callback( elems[ i ], i ); 29153 if ( callbackInverse !== callbackExpect ) { 29154 matches.push( elems[ i ] ); 29155 } 29156 } 29157 29158 return matches; 29159 }, 29160 29161 // arg is for internal usage only 29162 map: function( elems, callback, arg ) { 29163 var value, 29164 i = 0, 29165 length = elems.length, 29166 isArray = isArraylike( elems ), 29167 ret = []; 29168 29169 // Go through the array, translating each of the items to their new values 29170 if ( isArray ) { 29171 for ( ; i < length; i++ ) { 29172 value = callback( elems[ i ], i, arg ); 29173 29174 if ( value != null ) { 29175 ret.push( value ); 29176 } 29177 } 29178 29179 // Go through every key on the object, 29180 } else { 29181 for ( i in elems ) { 29182 value = callback( elems[ i ], i, arg ); 29183 29184 if ( value != null ) { 29185 ret.push( value ); 29186 } 29187 } 29188 } 29189 29190 // Flatten any nested arrays 29191 return concat.apply( [], ret ); 29192 }, 29193 29194 // A global GUID counter for objects 29195 guid: 1, 29196 29197 // Bind a function to a context, optionally partially applying any 29198 // arguments. 29199 proxy: function( fn, context ) { 29200 var tmp, args, proxy; 29201 29202 if ( typeof context === "string" ) { 29203 tmp = fn[ context ];
29204 context = fn; 29205 fn = tmp; 29206 } 29207 29208 // Quick check to determine if target is callable, in the spec 29209 // this throws a TypeError, but we will just return undefined. 29210 if ( !jQuery.isFunction( fn ) ) { 29211 return undefined; 29212 } 29213 29214 // Simulated bind 29215 args = slice.call( arguments, 2 ); 29216 proxy = function() { 29217 return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); 29218 }; 29219 29220 // Set the guid of unique handler to the same of original handler, so it can be removed 29221 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 29222 29223 return proxy; 29224 }, 29225 29226 now: Date.now, 29227 29228 // jQuery.support is not used in Core but other projects attach their 29229 // properties to it so it needs to exist. 29230 support: support 29231}); 29232 29233// Populate the class2type map 29234jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { 29235 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 29236}); 29237 29238function isArraylike( obj ) { 29239 var length = obj.length, 29240 type = jQuery.type( obj ); 29241 29242 if ( type === "function" || jQuery.isWindow( obj ) ) { 29243 return false; 29244 } 29245 29246 if ( obj.nodeType === 1 && length ) { 29247 return true; 29248 } 29249 29250 return type === "array" || length === 0 || 29251 typeof length === "number" && length > 0 && ( length - 1 ) in obj; 29252} 29253var Sizzle = 29254/*! 29255 * Sizzle CSS Selector Engine v2.2.0-pre 29256 * http://sizzlejs.com/ 29257 * 29258 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors 29259 * Released under the MIT license 29260 * http://jquery.org/license 29261 * 29262 * Date: 2014-12-16 29263 */ 29264(function( window ) { 29265 29266var i, 29267 support, 29268 Expr, 29269 getText, 29270 isXML, 29271 tokenize, 29272 compile, 29273 select, 29274 outermostContext, 29275 sortInput, 29276 hasDuplicate, 29277 29278 // Local document vars 29279 setDocument, 29280 document, 29281 docElem, 29282 documentIsHTML, 29283 rbuggyQSA, 29284 rbuggyMatches, 29285 matches, 29286 contains, 29287 29288 // Instance-specific data 29289 expando = "sizzle" + 1 * new Date(), 29290 preferredDoc = window.document, 29291 dirruns = 0, 29292 done = 0, 29293 classCache = createCache(), 29294 tokenCache = createCache(), 29295 compilerCache = createCache(), 29296 sortOrder = function( a, b ) { 29297 if ( a === b ) { 29298 hasDuplicate = true; 29299 } 29300 return 0; 29301 }, 29302 29303 // General-purpose constants 29304 MAX_NEGATIVE = 1 << 31, 29305 29306 // Instance methods 29307 hasOwn = ({}).hasOwnProperty, 29308 arr = [], 29309 pop = arr.pop, 29310 push_native = arr.push, 29311 push = arr.push, 29312 slice = arr.slice, 29313 // Use a stripped-down indexOf as it's faster than native 29314 // http://jsperf.com/thor-indexof-vs-for/5 29315 indexOf = function( list, elem ) { 29316 var i = 0, 29317 len = list.length; 29318 for ( ; i < len; i++ ) { 29319 if ( list[i] === elem ) { 29320 return i; 29321 } 29322 } 29323 return -1; 29324 }, 29325 29326 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", 29327 29328 // Regular expressions 29329 29330 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace 29331 whitespace = "[\\x20\\t\\r\\n\\f]", 29332 // http://www.w3.org/TR/css3-syntax/#characters 29333 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", 29334 29335 // Loosely modeled on CSS identifier characters 29336 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors 29337 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 29338 identifier = characterEncoding.replace( "w", "w#" ), 29339 29340 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors 29341 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + 29342 // Operator (capture 2) 29343 "*([*^$|!~]?=)" + whitespace + 29344 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" 29345 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + 29346 "*\\]", 29347 29348 pseudos = ":(" + characterEncoding + ")(?:\\((" + 29349 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: 29350 // 1. quoted (capture 3; capture 4 or capture 5)
29351 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + 29352 // 2. simple (capture 6) 29353 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + 29354 // 3. anything else (capture 2) 29355 ".*" + 29356 ")\\)|)", 29357 29358 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 29359 rwhitespace = new RegExp( whitespace + "+", "g" ), 29360 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), 29361 29362 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 29363 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), 29364 29365 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), 29366 29367 rpseudo = new RegExp( pseudos ), 29368 ridentifier = new RegExp( "^" + identifier + "$" ), 29369 29370 matchExpr = { 29371 "ID": new RegExp( "^#(" + characterEncoding + ")" ), 29372 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), 29373 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), 29374 "ATTR": new RegExp( "^" + attributes ), 29375 "PSEUDO": new RegExp( "^" + pseudos ), 29376 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + 29377 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + 29378 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 29379 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), 29380 // For use in libraries implementing .is() 29381 // We use this for POS matching in `select` 29382 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + 29383 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) 29384 }, 29385 29386 rinputs = /^(?:input|select|textarea|button)$/i, 29387 rheader = /^h\d$/i, 29388 29389 rnative = /^[^{]+\{\s*\[native \w/, 29390 29391 // Easily-parseable/retrievable ID or TAG or CLASS selectors 29392 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 29393 29394 rsibling = /[+~]/, 29395 rescape = /'|\\/g, 29396 29397 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters 29398 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), 29399 funescape = function( _, escaped, escapedWhitespace ) { 29400 var high = "0x" + escaped - 0x10000; 29401 // NaN means non-codepoint 29402 // Support: Firefox<24 29403 // Workaround erroneous numeric interpretation of +"0x" 29404 return high !== high || escapedWhitespace ? 29405 escaped : 29406 high < 0 ? 29407 // BMP codepoint 29408 String.fromCharCode( high + 0x10000 ) : 29409 // Supplemental Plane codepoint (surrogate pair) 29410 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); 29411 }, 29412 29413 // Used for iframes 29414 // See setDocument() 29415 // Removing the function wrapper causes a "Permission Denied" 29416 // error in IE 29417 unloadHandler = function() { 29418 setDocument(); 29419 }; 29420 29421// Optimize for push.apply( _, NodeList ) 29422try { 29423 push.apply( 29424 (arr = slice.call( preferredDoc.childNodes )), 29425 preferredDoc.childNodes 29426 ); 29427 // Support: Android<4.0 29428 // Detect silently failing push.apply 29429 arr[ preferredDoc.childNodes.length ].nodeType; 29430} catch ( e ) { 29431 push = { apply: arr.length ? 29432 29433 // Leverage slice if possible 29434 function( target, els ) { 29435 push_native.apply( target, slice.call(els) ); 29436 } : 29437 29438 // Support: IE<9 29439 // Otherwise append directly 29440 function( target, els ) { 29441 var j = target.length, 29442 i = 0; 29443 // Can't trust NodeList.length 29444 while ( (target[j++] = els[i++]) ) {} 29445 target.length = j - 1; 29446 } 29447 }; 29448} 29449 29450function Sizzle( selector, context, results, seed ) { 29451 var match, elem, m, nodeType, 29452 // QSA vars 29453 i, groups, old, nid, newContext, newSelector; 29454 29455 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { 29456 setDocument( context ); 29457 } 29458 29459 context = context || document; 29460 results = results || []; 29461 nodeType = context.nodeType; 29462 29463 if ( typeof selector !== "string" || !selector || 29464 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { 29465 29466 return results; 29467 } 29468 29469 if ( !seed && documentIsHTML ) { 29470 29471 // Try to shortcut find operations when possible (e.g., not under DocumentFragment) 29472 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { 29473 // Speed-up: Sizzle("#ID") 29474 if ( (m = match[1]) ) { 29475 if ( nodeType === 9 ) { 29476 elem = context.getElementById( m ); 29477 // Check parentNode to catch when Blackberry 4.6 returns 29478 // nodes that are no longer in the document (jQuery #6963) 29479 if ( elem && elem.parentNode ) { 29480 // Handle the case where IE, Opera, and Webkit return items 29481 // by name instead of ID 29482 if ( elem.id === m ) { 29483 results.push( elem ); 29484 return results; 29485 } 29486 } else { 29487 return results; 29488 } 29489 } else { 29490 // Context is not a document 29491 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && 29492 contains( context, elem ) && elem.id === m ) { 29493 results.push( elem ); 29494 return results; 29495 } 29496 } 29497 29498 // Speed-up: Sizzle("TAG") 29499 } else if ( match[2] ) { 29500 push.apply( results, context.getElementsByTagName( selector ) ); 29501 return results; 29502 29503 // Speed-up: Sizzle(".CLASS") 29504 } else if ( (m = match[3]) && support.getElementsByClassName ) { 29505 push.apply( results, context.getElementsByClassName( m ) ); 29506 return results; 29507 } 29508 } 29509 29510 // QSA path 29511 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { 29512 nid = old = expando; 29513 newContext = context; 29514 newSelector = nodeType !== 1 && selector; 29515 29516 // qSA works strangely on Element-rooted queries 29517 // We can work around this by specifying an extra ID on the root 29518 // and working up from there (Thanks to Andrew Dupont for the technique) 29519 // IE 8 doesn't work on object elements 29520 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { 29521 groups = tokenize( selector ); 29522 29523 if ( (old = context.getAttribute("id")) ) { 29524 nid = old.replace( rescape, "\\$&" ); 29525 } else { 29526 context.setAttribute( "id", nid ); 29527 } 29528 nid = "[id='" + nid + "'] "; 29529 29530 i = groups.length; 29531 while ( i-- ) { 29532 groups[i] = nid + toSelector( groups[i] ); 29533 }
29534 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; 29535 newSelector = groups.join(","); 29536 } 29537 29538 if ( newSelector ) { 29539 try { 29540 push.apply( results, 29541 newContext.querySelectorAll( newSelector ) 29542 ); 29543 return results; 29544 } catch(qsaError) { 29545 } finally { 29546 if ( !old ) { 29547 context.removeAttribute("id"); 29548 } 29549 } 29550 } 29551 } 29552 } 29553 29554 // All others 29555 return select( selector.replace( rtrim, "$1" ), context, results, seed ); 29556} 29557 29558/** 29559 * Create key-value caches of limited size 29560 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with 29561 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 29562 * deleting the oldest entry 29563 */ 29564function createCache() { 29565 var keys = []; 29566 29567 function cache( key, value ) { 29568 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) 29569 if ( keys.push( key + " " ) > Expr.cacheLength ) { 29570 // Only keep the most recent entries 29571 delete cache[ keys.shift() ]; 29572 } 29573 return (cache[ key + " " ] = value); 29574 } 29575 return cache; 29576} 29577 29578/** 29579 * Mark a function for special use by Sizzle 29580 * @param {Function} fn The function to mark 29581 */ 29582function markFunction( fn ) { 29583 fn[ expando ] = true; 29584 return fn; 29585} 29586 29587/** 29588 * Support testing using an element 29589 * @param {Function} fn Passed the created div and expects a boolean result 29590 */ 29591function assert( fn ) { 29592 var div = document.createElement("div"); 29593 29594 try { 29595 return !!fn( div ); 29596 } catch (e) { 29597 return false; 29598 } finally { 29599 // Remove from its parent by default 29600 if ( div.parentNode ) { 29601 div.parentNode.removeChild( div ); 29602 } 29603 // release memory in IE 29604 div = null; 29605 } 29606} 29607 29608/** 29609 * Adds the same handler for all of the specified attrs 29610 * @param {String} attrs Pipe-separated list of attributes 29611 * @param {Function} handler The method that will be applied 29612 */ 29613function addHandle( attrs, handler ) { 29614 var arr = attrs.split("|"), 29615 i = attrs.length; 29616 29617 while ( i-- ) { 29618 Expr.attrHandle[ arr[i] ] = handler; 29619 } 29620} 29621 29622/** 29623 * Checks document order of two siblings 29624 * @param {Element} a 29625 * @param {Element} b 29626 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b 29627 */ 29628function siblingCheck( a, b ) { 29629 var cur = b && a, 29630 diff = cur && a.nodeType === 1 && b.nodeType === 1 && 29631 ( ~b.sourceIndex || MAX_NEGATIVE ) - 29632 ( ~a.sourceIndex || MAX_NEGATIVE ); 29633 29634 // Use IE sourceIndex if available on both nodes 29635 if ( diff ) { 29636 return diff; 29637 } 29638 29639 // Check if b follows a 29640 if ( cur ) { 29641 while ( (cur = cur.nextSibling) ) { 29642 if ( cur === b ) { 29643 return -1; 29644 } 29645 } 29646 } 29647 29648 return a ? 1 : -1; 29649} 29650 29651/** 29652 * Returns a function to use in pseudos for input types 29653 * @param {String} type 29654 */ 29655function createInputPseudo( type ) { 29656 return function( elem ) { 29657 var name = elem.nodeName.toLowerCase(); 29658 return name === "input" && elem.type === type; 29659 }; 29660} 29661 29662/** 29663 * Returns a function to use in pseudos for buttons 29664 * @param {String} type 29665 */ 29666function createButtonPseudo( type ) { 29667 return function( elem ) { 29668 var name = elem.nodeName.toLowerCase(); 29669 return (name === "input" || name === "button") && elem.type === type; 29670 }; 29671} 29672 29673/** 29674 * Returns a function to use in pseudos for positionals 29675 * @param {Function} fn 29676 */ 29677function createPositionalPseudo( fn ) { 29678 return markFunction(function( argument ) { 29679 argument = +argument; 29680 return markFunction(function( seed, matches ) { 29681 var j, 29682 matchIndexes = fn( [], seed.length, argument ), 29683 i = matchIndexes.length; 29684 29685 // Match elements found at the specified indexes 29686 while ( i-- ) { 29687 if ( seed[ (j = matchIndexes[i]) ] ) { 29688 seed[j] = !(matches[j] = seed[j]); 29689 } 29690 } 29691 }); 29692 }); 29693} 29694 29695/** 29696 * Checks a node for validity as a Sizzle context 29697 * @param {Element|Object=} context 29698 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 29699 */ 29700function testContext( context ) { 29701 return context && typeof context.getElementsByTagName !== "undefined" && context; 29702} 29703 29704// Expose support vars for convenience 29705support = Sizzle.support = {}; 29706 29707/** 29708 * Detects XML nodes
29709 * @param {Element|Object} elem An element or a document 29710 * @returns {Boolean} True iff elem is a non-HTML XML node 29711 */ 29712isXML = Sizzle.isXML = function( elem ) { 29713 // documentElement is verified for cases where it doesn't yet exist 29714 // (such as loading iframes in IE - #4833) 29715 var documentElement = elem && (elem.ownerDocument || elem).documentElement; 29716 return documentElement ? documentElement.nodeName !== "HTML" : false; 29717}; 29718 29719/** 29720 * Sets document-related variables once based on the current document 29721 * @param {Element|Object} [doc] An element or document object to use to set the document 29722 * @returns {Object} Returns the current document 29723 */ 29724setDocument = Sizzle.setDocument = function( node ) { 29725 var hasCompare, parent, 29726 doc = node ? node.ownerDocument || node : preferredDoc; 29727 29728 // If no document and documentElement is available, return 29729 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { 29730 return document; 29731 } 29732 29733 // Set our document 29734 document = doc; 29735 docElem = doc.documentElement; 29736 parent = doc.defaultView; 29737 29738 // Support: IE>8 29739 // If iframe document is assigned to "document" variable and if iframe has been reloaded, 29740 // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 29741 // IE6-8 do not support the defaultView property so parent will be undefined 29742 if ( parent && parent !== parent.top ) { 29743 // IE11 does not have attachEvent, so all must suffer 29744 if ( parent.addEventListener ) { 29745 parent.addEventListener( "unload", unloadHandler, false ); 29746 } else if ( parent.attachEvent ) { 29747 parent.attachEvent( "onunload", unloadHandler ); 29748 } 29749 } 29750 29751 /* Support tests 29752 ---------------------------------------------------------------------- */ 29753 documentIsHTML = !isXML( doc ); 29754 29755 /* Attributes 29756 ---------------------------------------------------------------------- */ 29757 29758 // Support: IE<8 29759 // Verify that getAttribute really returns attributes and not properties 29760 // (excepting IE8 booleans) 29761 support.attributes = assert(function( div ) { 29762 div.className = "i"; 29763 return !div.getAttribute("className"); 29764 }); 29765 29766 /* getElement(s)By* 29767 ---------------------------------------------------------------------- */ 29768 29769 // Check if getElementsByTagName("*") returns only elements 29770 support.getElementsByTagName = assert(function( div ) { 29771 div.appendChild( doc.createComment("") ); 29772 return !div.getElementsByTagName("*").length; 29773 }); 29774 29775 // Support: IE<9 29776 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); 29777 29778 // Support: IE<10 29779 // Check if getElementById returns elements by name 29780 // The broken getElementById methods don't pick up programatically-set names, 29781 // so use a roundabout getElementsByName test 29782 support.getById = assert(function( div ) { 29783 docElem.appendChild( div ).id = expando; 29784 return !doc.getElementsByName || !doc.getElementsByName( expando ).length; 29785 }); 29786 29787 // ID find and filter 29788 if ( support.getById ) { 29789 Expr.find["ID"] = function( id, context ) { 29790 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { 29791 var m = context.getElementById( id ); 29792 // Check parentNode to catch when Blackberry 4.6 returns 29793 // nodes that are no longer in the document #6963 29794 return m && m.parentNode ? [ m ] : []; 29795 } 29796 }; 29797 Expr.filter["ID"] = function( id ) { 29798 var attrId = id.replace( runescape, funescape ); 29799 return function( elem ) { 29800 return elem.getAttribute("id") === attrId; 29801 }; 29802 }; 29803 } else { 29804 // Support: IE6/7 29805 // getElementById is not reliable as a find shortcut 29806 delete Expr.find["ID"]; 29807 29808 Expr.filter["ID"] = function( id ) { 29809 var attrId = id.replace( runescape, funescape ); 29810 return function( elem ) { 29811 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); 29812 return node && node.value === attrId; 29813 }; 29814 }; 29815 } 29816 29817 // Tag 29818 Expr.find["TAG"] = support.getElementsByTagName ? 29819 function( tag, context ) { 29820 if ( typeof context.getElementsByTagName !== "undefined" ) { 29821 return context.getElementsByTagName( tag ); 29822 29823 // DocumentFragment nodes don't have gEBTN 29824 } else if ( support.qsa ) { 29825 return context.querySelectorAll( tag ); 29826 } 29827 } : 29828 29829 function( tag, context ) { 29830 var elem, 29831 tmp = [], 29832 i = 0, 29833 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too 29834 results = context.getElementsByTagName( tag ); 29835 29836 // Filter out possible comments 29837 if ( tag === "*" ) { 29838 while ( (elem = results[i++]) ) { 29839 if ( elem.nodeType === 1 ) { 29840 tmp.push( elem ); 29841 } 29842 } 29843 29844 return tmp; 29845 } 29846 return results; 29847 }; 29848 29849 // Class 29850 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { 29851 if ( documentIsHTML ) { 29852 return context.getElementsByClassName( className ); 29853 } 29854 }; 29855 29856 /* QSA/matchesSelector 29857 ---------------------------------------------------------------------- */ 29858 29859 // QSA and matchesSelector support 29860 29861 // matchesSelector(:active) reports false when true (IE9/Opera 11.5) 29862 rbuggyMatches = []; 29863 29864 // qSa(:focus) reports false when true (Chrome 21) 29865 // We allow this because of a bug in IE8/9 that throws an error 29866 // whenever `document.activeElement` is accessed on an iframe 29867 // So, we allow :focus to pass through QSA all the time to avoid the IE error 29868 // See http://bugs.jquery.com/ticket/13378 29869 rbuggyQSA = []; 29870 29871 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { 29872 // Build QSA regex 29873 // Regex strategy adopted from Diego Perini 29874 assert(function( div ) { 29875 // Select is set to empty string on purpose 29876 // This is to test IE's treatment of not explicitly 29877 // setting a boolean content attribute, 29878 // since its presence should be enough 29879 // http://bugs.jquery.com/ticket/12359 29880 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" + 29881 "<select id='" + expando + "-\f]' msallowcapture=''>" + 29882 "<option selected=''></option></select>"; 29883
29884 // Support: IE8, Opera 11-12.16 29885 // Nothing should be selected when empty strings follow ^= or $= or *= 29886 // The test attribute must be unknown in Opera but "safe" for WinRT 29887 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section 29888 if ( div.querySelectorAll("[msallowcapture^='']").length ) { 29889 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); 29890 } 29891 29892 // Support: IE8 29893 // Boolean attributes and "value" are not treated correctly 29894 if ( !div.querySelectorAll("[selected]").length ) { 29895 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); 29896 } 29897 29898 // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ 29899 if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { 29900 rbuggyQSA.push("~="); 29901 } 29902 29903 // Webkit/Opera - :checked should return selected option elements 29904 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 29905 // IE8 throws error here and will not see later tests 29906 if ( !div.querySelectorAll(":checked").length ) { 29907 rbuggyQSA.push(":checked"); 29908 } 29909 29910 // Support: Safari 8+, iOS 8+ 29911 // https://bugs.webkit.org/show_bug.cgi?id=136851 29912 // In-page `selector#id sibing-combinator selector` fails 29913 if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { 29914 rbuggyQSA.push(".#.+[+~]"); 29915 } 29916 }); 29917 29918 assert(function( div ) { 29919 // Support: Windows 8 Native Apps 29920 // The type and name attributes are restricted during .innerHTML assignment 29921 var input = doc.createElement("input"); 29922 input.setAttribute( "type", "hidden" ); 29923 div.appendChild( input ).setAttribute( "name", "D" ); 29924 29925 // Support: IE8 29926 // Enforce case-sensitivity of name attribute 29927 if ( div.querySelectorAll("[name=d]").length ) { 29928 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); 29929 } 29930 29931 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) 29932 // IE8 throws error here and will not see later tests 29933 if ( !div.querySelectorAll(":enabled").length ) { 29934 rbuggyQSA.push( ":enabled", ":disabled" ); 29935 } 29936 29937 // Opera 10-11 does not throw on post-comma invalid pseudos 29938 div.querySelectorAll("*,:x"); 29939 rbuggyQSA.push(",.*:"); 29940 }); 29941 } 29942 29943 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || 29944 docElem.webkitMatchesSelector || 29945 docElem.mozMatchesSelector || 29946 docElem.oMatchesSelector || 29947 docElem.msMatchesSelector) )) ) { 29948 29949 assert(function( div ) { 29950 // Check to see if it's possible to do matchesSelector 29951 // on a disconnected node (IE 9) 29952 support.disconnectedMatch = matches.call( div, "div" ); 29953 29954 // This should fail with an exception 29955 // Gecko does not error, returns false instead 29956 matches.call( div, "[s!='']:x" ); 29957 rbuggyMatches.push( "!=", pseudos ); 29958 }); 29959 } 29960 29961 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); 29962 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); 29963 29964 /* Contains 29965 ---------------------------------------------------------------------- */ 29966 hasCompare = rnative.test( docElem.compareDocumentPosition ); 29967 29968 // Element contains another 29969 // Purposefully does not implement inclusive descendent 29970 // As in, an element does not contain itself 29971 contains = hasCompare || rnative.test( docElem.contains ) ? 29972 function( a, b ) { 29973 var adown = a.nodeType === 9 ? a.documentElement : a, 29974 bup = b && b.parentNode; 29975 return a === bup || !!( bup && bup.nodeType === 1 && ( 29976 adown.contains ? 29977 adown.contains( bup ) : 29978 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 29979 )); 29980 } : 29981 function( a, b ) { 29982 if ( b ) { 29983 while ( (b = b.parentNode) ) { 29984 if ( b === a ) { 29985 return true; 29986 } 29987 } 29988 } 29989 return false; 29990 }; 29991 29992 /* Sorting 29993 ---------------------------------------------------------------------- */ 29994 29995 // Document order sorting 29996 sortOrder = hasCompare ? 29997 function( a, b ) { 29998 29999 // Flag for duplicate removal 30000 if ( a === b ) { 30001 hasDuplicate = true; 30002 return 0; 30003 } 30004 30005 // Sort on method existence if only one input has compareDocumentPosition 30006 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 30007 if ( compare ) { 30008 return compare; 30009 } 30010 30011 // Calculate position if both inputs belong to the same document 30012 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? 30013 a.compareDocumentPosition( b ) : 30014 30015 // Otherwise we know they are disconnected 30016 1; 30017 30018 // Disconnected nodes 30019 if ( compare & 1 || 30020 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { 30021 30022 // Choose the first element that is related to our preferred document 30023 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { 30024 return -1; 30025 } 30026 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { 30027 return 1; 30028 } 30029 30030 // Maintain original order 30031 return sortInput ? 30032 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 30033 0; 30034 } 30035 30036 return compare & 4 ? -1 : 1; 30037 } : 30038 function( a, b ) { 30039 // Exit early if the nodes are identical 30040 if ( a === b ) { 30041 hasDuplicate = true; 30042 return 0; 30043 } 30044 30045 var cur, 30046 i = 0, 30047 aup = a.parentNode, 30048 bup = b.parentNode, 30049 ap = [ a ], 30050 bp = [ b ]; 30051 30052 // Parentless nodes are either documents or disconnected 30053 if ( !aup || !bup ) { 30054 return a === doc ? -1 : 30055 b === doc ? 1 : 30056 aup ? -1 : 30057 bup ? 1 : 30058 sortInput ? 30059 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 30060 0; 30061 30062 // If the nodes are siblings, we can do a quick check 30063 } else if ( aup === bup ) { 30064 return siblingCheck( a, b ); 30065 } 30066 30067 // Otherwise we need full lists of their ancestors for comparison 30068 cur = a; 30069 while ( (cur = cur.parentNode) ) { 30070 ap.unshift( cur ); 30071 } 30072 cur = b; 30073 while ( (cur = cur.parentNode) ) { 30074 bp.unshift( cur ); 30075 } 30076 30077 // Walk down the tree looking for a discrepancy 30078 while ( ap[i] === bp[i] ) { 30079 i++; 30080 } 30081 30082 return i ? 30083 // Do a sibling check if the nodes have a common ancestor 30084 siblingCheck( ap[i], bp[i] ) : 30085 30086 // Otherwise nodes in our document sort first 30087 ap[i] === preferredDoc ? -1 : 30088 bp[i] === preferredDoc ? 1 : 30089 0; 30090 }; 30091 30092 return doc; 30093};
30094 30095Sizzle.matches = function( expr, elements ) { 30096 return Sizzle( expr, null, null, elements ); 30097}; 30098 30099Sizzle.matchesSelector = function( elem, expr ) { 30100 // Set document vars if needed 30101 if ( ( elem.ownerDocument || elem ) !== document ) { 30102 setDocument( elem ); 30103 } 30104 30105 // Make sure that attribute selectors are quoted 30106 expr = expr.replace( rattributeQuotes, "='$1']" ); 30107 30108 if ( support.matchesSelector && documentIsHTML && 30109 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && 30110 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { 30111 30112 try { 30113 var ret = matches.call( elem, expr ); 30114 30115 // IE 9's matchesSelector returns false on disconnected nodes 30116 if ( ret || support.disconnectedMatch || 30117 // As well, disconnected nodes are said to be in a document 30118 // fragment in IE 9 30119 elem.document && elem.document.nodeType !== 11 ) { 30120 return ret; 30121 } 30122 } catch (e) {} 30123 } 30124 30125 return Sizzle( expr, document, null, [ elem ] ).length > 0; 30126}; 30127 30128Sizzle.contains = function( context, elem ) { 30129 // Set document vars if needed 30130 if ( ( context.ownerDocument || context ) !== document ) { 30131 setDocument( context ); 30132 } 30133 return contains( context, elem ); 30134}; 30135 30136Sizzle.attr = function( elem, name ) { 30137 // Set document vars if needed 30138 if ( ( elem.ownerDocument || elem ) !== document ) { 30139 setDocument( elem ); 30140 } 30141 30142 var fn = Expr.attrHandle[ name.toLowerCase() ], 30143 // Don't get fooled by Object.prototype properties (jQuery #13807) 30144 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? 30145 fn( elem, name, !documentIsHTML ) : 30146 undefined; 30147 30148 return val !== undefined ? 30149 val : 30150 support.attributes || !documentIsHTML ? 30151 elem.getAttribute( name ) : 30152 (val = elem.getAttributeNode(name)) && val.specified ? 30153 val.value : 30154 null; 30155}; 30156 30157Sizzle.error = function( msg ) { 30158 throw new Error( "Syntax error, unrecognized expression: " + msg ); 30159}; 30160 30161/** 30162 * Document sorting and removing duplicates 30163 * @param {ArrayLike} results 30164 */ 30165Sizzle.uniqueSort = function( results ) { 30166 var elem, 30167 duplicates = [], 30168 j = 0, 30169 i = 0; 30170 30171 // Unless we *know* we can detect duplicates, assume their presence 30172 hasDuplicate = !support.detectDuplicates; 30173 sortInput = !support.sortStable && results.slice( 0 ); 30174 results.sort( sortOrder ); 30175 30176 if ( hasDuplicate ) { 30177 while ( (elem = results[i++]) ) { 30178 if ( elem === results[ i ] ) { 30179 j = duplicates.push( i ); 30180 } 30181 } 30182 while ( j-- ) { 30183 results.splice( duplicates[ j ], 1 ); 30184 } 30185 } 30186 30187 // Clear input after sorting to release objects 30188 // See https://github.com/jquery/sizzle/pull/225 30189 sortInput = null; 30190 30191 return results; 30192}; 30193 30194/** 30195 * Utility function for retrieving the text value of an array of DOM nodes 30196 * @param {Array|Element} elem 30197 */ 30198getText = Sizzle.getText = function( elem ) { 30199 var node, 30200 ret = "", 30201 i = 0, 30202 nodeType = elem.nodeType; 30203 30204 if ( !nodeType ) { 30205 // If no nodeType, this is expected to be an array 30206 while ( (node = elem[i++]) ) { 30207 // Do not traverse comment nodes 30208 ret += getText( node ); 30209 } 30210 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { 30211 // Use textContent for elements 30212 // innerText usage removed for consistency of new lines (jQuery #11153) 30213 if ( typeof elem.textContent === "string" ) { 30214 return elem.textContent; 30215 } else { 30216 // Traverse its children 30217 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 30218 ret += getText( elem ); 30219 } 30220 } 30221 } else if ( nodeType === 3 || nodeType === 4 ) { 30222 return elem.nodeValue; 30223 } 30224 // Do not include comment or processing instruction nodes 30225 30226 return ret; 30227}; 30228 30229Expr = Sizzle.selectors = { 30230 30231 // Can be adjusted by the user 30232 cacheLength: 50, 30233 30234 createPseudo: markFunction, 30235 30236 match: matchExpr, 30237 30238 attrHandle: {}, 30239 30240 find: {}, 30241 30242 relative: { 30243 ">": { dir: "parentNode", first: true }, 30244 " ": { dir: "parentNode" }, 30245 "+": { dir: "previousSibling", first: true }, 30246 "~": { dir: "previousSibling" } 30247 }, 30248 30249 preFilter: { 30250 "ATTR": function( match ) { 30251 match[1] = match[1].replace( runescape, funescape ); 30252 30253 // Move the given value to match[3] whether quoted or unquoted 30254 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); 30255 30256 if ( match[2] === "~=" ) { 30257 match[3] = " " + match[3] + " "; 30258 } 30259 30260 return match.slice( 0, 4 ); 30261 }, 30262 30263 "CHILD": function( match ) { 30264 /* matches from matchExpr["CHILD"] 30265 1 type (only|nth|...) 30266 2 what (child|of-type)
30267 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 30268 4 xn-component of xn+y argument ([+-]?\d*n|) 30269 5 sign of xn-component 30270 6 x of xn-component 30271 7 sign of y-component 30272 8 y of y-component 30273 */ 30274 match[1] = match[1].toLowerCase(); 30275 30276 if ( match[1].slice( 0, 3 ) === "nth" ) { 30277 // nth-* requires argument 30278 if ( !match[3] ) { 30279 Sizzle.error( match[0] ); 30280 } 30281 30282 // numeric x and y parameters for Expr.filter.CHILD 30283 // remember that false/true cast respectively to 0/1 30284 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 30285 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 30286 30287 // other types prohibit arguments 30288 } else if ( match[3] ) { 30289 Sizzle.error( match[0] ); 30290 } 30291 30292 return match; 30293 }, 30294 30295 "PSEUDO": function( match ) { 30296 var excess, 30297 unquoted = !match[6] && match[2]; 30298 30299 if ( matchExpr["CHILD"].test( match[0] ) ) { 30300 return null; 30301 } 30302 30303 // Accept quoted arguments as-is 30304 if ( match[3] ) { 30305 match[2] = match[4] || match[5] || ""; 30306 30307 // Strip excess characters from unquoted arguments 30308 } else if ( unquoted && rpseudo.test( unquoted ) && 30309 // Get excess from tokenize (recursively) 30310 (excess = tokenize( unquoted, true )) && 30311 // advance to the next closing parenthesis 30312 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 30313 30314 // excess is a negative index 30315 match[0] = match[0].slice( 0, excess ); 30316 match[2] = unquoted.slice( 0, excess ); 30317 } 30318 30319 // Return only captures needed by the pseudo filter method (type and argument) 30320 return match.slice( 0, 3 ); 30321 } 30322 }, 30323 30324 filter: { 30325 30326 "TAG": function( nodeNameSelector ) { 30327 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); 30328 return nodeNameSelector === "*" ? 30329 function() { return true; } : 30330 function( elem ) { 30331 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 30332 }; 30333 }, 30334 30335 "CLASS": function( className ) { 30336 var pattern = classCache[ className + " " ]; 30337 30338 return pattern || 30339 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && 30340 classCache( className, function( elem ) { 30341 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); 30342 }); 30343 }, 30344 30345 "ATTR": function( name, operator, check ) { 30346 return function( elem ) { 30347 var result = Sizzle.attr( elem, name ); 30348 30349 if ( result == null ) { 30350 return operator === "!="; 30351 } 30352 if ( !operator ) { 30353 return true; 30354 } 30355 30356 result += ""; 30357 30358 return operator === "=" ? result === check : 30359 operator === "!=" ? result !== check : 30360 operator === "^=" ? check && result.indexOf( check ) === 0 : 30361 operator === "*=" ? check && result.indexOf( check ) > -1 : 30362 operator === "$=" ? check && result.slice( -check.length ) === check : 30363 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : 30364 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : 30365 false; 30366 }; 30367 }, 30368 30369 "CHILD": function( type, what, argument, first, last ) { 30370 var simple = type.slice( 0, 3 ) !== "nth", 30371 forward = type.slice( -4 ) !== "last", 30372 ofType = what === "of-type"; 30373 30374 return first === 1 && last === 0 ? 30375 30376 // Shortcut for :nth-*(n) 30377 function( elem ) { 30378 return !!elem.parentNode; 30379 } : 30380 30381 function( elem, context, xml ) { 30382 var cache, outerCache, node, diff, nodeIndex, start, 30383 dir = simple !== forward ? "nextSibling" : "previousSibling", 30384 parent = elem.parentNode, 30385 name = ofType && elem.nodeName.toLowerCase(), 30386 useCache = !xml && !ofType; 30387 30388 if ( parent ) { 30389 30390 // :(first|last|only)-(child|of-type) 30391 if ( simple ) { 30392 while ( dir ) { 30393 node = elem; 30394 while ( (node = node[ dir ]) ) { 30395 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { 30396 return false; 30397 } 30398 } 30399 // Reverse direction for :only-* (if we haven't yet done so) 30400 start = dir = type === "only" && !start && "nextSibling"; 30401 } 30402 return true; 30403 } 30404 30405 start = [ forward ? parent.firstChild : parent.lastChild ]; 30406 30407 // non-xml :nth-child(...) stores cache data on `parent` 30408 if ( forward && useCache ) { 30409 // Seek `elem` from a previously-cached index 30410 outerCache = parent[ expando ] || (parent[ expando ] = {}); 30411 cache = outerCache[ type ] || [];
30412 nodeIndex = cache[0] === dirruns && cache[1]; 30413 diff = cache[0] === dirruns && cache[2]; 30414 node = nodeIndex && parent.childNodes[ nodeIndex ]; 30415 30416 while ( (node = ++nodeIndex && node && node[ dir ] || 30417 30418 // Fallback to seeking `elem` from the start 30419 (diff = nodeIndex = 0) || start.pop()) ) { 30420 30421 // When found, cache indexes on `parent` and break 30422 if ( node.nodeType === 1 && ++diff && node === elem ) { 30423 outerCache[ type ] = [ dirruns, nodeIndex, diff ]; 30424 break; 30425 } 30426 } 30427 30428 // Use previously-cached element index if available 30429 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { 30430 diff = cache[1]; 30431 30432 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) 30433 } else { 30434 // Use the same loop as above to seek `elem` from the start 30435 while ( (node = ++nodeIndex && node && node[ dir ] || 30436 (diff = nodeIndex = 0) || start.pop()) ) { 30437 30438 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { 30439 // Cache the index of each encountered element 30440 if ( useCache ) { 30441 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; 30442 } 30443 30444 if ( node === elem ) { 30445 break; 30446 } 30447 } 30448 } 30449 } 30450 30451 // Incorporate the offset, then check against cycle size 30452 diff -= last; 30453 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 30454 } 30455 }; 30456 }, 30457 30458 "PSEUDO": function( pseudo, argument ) { 30459 // pseudo-class names are case-insensitive 30460 // http://www.w3.org/TR/selectors/#pseudo-classes 30461 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 30462 // Remember that setFilters inherits from pseudos 30463 var args, 30464 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 30465 Sizzle.error( "unsupported pseudo: " + pseudo ); 30466 30467 // The user may use createPseudo to indicate that 30468 // arguments are needed to create the filter function 30469 // just as Sizzle does 30470 if ( fn[ expando ] ) { 30471 return fn( argument ); 30472 } 30473 30474 // But maintain support for old signatures 30475 if ( fn.length > 1 ) { 30476 args = [ pseudo, pseudo, "", argument ]; 30477 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 30478 markFunction(function( seed, matches ) { 30479 var idx, 30480 matched = fn( seed, argument ), 30481 i = matched.length; 30482 while ( i-- ) { 30483 idx = indexOf( seed, matched[i] ); 30484 seed[ idx ] = !( matches[ idx ] = matched[i] ); 30485 } 30486 }) : 30487 function( elem ) { 30488 return fn( elem, 0, args ); 30489 }; 30490 } 30491 30492 return fn; 30493 } 30494 }, 30495 30496 pseudos: { 30497 // Potentially complex pseudos 30498 "not": markFunction(function( selector ) { 30499 // Trim the selector passed to compile 30500 // to avoid treating leading and trailing 30501 // spaces as combinators 30502 var input = [], 30503 results = [], 30504 matcher = compile( selector.replace( rtrim, "$1" ) ); 30505 30506 return matcher[ expando ] ? 30507 markFunction(function( seed, matches, context, xml ) { 30508 var elem, 30509 unmatched = matcher( seed, null, xml, [] ), 30510 i = seed.length; 30511 30512 // Match elements unmatched by `matcher` 30513 while ( i-- ) { 30514 if ( (elem = unmatched[i]) ) { 30515 seed[i] = !(matches[i] = elem); 30516 } 30517 } 30518 }) : 30519 function( elem, context, xml ) { 30520 input[0] = elem; 30521 matcher( input, null, xml, results ); 30522 // Don't keep the element (issue #299) 30523 input[0] = null; 30524 return !results.pop(); 30525 }; 30526 }), 30527 30528 "has": markFunction(function( selector ) { 30529 return function( elem ) { 30530 return Sizzle( selector, elem ).length > 0; 30531 }; 30532 }), 30533 30534 "contains": markFunction(function( text ) { 30535 text = text.replace( runescape, funescape ); 30536 return function( elem ) { 30537 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; 30538 }; 30539 }), 30540 30541 // "Whether an element is represented by a :lang() selector 30542 // is based solely on the element's language value 30543 // being equal to the identifier C, 30544 // or beginning with the identifier C immediately followed by "-". 30545 // The matching of C against the element's language value is performed case-insensitively. 30546 // The identifier C does not have to be a valid language name." 30547 // http://www.w3.org/TR/selectors/#lang-pseudo 30548 "lang": markFunction( function( lang ) { 30549 // lang value must be a valid identifier 30550 if ( !ridentifier.test(lang || "") ) { 30551 Sizzle.error( "unsupported lang: " + lang ); 30552 } 30553 lang = lang.replace( runescape, funescape ).toLowerCase(); 30554 return function( elem ) { 30555 var elemLang; 30556 do { 30557 if ( (elemLang = documentIsHTML ? 30558 elem.lang : 30559 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { 30560 30561 elemLang = elemLang.toLowerCase(); 30562 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 30563 } 30564 } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); 30565 return false; 30566 }; 30567 }), 30568 30569 // Miscellaneous 30570 "target": function( elem ) { 30571 var hash = window.location && window.location.hash; 30572 return hash && hash.slice( 1 ) === elem.id; 30573 }, 30574 30575 "root": function( elem ) { 30576 return elem === docElem; 30577 }, 30578
30579 "focus": function( elem ) { 30580 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 30581 }, 30582 30583 // Boolean properties 30584 "enabled": function( elem ) { 30585 return elem.disabled === false; 30586 }, 30587 30588 "disabled": function( elem ) { 30589 return elem.disabled === true; 30590 }, 30591 30592 "checked": function( elem ) { 30593 // In CSS3, :checked should return both checked and selected elements 30594 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 30595 var nodeName = elem.nodeName.toLowerCase(); 30596 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); 30597 }, 30598 30599 "selected": function( elem ) { 30600 // Accessing this property makes selected-by-default 30601 // options in Safari work properly 30602 if ( elem.parentNode ) { 30603 elem.parentNode.selectedIndex; 30604 } 30605 30606 return elem.selected === true; 30607 }, 30608 30609 // Contents 30610 "empty": function( elem ) { 30611 // http://www.w3.org/TR/selectors/#empty-pseudo 30612 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), 30613 // but not by others (comment: 8; processing instruction: 7; etc.) 30614 // nodeType < 6 works because attributes (2) do not appear as children 30615 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 30616 if ( elem.nodeType < 6 ) { 30617 return false; 30618 } 30619 } 30620 return true; 30621 }, 30622 30623 "parent": function( elem ) { 30624 return !Expr.pseudos["empty"]( elem ); 30625 }, 30626 30627 // Element/input types 30628 "header": function( elem ) { 30629 return rheader.test( elem.nodeName ); 30630 }, 30631 30632 "input": function( elem ) { 30633 return rinputs.test( elem.nodeName ); 30634 }, 30635 30636 "button": function( elem ) { 30637 var name = elem.nodeName.toLowerCase(); 30638 return name === "input" && elem.type === "button" || name === "button"; 30639 }, 30640 30641 "text": function( elem ) { 30642 var attr; 30643 return elem.nodeName.toLowerCase() === "input" && 30644 elem.type === "text" && 30645 30646 // Support: IE<8 30647 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" 30648 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); 30649 }, 30650 30651 // Position-in-collection 30652 "first": createPositionalPseudo(function() { 30653 return [ 0 ]; 30654 }), 30655 30656 "last": createPositionalPseudo(function( matchIndexes, length ) { 30657 return [ length - 1 ]; 30658 }), 30659 30660 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { 30661 return [ argument < 0 ? argument + length : argument ]; 30662 }), 30663 30664 "even": createPositionalPseudo(function( matchIndexes, length ) { 30665 var i = 0; 30666 for ( ; i < length; i += 2 ) { 30667 matchIndexes.push( i ); 30668 } 30669 return matchIndexes; 30670 }), 30671 30672 "odd": createPositionalPseudo(function( matchIndexes, length ) { 30673 var i = 1; 30674 for ( ; i < length; i += 2 ) { 30675 matchIndexes.push( i ); 30676 } 30677 return matchIndexes; 30678 }), 30679 30680 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { 30681 var i = argument < 0 ? argument + length : argument; 30682 for ( ; --i >= 0; ) { 30683 matchIndexes.push( i ); 30684 } 30685 return matchIndexes; 30686 }), 30687 30688 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { 30689 var i = argument < 0 ? argument + length : argument; 30690 for ( ; ++i < length; ) { 30691 matchIndexes.push( i ); 30692 } 30693 return matchIndexes; 30694 }) 30695 } 30696}; 30697 30698Expr.pseudos["nth"] = Expr.pseudos["eq"]; 30699 30700// Add button/input type pseudos 30701for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 30702 Expr.pseudos[ i ] = createInputPseudo( i ); 30703} 30704for ( i in { submit: true, reset: true } ) { 30705 Expr.pseudos[ i ] = createButtonPseudo( i ); 30706} 30707 30708// Easy API for creating new setFilters 30709function setFilters() {} 30710setFilters.prototype = Expr.filters = Expr.pseudos; 30711Expr.setFilters = new setFilters(); 30712 30713tokenize = Sizzle.tokenize = function( selector, parseOnly ) { 30714 var matched, match, tokens, type, 30715 soFar, groups, preFilters, 30716 cached = tokenCache[ selector + " " ]; 30717 30718 if ( cached ) { 30719 return parseOnly ? 0 : cached.slice( 0 ); 30720 } 30721 30722 soFar = selector; 30723 groups = []; 30724 preFilters = Expr.preFilter; 30725 30726 while ( soFar ) { 30727 30728 // Comma and first run 30729 if ( !matched || (match = rcomma.exec( soFar )) ) { 30730 if ( match ) { 30731 // Don't consume trailing commas as valid 30732 soFar = soFar.slice( match[0].length ) || soFar; 30733 } 30734 groups.push( (tokens = []) ); 30735 } 30736 30737 matched = false; 30738 30739 // Combinators 30740 if ( (match = rcombinators.exec( soFar )) ) { 30741 matched = match.shift(); 30742 tokens.push({ 30743 value: matched, 30744 // Cast descendant combinators to space 30745 type: match[0].replace( rtrim, " " ) 30746 }); 30747 soFar = soFar.slice( matched.length ); 30748 } 30749 30750 // Filters 30751 for ( type in Expr.filter ) { 30752 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || 30753 (match = preFilters[ type ]( match ))) ) { 30754 matched = match.shift(); 30755 tokens.push({ 30756 value: matched, 30757 type: type, 30758 matches: match 30759 }); 30760 soFar = soFar.slice( matched.length ); 30761 } 30762 } 30763 30764 if ( !matched ) { 30765 break; 30766 } 30767 } 30768 30769 // Return the length of the invalid excess 30770 // if we're just parsing 30771 // Otherwise, throw an error or return tokens 30772 return parseOnly ? 30773 soFar.length : 30774 soFar ? 30775 Sizzle.error( selector ) : 30776 // Cache the tokens 30777 tokenCache( selector, groups ).slice( 0 ); 30778};
vendor: 11,230 bytes, lines 30779-31165
30779 30780function toSelector( tokens ) { 30781 var i = 0, 30782 len = tokens.length, 30783 selector = ""; 30784 for ( ; i < len; i++ ) { 30785 selector += tokens[i].value; 30786 } 30787 return selector; 30788} 30789 30790function addCombinator( matcher, combinator, base ) { 30791 var dir = combinator.dir, 30792 checkNonElements = base && dir === "parentNode", 30793 doneName = done++; 30794 30795 return combinator.first ? 30796 // Check against closest ancestor/preceding element 30797 function( elem, context, xml ) { 30798 while ( (elem = elem[ dir ]) ) { 30799 if ( elem.nodeType === 1 || checkNonElements ) { 30800 return matcher( elem, context, xml ); 30801 } 30802 } 30803 } : 30804 30805 // Check against all ancestor/preceding elements 30806 function( elem, context, xml ) { 30807 var oldCache, outerCache, 30808 newCache = [ dirruns, doneName ]; 30809 30810 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching 30811 if ( xml ) { 30812 while ( (elem = elem[ dir ]) ) { 30813 if ( elem.nodeType === 1 || checkNonElements ) { 30814 if ( matcher( elem, context, xml ) ) { 30815 return true; 30816 } 30817 } 30818 } 30819 } else { 30820 while ( (elem = elem[ dir ]) ) { 30821 if ( elem.nodeType === 1 || checkNonElements ) { 30822 outerCache = elem[ expando ] || (elem[ expando ] = {}); 30823 if ( (oldCache = outerCache[ dir ]) && 30824 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { 30825 30826 // Assign to newCache so results back-propagate to previous elements 30827 return (newCache[ 2 ] = oldCache[ 2 ]); 30828 } else { 30829 // Reuse newcache so results back-propagate to previous elements 30830 outerCache[ dir ] = newCache; 30831 30832 // A match means we're done; a fail means we have to keep checking 30833 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { 30834 return true; 30835 } 30836 } 30837 } 30838 } 30839 } 30840 }; 30841} 30842 30843function elementMatcher( matchers ) { 30844 return matchers.length > 1 ? 30845 function( elem, context, xml ) { 30846 var i = matchers.length; 30847 while ( i-- ) { 30848 if ( !matchers[i]( elem, context, xml ) ) { 30849 return false; 30850 } 30851 } 30852 return true; 30853 } : 30854 matchers[0]; 30855} 30856 30857function multipleContexts( selector, contexts, results ) { 30858 var i = 0, 30859 len = contexts.length; 30860 for ( ; i < len; i++ ) { 30861 Sizzle( selector, contexts[i], results ); 30862 } 30863 return results; 30864} 30865 30866function condense( unmatched, map, filter, context, xml ) { 30867 var elem, 30868 newUnmatched = [], 30869 i = 0, 30870 len = unmatched.length, 30871 mapped = map != null; 30872 30873 for ( ; i < len; i++ ) { 30874 if ( (elem = unmatched[i]) ) { 30875 if ( !filter || filter( elem, context, xml ) ) { 30876 newUnmatched.push( elem ); 30877 if ( mapped ) { 30878 map.push( i ); 30879 } 30880 } 30881 } 30882 } 30883 30884 return newUnmatched; 30885} 30886 30887function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 30888 if ( postFilter && !postFilter[ expando ] ) { 30889 postFilter = setMatcher( postFilter ); 30890 } 30891 if ( postFinder && !postFinder[ expando ] ) { 30892 postFinder = setMatcher( postFinder, postSelector ); 30893 } 30894 return markFunction(function( seed, results, context, xml ) { 30895 var temp, i, elem, 30896 preMap = [], 30897 postMap = [], 30898 preexisting = results.length, 30899 30900 // Get initial elements from seed or context 30901 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), 30902 30903 // Prefilter to get matcher input, preserving a map for seed-results synchronization 30904 matcherIn = preFilter && ( seed || !selector ) ? 30905 condense( elems, preMap, preFilter, context, xml ) : 30906 elems, 30907 30908 matcherOut = matcher ? 30909 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, 30910 postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 30911 30912 // ...intermediate processing is necessary 30913 [] : 30914 30915 // ...otherwise use results directly 30916 results : 30917 matcherIn; 30918 30919 // Find primary matches 30920 if ( matcher ) { 30921 matcher( matcherIn, matcherOut, context, xml ); 30922 } 30923 30924 // Apply postFilter 30925 if ( postFilter ) { 30926 temp = condense( matcherOut, postMap ); 30927 postFilter( temp, [], context, xml ); 30928 30929 // Un-match failing elements by moving them back to matcherIn 30930 i = temp.length; 30931 while ( i-- ) { 30932 if ( (elem = temp[i]) ) { 30933 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); 30934 } 30935 } 30936 } 30937 30938 if ( seed ) { 30939 if ( postFinder || preFilter ) { 30940 if ( postFinder ) { 30941 // Get the final matcherOut by condensing this intermediate into postFinder contexts 30942 temp = []; 30943 i = matcherOut.length; 30944 while ( i-- ) { 30945 if ( (elem = matcherOut[i]) ) { 30946 // Restore matcherIn since elem is not yet a final match 30947 temp.push( (matcherIn[i] = elem) ); 30948 } 30949 } 30950 postFinder( null, (matcherOut = []), temp, xml ); 30951 } 30952 30953 // Move matched elements from seed to results to keep them synchronized 30954 i = matcherOut.length; 30955 while ( i-- ) { 30956 if ( (elem = matcherOut[i]) && 30957 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { 30958 30959 seed[temp] = !(results[temp] = elem); 30960 } 30961 } 30962 } 30963 30964 // Add elements to results, through postFinder if defined 30965 } else { 30966 matcherOut = condense( 30967 matcherOut === results ? 30968 matcherOut.splice( preexisting, matcherOut.length ) : 30969 matcherOut 30970 ); 30971 if ( postFinder ) { 30972 postFinder( null, results, matcherOut, xml ); 30973 } else { 30974 push.apply( results, matcherOut ); 30975 } 30976 } 30977 }); 30978} 30979 30980function matcherFromTokens( tokens ) { 30981 var checkContext, matcher, j, 30982 len = tokens.length, 30983 leadingRelative = Expr.relative[ tokens[0].type ], 30984 implicitRelative = leadingRelative || Expr.relative[" "], 30985 i = leadingRelative ? 1 : 0, 30986 30987 // The foundational matcher ensures that elements are reachable from top-level context(s) 30988 matchContext = addCombinator( function( elem ) { 30989 return elem === checkContext; 30990 }, implicitRelative, true ), 30991 matchAnyContext = addCombinator( function( elem ) { 30992 return indexOf( checkContext, elem ) > -1; 30993 }, implicitRelative, true ), 30994 matchers = [ function( elem, context, xml ) { 30995 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( 30996 (checkContext = context).nodeType ? 30997 matchContext( elem, context, xml ) : 30998 matchAnyContext( elem, context, xml ) ); 30999 // Avoid hanging onto element (issue #299) 31000 checkContext = null; 31001 return ret; 31002 } ]; 31003 31004 for ( ; i < len; i++ ) { 31005 if ( (matcher = Expr.relative[ tokens[i].type ]) ) { 31006 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; 31007 } else { 31008 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); 31009 31010 // Return special upon seeing a positional matcher 31011 if ( matcher[ expando ] ) { 31012 // Find the next relative operator (if any) for proper handling 31013 j = ++i; 31014 for ( ; j < len; j++ ) { 31015 if ( Expr.relative[ tokens[j].type ] ) { 31016 break; 31017 } 31018 } 31019 return setMatcher( 31020 i > 1 && elementMatcher( matchers ), 31021 i > 1 && toSelector( 31022 // If the preceding token was a descendant combinator, insert an implicit any-element `*` 31023 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) 31024 ).replace( rtrim, "$1" ), 31025 matcher, 31026 i < j && matcherFromTokens( tokens.slice( i, j ) ), 31027 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), 31028 j < len && toSelector( tokens ) 31029 ); 31030 } 31031 matchers.push( matcher ); 31032 } 31033 } 31034 31035 return elementMatcher( matchers ); 31036} 31037 31038function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 31039 var bySet = setMatchers.length > 0, 31040 byElement = elementMatchers.length > 0, 31041 superMatcher = function( seed, context, xml, results, outermost ) { 31042 var elem, j, matcher, 31043 matchedCount = 0, 31044 i = "0", 31045 unmatched = seed && [], 31046 setMatched = [], 31047 contextBackup = outermostContext, 31048 // We must always have either seed elements or outermost context 31049 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), 31050 // Use integer dirruns iff this is the outermost matcher 31051 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), 31052 len = elems.length; 31053 31054 if ( outermost ) { 31055 outermostContext = context !== document && context; 31056 } 31057 31058 // Add elements passing elementMatchers directly to results 31059 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below 31060 // Support: IE<9, Safari 31061 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id 31062 for ( ; i !== len && (elem = elems[i]) != null; i++ ) { 31063 if ( byElement && elem ) { 31064 j = 0; 31065 while ( (matcher = elementMatchers[j++]) ) { 31066 if ( matcher( elem, context, xml ) ) { 31067 results.push( elem ); 31068 break; 31069 } 31070 } 31071 if ( outermost ) { 31072 dirruns = dirrunsUnique; 31073 } 31074 } 31075 31076 // Track unmatched elements for set filters 31077 if ( bySet ) { 31078 // They will have gone through all possible matchers 31079 if ( (elem = !matcher && elem) ) { 31080 matchedCount--; 31081 } 31082 31083 // Lengthen the array for every element, matched or not 31084 if ( seed ) { 31085 unmatched.push( elem ); 31086 } 31087 } 31088 } 31089 31090 // Apply set filters to unmatched elements 31091 matchedCount += i; 31092 if ( bySet && i !== matchedCount ) { 31093 j = 0; 31094 while ( (matcher = setMatchers[j++]) ) { 31095 matcher( unmatched, setMatched, context, xml ); 31096 } 31097 31098 if ( seed ) { 31099 // Reintegrate element matches to eliminate the need for sorting 31100 if ( matchedCount > 0 ) { 31101 while ( i-- ) { 31102 if ( !(unmatched[i] || setMatched[i]) ) { 31103 setMatched[i] = pop.call( results ); 31104 } 31105 } 31106 } 31107 31108 // Discard index placeholder values to get only actual matches 31109 setMatched = condense( setMatched ); 31110 } 31111 31112 // Add matches to results 31113 push.apply( results, setMatched ); 31114 31115 // Seedless set matches succeeding multiple successful matchers stipulate sorting 31116 if ( outermost && !seed && setMatched.length > 0 && 31117 ( matchedCount + setMatchers.length ) > 1 ) { 31118 31119 Sizzle.uniqueSort( results ); 31120 } 31121 } 31122 31123 // Override manipulation of globals by nested matchers 31124 if ( outermost ) { 31125 dirruns = dirrunsUnique; 31126 outermostContext = contextBackup; 31127 } 31128 31129 return unmatched; 31130 }; 31131 31132 return bySet ? 31133 markFunction( superMatcher ) : 31134 superMatcher; 31135} 31136 31137compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { 31138 var i, 31139 setMatchers = [], 31140 elementMatchers = [], 31141 cached = compilerCache[ selector + " " ]; 31142 31143 if ( !cached ) { 31144 // Generate a function of recursive functions that can be used to check each element 31145 if ( !match ) { 31146 match = tokenize( selector ); 31147 } 31148 i = match.length; 31149 while ( i-- ) { 31150 cached = matcherFromTokens( match[i] ); 31151 if ( cached[ expando ] ) { 31152 setMatchers.push( cached ); 31153 } else { 31154 elementMatchers.push( cached ); 31155 } 31156 } 31157 31158 // Cache the compiled function 31159 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 31160 31161 // Save selector and tokenization 31162 cached.selector = selector; 31163 } 31164 return cached; 31165};
31166 31167/** 31168 * A low-level selection function that works with Sizzle's compiled 31169 * selector functions 31170 * @param {String|Function} selector A selector or a pre-compiled 31171 * selector function built with Sizzle.compile 31172 * @param {Element} context 31173 * @param {Array} [results] 31174 * @param {Array} [seed] A set of elements to match against 31175 */ 31176select = Sizzle.select = function( selector, context, results, seed ) { 31177 var i, tokens, token, type, find, 31178 compiled = typeof selector === "function" && selector, 31179 match = !seed && tokenize( (selector = compiled.selector || selector) ); 31180 31181 results = results || []; 31182 31183 // Try to minimize operations if there is no seed and only one group 31184 if ( match.length === 1 ) { 31185 31186 // Take a shortcut and set the context if the root selector is an ID 31187 tokens = match[0] = match[0].slice( 0 ); 31188 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && 31189 support.getById && context.nodeType === 9 && documentIsHTML && 31190 Expr.relative[ tokens[1].type ] ) { 31191 31192 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; 31193 if ( !context ) { 31194 return results; 31195 31196 // Precompiled matchers will still verify ancestry, so step up a level 31197 } else if ( compiled ) { 31198 context = context.parentNode; 31199 } 31200 31201 selector = selector.slice( tokens.shift().value.length ); 31202 } 31203 31204 // Fetch a seed set for right-to-left matching 31205 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; 31206 while ( i-- ) { 31207 token = tokens[i]; 31208 31209 // Abort if we hit a combinator 31210 if ( Expr.relative[ (type = token.type) ] ) { 31211 break; 31212 } 31213 if ( (find = Expr.find[ type ]) ) { 31214 // Search, expanding context for leading sibling combinators 31215 if ( (seed = find( 31216 token.matches[0].replace( runescape, funescape ), 31217 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context 31218 )) ) { 31219 31220 // If seed is empty or no tokens remain, we can return early 31221 tokens.splice( i, 1 ); 31222 selector = seed.length && toSelector( tokens ); 31223 if ( !selector ) { 31224 push.apply( results, seed ); 31225 return results; 31226 } 31227 31228 break; 31229 } 31230 } 31231 } 31232 } 31233 31234 // Compile and execute a filtering function if one is not provided 31235 // Provide `match` to avoid retokenization if we modified the selector above 31236 ( compiled || compile( selector, match ) )( 31237 seed, 31238 context, 31239 !documentIsHTML, 31240 results, 31241 rsibling.test( selector ) && testContext( context.parentNode ) || context 31242 ); 31243 return results; 31244}; 31245 31246// One-time assignments 31247 31248// Sort stability 31249support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; 31250 31251// Support: Chrome 14-35+ 31252// Always assume duplicates if they aren't passed to the comparison function 31253support.detectDuplicates = !!hasDuplicate; 31254 31255// Initialize against the default document 31256setDocument(); 31257 31258// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) 31259// Detached nodes confoundingly follow *each other* 31260support.sortDetached = assert(function( div1 ) { 31261 // Should return 1, but returns 4 (following) 31262 return div1.compareDocumentPosition( document.createElement("div") ) & 1; 31263}); 31264 31265// Support: IE<8 31266// Prevent attribute/property "interpolation" 31267// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx 31268if ( !assert(function( div ) { 31269 div.innerHTML = "<a href='#'></a>"; 31270 return div.firstChild.getAttribute("href") === "#" ; 31271}) ) { 31272 addHandle( "type|href|height|width", function( elem, name, isXML ) { 31273 if ( !isXML ) { 31274 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); 31275 } 31276 }); 31277} 31278 31279// Support: IE<9 31280// Use defaultValue in place of getAttribute("value") 31281if ( !support.attributes || !assert(function( div ) { 31282 div.innerHTML = "<input/>"; 31283 div.firstChild.setAttribute( "value", "" ); 31284 return div.firstChild.getAttribute( "value" ) === ""; 31285}) ) { 31286 addHandle( "value", function( elem, name, isXML ) { 31287 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { 31288 return elem.defaultValue; 31289 } 31290 }); 31291} 31292 31293// Support: IE<9
31294// Use getAttributeNode to fetch booleans when getAttribute lies 31295if ( !assert(function( div ) { 31296 return div.getAttribute("disabled") == null; 31297}) ) { 31298 addHandle( booleans, function( elem, name, isXML ) { 31299 var val; 31300 if ( !isXML ) { 31301 return elem[ name ] === true ? name.toLowerCase() : 31302 (val = elem.getAttributeNode( name )) && val.specified ? 31303 val.value : 31304 null; 31305 } 31306 }); 31307} 31308 31309return Sizzle; 31310 31311})( window ); 31312 31313 31314 31315jQuery.find = Sizzle; 31316jQuery.expr = Sizzle.selectors; 31317jQuery.expr[":"] = jQuery.expr.pseudos; 31318jQuery.unique = Sizzle.uniqueSort; 31319jQuery.text = Sizzle.getText; 31320jQuery.isXMLDoc = Sizzle.isXML; 31321jQuery.contains = Sizzle.contains; 31322 31323 31324 31325var rneedsContext = jQuery.expr.match.needsContext; 31326 31327var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); 31328 31329 31330 31331var risSimple = /^.[^:#\[\.,]*$/; 31332 31333// Implement the identical functionality for filter and not 31334function winnow( elements, qualifier, not ) { 31335 if ( jQuery.isFunction( qualifier ) ) { 31336 return jQuery.grep( elements, function( elem, i ) { 31337 /* jshint -W018 */ 31338 return !!qualifier.call( elem, i, elem ) !== not; 31339 }); 31340 31341 } 31342 31343 if ( qualifier.nodeType ) { 31344 return jQuery.grep( elements, function( elem ) { 31345 return ( elem === qualifier ) !== not; 31346 }); 31347 31348 } 31349 31350 if ( typeof qualifier === "string" ) { 31351 if ( risSimple.test( qualifier ) ) { 31352 return jQuery.filter( qualifier, elements, not ); 31353 } 31354 31355 qualifier = jQuery.filter( qualifier, elements ); 31356 } 31357 31358 return jQuery.grep( elements, function( elem ) { 31359 return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; 31360 }); 31361} 31362 31363jQuery.filter = function( expr, elems, not ) { 31364 var elem = elems[ 0 ]; 31365 31366 if ( not ) { 31367 expr = ":not(" + expr + ")"; 31368 } 31369 31370 return elems.length === 1 && elem.nodeType === 1 ? 31371 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : 31372 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { 31373 return elem.nodeType === 1; 31374 })); 31375}; 31376 31377jQuery.fn.extend({ 31378 find: function( selector ) { 31379 var i, 31380 len = this.length, 31381 ret = [], 31382 self = this; 31383 31384 if ( typeof selector !== "string" ) { 31385 return this.pushStack( jQuery( selector ).filter(function() { 31386 for ( i = 0; i < len; i++ ) { 31387 if ( jQuery.contains( self[ i ], this ) ) { 31388 return true; 31389 } 31390 } 31391 }) ); 31392 } 31393 31394 for ( i = 0; i < len; i++ ) { 31395 jQuery.find( selector, self[ i ], ret ); 31396 } 31397 31398 // Needed because $( selector, context ) becomes $( context ).find( selector ) 31399 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); 31400 ret.selector = this.selector ? this.selector + " " + selector : selector; 31401 return ret; 31402 }, 31403 filter: function( selector ) { 31404 return this.pushStack( winnow(this, selector || [], false) ); 31405 }, 31406 not: function( selector ) { 31407 return this.pushStack( winnow(this, selector || [], true) ); 31408 }, 31409 is: function( selector ) { 31410 return !!winnow( 31411 this, 31412 31413 // If this is a positional/relative selector, check membership in the returned set 31414 // so $("p:first").is("p:last") won't return true for a doc with two "p". 31415 typeof selector === "string" && rneedsContext.test( selector ) ? 31416 jQuery( selector ) : 31417 selector || [], 31418 false 31419 ).length; 31420 } 31421}); 31422 31423 31424// Initialize a jQuery object 31425 31426 31427// A central reference to the root jQuery(document) 31428var rootjQuery, 31429 31430 // A simple way to check for HTML strings 31431 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 31432 // Strict HTML recognition (#11290: must start with <) 31433 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, 31434 31435 init = jQuery.fn.init = function( selector, context ) { 31436 var match, elem; 31437 31438 // HANDLE: $(""), $(null), $(undefined), $(false) 31439 if ( !selector ) { 31440 return this; 31441 } 31442 31443 // Handle HTML strings 31444 if ( typeof selector === "string" ) { 31445 if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { 31446 // Assume that strings that start and end with <> are HTML and skip the regex check 31447 match = [ null, selector, null ]; 31448 31449 } else { 31450 match = rquickExpr.exec( selector ); 31451 } 31452 31453 // Match html or make sure no context is specified for #id 31454 if ( match && (match[1] || !context) ) { 31455 31456 // HANDLE: $(html) -> $(array) 31457 if ( match[1] ) { 31458 context = context instanceof jQuery ? context[0] : context; 31459 31460 // Option to run scripts is true for back-compat 31461 // Intentionally let the error be thrown if parseHTML is not present 31462 jQuery.merge( this, jQuery.parseHTML( 31463 match[1], 31464 context && context.nodeType ? context.ownerDocument || context : document, 31465 true 31466 ) ); 31467 31468 // HANDLE: $(html, props) 31469 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { 31470 for ( match in context ) { 31471 // Properties of context are called as methods if possible 31472 if ( jQuery.isFunction( this[ match ] ) ) { 31473 this[ match ]( context[ match ] ); 31474 31475 // ...and otherwise set as attributes 31476 } else { 31477 this.attr( match, context[ match ] ); 31478 } 31479 } 31480 } 31481 31482 return this; 31483 31484 // HANDLE: $(#id) 31485 } else { 31486 elem = document.getElementById( match[2] ); 31487
31488 // Support: Blackberry 4.6 31489 // gEBID returns nodes no longer in the document (#6963) 31490 if ( elem && elem.parentNode ) { 31491 // Inject the element directly into the jQuery object 31492 this.length = 1; 31493 this[0] = elem; 31494 } 31495 31496 this.context = document; 31497 this.selector = selector; 31498 return this; 31499 } 31500 31501 // HANDLE: $(expr, $(...)) 31502 } else if ( !context || context.jquery ) { 31503 return ( context || rootjQuery ).find( selector ); 31504 31505 // HANDLE: $(expr, context) 31506 // (which is just equivalent to: $(context).find(expr) 31507 } else { 31508 return this.constructor( context ).find( selector ); 31509 } 31510 31511 // HANDLE: $(DOMElement) 31512 } else if ( selector.nodeType ) { 31513 this.context = this[0] = selector; 31514 this.length = 1; 31515 return this; 31516 31517 // HANDLE: $(function) 31518 // Shortcut for document ready 31519 } else if ( jQuery.isFunction( selector ) ) { 31520 return typeof rootjQuery.ready !== "undefined" ? 31521 rootjQuery.ready( selector ) : 31522 // Execute immediately if ready is not present 31523 selector( jQuery ); 31524 } 31525 31526 if ( selector.selector !== undefined ) { 31527 this.selector = selector.selector; 31528 this.context = selector.context; 31529 } 31530 31531 return jQuery.makeArray( selector, this ); 31532 }; 31533 31534// Give the init function the jQuery prototype for later instantiation 31535init.prototype = jQuery.fn; 31536 31537// Initialize central reference 31538rootjQuery = jQuery( document ); 31539 31540 31541var rparentsprev = /^(?:parents|prev(?:Until|All))/, 31542 // Methods guaranteed to produce a unique set when starting from a unique set 31543 guaranteedUnique = { 31544 children: true, 31545 contents: true, 31546 next: true, 31547 prev: true 31548 }; 31549 31550jQuery.extend({ 31551 dir: function( elem, dir, until ) { 31552 var matched = [], 31553 truncate = until !== undefined; 31554 31555 while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { 31556 if ( elem.nodeType === 1 ) { 31557 if ( truncate && jQuery( elem ).is( until ) ) { 31558 break; 31559 } 31560 matched.push( elem ); 31561 } 31562 } 31563 return matched; 31564 }, 31565 31566 sibling: function( n, elem ) { 31567 var matched = []; 31568 31569 for ( ; n; n = n.nextSibling ) { 31570 if ( n.nodeType === 1 && n !== elem ) { 31571 matched.push( n ); 31572 } 31573 } 31574 31575 return matched; 31576 } 31577}); 31578 31579jQuery.fn.extend({ 31580 has: function( target ) { 31581 var targets = jQuery( target, this ), 31582 l = targets.length; 31583 31584 return this.filter(function() { 31585 var i = 0; 31586 for ( ; i < l; i++ ) { 31587 if ( jQuery.contains( this, targets[i] ) ) { 31588 return true; 31589 } 31590 } 31591 }); 31592 }, 31593 31594 closest: function( selectors, context ) { 31595 var cur, 31596 i = 0, 31597 l = this.length, 31598 matched = [], 31599 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? 31600 jQuery( selectors, context || this.context ) : 31601 0; 31602 31603 for ( ; i < l; i++ ) { 31604 for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { 31605 // Always skip document fragments 31606 if ( cur.nodeType < 11 && (pos ? 31607 pos.index(cur) > -1 : 31608 31609 // Don't pass non-elements to Sizzle 31610 cur.nodeType === 1 && 31611 jQuery.find.matchesSelector(cur, selectors)) ) { 31612 31613 matched.push( cur ); 31614 break; 31615 } 31616 } 31617 } 31618 31619 return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); 31620 }, 31621 31622 // Determine the position of an element within the set 31623 index: function( elem ) { 31624 31625 // No argument, return index in parent 31626 if ( !elem ) { 31627 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; 31628 } 31629 31630 // Index in selector 31631 if ( typeof elem === "string" ) { 31632 return indexOf.call( jQuery( elem ), this[ 0 ] ); 31633 } 31634 31635 // Locate the position of the desired element 31636 return indexOf.call( this, 31637 31638 // If it receives a jQuery object, the first element is used 31639 elem.jquery ? elem[ 0 ] : elem 31640 ); 31641 }, 31642 31643 add: function( selector, context ) { 31644 return this.pushStack( 31645 jQuery.unique( 31646 jQuery.merge( this.get(), jQuery( selector, context ) ) 31647 ) 31648 ); 31649 }, 31650 31651 addBack: function( selector ) { 31652 return this.add( selector == null ? 31653 this.prevObject : this.prevObject.filter(selector) 31654 ); 31655 } 31656}); 31657 31658function sibling( cur, dir ) { 31659 while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} 31660 return cur; 31661} 31662 31663jQuery.each({ 31664 parent: function( elem ) { 31665 var parent = elem.parentNode; 31666 return parent && parent.nodeType !== 11 ? parent : null; 31667 }, 31668 parents: function( elem ) { 31669 return jQuery.dir( elem, "parentNode" ); 31670 }, 31671 parentsUntil: function( elem, i, until ) { 31672 return jQuery.dir( elem, "parentNode", until ); 31673 }, 31674 next: function( elem ) { 31675 return sibling( elem, "nextSibling" ); 31676 }, 31677 prev: function( elem ) { 31678 return sibling( elem, "previousSibling" ); 31679 }, 31680 nextAll: function( elem ) { 31681 return jQuery.dir( elem, "nextSibling" ); 31682 }, 31683 prevAll: function( elem ) { 31684 return jQuery.dir( elem, "previousSibling" ); 31685 }, 31686 nextUntil: function( elem, i, until ) { 31687 return jQuery.dir( elem, "nextSibling", until ); 31688 }, 31689 prevUntil: function( elem, i, until ) { 31690 return jQuery.dir( elem, "previousSibling", until ); 31691 }, 31692 siblings: function( elem ) { 31693 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); 31694 }, 31695 children: function( elem ) { 31696 return jQuery.sibling( elem.firstChild ); 31697 }, 31698 contents: function( elem ) { 31699 return elem.contentDocument || jQuery.merge( [], elem.childNodes ); 31700 } 31701}, function( name, fn ) { 31702 jQuery.fn[ name ] = function( until, selector ) { 31703 var matched = jQuery.map( this, fn, until ); 31704 31705 if ( name.slice( -5 ) !== "Until" ) { 31706 selector = until; 31707 } 31708 31709 if ( selector && typeof selector === "string" ) { 31710 matched = jQuery.filter( selector, matched ); 31711 } 31712 31713 if ( this.length > 1 ) { 31714 // Remove duplicates 31715 if ( !guaranteedUnique[ name ] ) { 31716 jQuery.unique( matched ); 31717 } 31718 31719 // Reverse order for parents* and prev-derivatives 31720 if ( rparentsprev.test( name ) ) { 31721 matched.reverse(); 31722 } 31723 } 31724 31725 return this.pushStack( matched ); 31726 }; 31727}); 31728var rnotwhite = (/\S+/g); 31729 31730 31731 31732// String to Object options format cache 31733var optionsCache = {}; 31734 31735// Convert String-formatted options into Object-formatted ones and store in cache 31736function createOptions( options ) { 31737 var object = optionsCache[ options ] = {}; 31738 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { 31739 object[ flag ] = true; 31740 }); 31741 return object; 31742} 31743 31744/* 31745 * Create a callback list using the following parameters: 31746 * 31747 * options: an optional list of space-separated options that will change how 31748 * the callback list behaves or a more traditional option object 31749 * 31750 * By default a callback list will act like an event callback list and can be 31751 * "fired" multiple times. 31752 * 31753 * Possible options: 31754 * 31755 * once: will ensure the callback list can only be fired once (like a Deferred) 31756 * 31757 * memory: will keep track of previous values and will call any callback added 31758 * after the list has been fired right away with the latest "memorized" 31759 * values (like a Deferred) 31760 * 31761 * unique: will ensure a callback can only be added once (no duplicate in the list) 31762 * 31763 * stopOnFalse: interrupt callings when a callback returns false 31764 * 31765 */ 31766jQuery.Callbacks = function( options ) { 31767 31768 // Convert options from String-formatted to Object-formatted if needed 31769 // (we check in cache first) 31770 options = typeof options === "string" ? 31771 ( optionsCache[ options ] || createOptions( options ) ) : 31772 jQuery.extend( {}, options ); 31773 31774 var // Last fire value (for non-forgettable lists) 31775 memory, 31776 // Flag to know if list was already fired 31777 fired, 31778 // Flag to know if list is currently firing 31779 firing, 31780 // First callback to fire (used internally by add and fireWith) 31781 firingStart, 31782 // End of the loop when firing 31783 firingLength, 31784 // Index of currently firing callback (modified by remove if needed) 31785 firingIndex, 31786 // Actual callback list 31787 list = [],
31788 // Stack of fire calls for repeatable lists 31789 stack = !options.once && [], 31790 // Fire callbacks 31791 fire = function( data ) { 31792 memory = options.memory && data; 31793 fired = true; 31794 firingIndex = firingStart || 0; 31795 firingStart = 0; 31796 firingLength = list.length; 31797 firing = true; 31798 for ( ; list && firingIndex < firingLength; firingIndex++ ) { 31799 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { 31800 memory = false; // To prevent further calls using add 31801 break; 31802 } 31803 } 31804 firing = false; 31805 if ( list ) { 31806 if ( stack ) { 31807 if ( stack.length ) { 31808 fire( stack.shift() ); 31809 } 31810 } else if ( memory ) { 31811 list = []; 31812 } else { 31813 self.disable(); 31814 } 31815 } 31816 }, 31817 // Actual Callbacks object 31818 self = { 31819 // Add a callback or a collection of callbacks to the list 31820 add: function() { 31821 if ( list ) { 31822 // First, we save the current length 31823 var start = list.length; 31824 (function add( args ) { 31825 jQuery.each( args, function( _, arg ) { 31826 var type = jQuery.type( arg ); 31827 if ( type === "function" ) { 31828 if ( !options.unique || !self.has( arg ) ) { 31829 list.push( arg ); 31830 } 31831 } else if ( arg && arg.length && type !== "string" ) { 31832 // Inspect recursively 31833 add( arg ); 31834 } 31835 }); 31836 })( arguments ); 31837 // Do we need to add the callbacks to the 31838 // current firing batch? 31839 if ( firing ) { 31840 firingLength = list.length; 31841 // With memory, if we're not firing then 31842 // we should call right away 31843 } else if ( memory ) { 31844 firingStart = start; 31845 fire( memory ); 31846 } 31847 } 31848 return this; 31849 }, 31850 // Remove a callback from the list 31851 remove: function() { 31852 if ( list ) { 31853 jQuery.each( arguments, function( _, arg ) { 31854 var index; 31855 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { 31856 list.splice( index, 1 ); 31857 // Handle firing indexes 31858 if ( firing ) { 31859 if ( index <= firingLength ) { 31860 firingLength--; 31861 } 31862 if ( index <= firingIndex ) { 31863 firingIndex--; 31864 } 31865 } 31866 } 31867 }); 31868 } 31869 return this; 31870 }, 31871 // Check if a given callback is in the list. 31872 // If no argument is given, return whether or not list has callbacks attached. 31873 has: function( fn ) { 31874 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); 31875 }, 31876 // Remove all callbacks from the list 31877 empty: function() { 31878 list = []; 31879 firingLength = 0; 31880 return this; 31881 }, 31882 // Have the list do nothing anymore 31883 disable: function() { 31884 list = stack = memory = undefined; 31885 return this; 31886 }, 31887 // Is it disabled? 31888 disabled: function() { 31889 return !list; 31890 }, 31891 // Lock the list in its current state 31892 lock: function() { 31893 stack = undefined; 31894 if ( !memory ) { 31895 self.disable(); 31896 } 31897 return this; 31898 }, 31899 // Is it locked? 31900 locked: function() { 31901 return !stack; 31902 }, 31903 // Call all callbacks with the given context and arguments 31904 fireWith: function( context, args ) { 31905 if ( list && ( !fired || stack ) ) { 31906 args = args || []; 31907 args = [ context, args.slice ? args.slice() : args ]; 31908 if ( firing ) { 31909 stack.push( args ); 31910 } else { 31911 fire( args ); 31912 } 31913 } 31914 return this; 31915 }, 31916 // Call all the callbacks with the given arguments 31917 fire: function() { 31918 self.fireWith( this, arguments ); 31919 return this; 31920 }, 31921 // To know if the callbacks have already been called at least once 31922 fired: function() { 31923 return !!fired; 31924 } 31925 }; 31926 31927 return self; 31928}; 31929 31930 31931jQuery.extend({ 31932 31933 Deferred: function( func ) { 31934 var tuples = [ 31935 // action, add listener, listener list, final state 31936 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], 31937 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], 31938 [ "notify", "progress", jQuery.Callbacks("memory") ] 31939 ], 31940 state = "pending", 31941 promise = { 31942 state: function() { 31943 return state; 31944 }, 31945 always: function() { 31946 deferred.done( arguments ).fail( arguments ); 31947 return this; 31948 }, 31949 then: function( /* fnDone, fnFail, fnProgress */ ) { 31950 var fns = arguments; 31951 return jQuery.Deferred(function( newDefer ) { 31952 jQuery.each( tuples, function( i, tuple ) { 31953 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; 31954 // deferred[ done | fail | progress ] for forwarding actions to newDefer 31955 deferred[ tuple[1] ](function() { 31956 var returned = fn && fn.apply( this, arguments ); 31957 if ( returned && jQuery.isFunction( returned.promise ) ) { 31958 returned.promise() 31959 .done( newDefer.resolve ) 31960 .fail( newDefer.reject ) 31961 .progress( newDefer.notify ); 31962 } else { 31963 newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); 31964 } 31965 });
31966 }); 31967 fns = null; 31968 }).promise(); 31969 }, 31970 // Get a promise for this deferred 31971 // If obj is provided, the promise aspect is added to the object 31972 promise: function( obj ) { 31973 return obj != null ? jQuery.extend( obj, promise ) : promise; 31974 } 31975 }, 31976 deferred = {}; 31977 31978 // Keep pipe for back-compat 31979 promise.pipe = promise.then; 31980 31981 // Add list-specific methods 31982 jQuery.each( tuples, function( i, tuple ) { 31983 var list = tuple[ 2 ], 31984 stateString = tuple[ 3 ]; 31985 31986 // promise[ done | fail | progress ] = list.add 31987 promise[ tuple[1] ] = list.add; 31988 31989 // Handle state 31990 if ( stateString ) { 31991 list.add(function() { 31992 // state = [ resolved | rejected ] 31993 state = stateString; 31994 31995 // [ reject_list | resolve_list ].disable; progress_list.lock 31996 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); 31997 } 31998 31999 // deferred[ resolve | reject | notify ] 32000 deferred[ tuple[0] ] = function() { 32001 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); 32002 return this; 32003 }; 32004 deferred[ tuple[0] + "With" ] = list.fireWith; 32005 }); 32006 32007 // Make the deferred a promise 32008 promise.promise( deferred ); 32009 32010 // Call given func if any 32011 if ( func ) { 32012 func.call( deferred, deferred ); 32013 } 32014 32015 // All done! 32016 return deferred; 32017 }, 32018 32019 // Deferred helper 32020 when: function( subordinate /* , ..., subordinateN */ ) { 32021 var i = 0, 32022 resolveValues = slice.call( arguments ), 32023 length = resolveValues.length, 32024 32025 // the count of uncompleted subordinates 32026 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, 32027 32028 // the master Deferred. If resolveValues consist of only a single Deferred, just use that. 32029 deferred = remaining === 1 ? subordinate : jQuery.Deferred(), 32030 32031 // Update function for both resolve and progress values 32032 updateFunc = function( i, contexts, values ) { 32033 return function( value ) { 32034 contexts[ i ] = this; 32035 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; 32036 if ( values === progressValues ) { 32037 deferred.notifyWith( contexts, values ); 32038 } else if ( !( --remaining ) ) { 32039 deferred.resolveWith( contexts, values ); 32040 } 32041 }; 32042 }, 32043 32044 progressValues, progressContexts, resolveContexts; 32045 32046 // Add listeners to Deferred subordinates; treat others as resolved 32047 if ( length > 1 ) { 32048 progressValues = new Array( length ); 32049 progressContexts = new Array( length ); 32050 resolveContexts = new Array( length ); 32051 for ( ; i < length; i++ ) { 32052 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { 32053 resolveValues[ i ].promise() 32054 .done( updateFunc( i, resolveContexts, resolveValues ) ) 32055 .fail( deferred.reject ) 32056 .progress( updateFunc( i, progressContexts, progressValues ) ); 32057 } else { 32058 --remaining; 32059 } 32060 } 32061 } 32062 32063 // If we're not waiting on anything, resolve the master 32064 if ( !remaining ) { 32065 deferred.resolveWith( resolveContexts, resolveValues ); 32066 } 32067 32068 return deferred.promise(); 32069 } 32070}); 32071 32072 32073// The deferred used on DOM ready 32074var readyList; 32075 32076jQuery.fn.ready = function( fn ) { 32077 // Add the callback 32078 jQuery.ready.promise().done( fn ); 32079 32080 return this; 32081}; 32082 32083jQuery.extend({ 32084 // Is the DOM ready to be used? Set to true once it occurs. 32085 isReady: false, 32086 32087 // A counter to track how many items to wait for before 32088 // the ready event fires. See #6781 32089 readyWait: 1, 32090 32091 // Hold (or release) the ready event 32092 holdReady: function( hold ) { 32093 if ( hold ) { 32094 jQuery.readyWait++; 32095 } else { 32096 jQuery.ready( true ); 32097 } 32098 }, 32099 32100 // Handle when the DOM is ready 32101 ready: function( wait ) { 32102 32103 // Abort if there are pending holds or we're already ready 32104 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 32105 return; 32106 } 32107 32108 // Remember that the DOM is ready 32109 jQuery.isReady = true; 32110 32111 // If a normal DOM Ready event fired, decrement, and wait if need be 32112 if ( wait !== true && --jQuery.readyWait > 0 ) { 32113 return; 32114 } 32115
32116 // If there are functions bound, to execute 32117 readyList.resolveWith( document, [ jQuery ] ); 32118 32119 // Trigger any bound ready events 32120 if ( jQuery.fn.triggerHandler ) { 32121 jQuery( document ).triggerHandler( "ready" ); 32122 jQuery( document ).off( "ready" ); 32123 } 32124 } 32125}); 32126 32127/** 32128 * The ready event handler and self cleanup method 32129 */ 32130function completed() { 32131 document.removeEventListener( "DOMContentLoaded", completed, false ); 32132 window.removeEventListener( "load", completed, false ); 32133 jQuery.ready(); 32134} 32135 32136jQuery.ready.promise = function( obj ) { 32137 if ( !readyList ) { 32138 32139 readyList = jQuery.Deferred(); 32140 32141 // Catch cases where $(document).ready() is called after the browser event has already occurred. 32142 // We once tried to use readyState "interactive" here, but it caused issues like the one 32143 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 32144 if ( document.readyState === "complete" ) { 32145 // Handle it asynchronously to allow scripts the opportunity to delay ready 32146 setTimeout( jQuery.ready ); 32147 32148 } else { 32149 32150 // Use the handy event callback 32151 document.addEventListener( "DOMContentLoaded", completed, false ); 32152 32153 // A fallback to window.onload, that will always work 32154 window.addEventListener( "load", completed, false ); 32155 } 32156 } 32157 return readyList.promise( obj ); 32158}; 32159 32160// Kick off the DOM ready check even if the user does not 32161jQuery.ready.promise(); 32162 32163 32164 32165 32166// Multifunctional method to get and set values of a collection 32167// The value/s can optionally be executed if it's a function 32168var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { 32169 var i = 0, 32170 len = elems.length, 32171 bulk = key == null; 32172 32173 // Sets many values 32174 if ( jQuery.type( key ) === "object" ) { 32175 chainable = true; 32176 for ( i in key ) { 32177 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); 32178 } 32179 32180 // Sets one value 32181 } else if ( value !== undefined ) { 32182 chainable = true; 32183 32184 if ( !jQuery.isFunction( value ) ) { 32185 raw = true; 32186 } 32187 32188 if ( bulk ) { 32189 // Bulk operations run against the entire set 32190 if ( raw ) { 32191 fn.call( elems, value ); 32192 fn = null; 32193 32194 // ...except when executing function values 32195 } else { 32196 bulk = fn; 32197 fn = function( elem, key, value ) { 32198 return bulk.call( jQuery( elem ), value ); 32199 }; 32200 } 32201 } 32202 32203 if ( fn ) { 32204 for ( ; i < len; i++ ) { 32205 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); 32206 } 32207 } 32208 } 32209 32210 return chainable ? 32211 elems : 32212 32213 // Gets 32214 bulk ? 32215 fn.call( elems ) : 32216 len ? fn( elems[0], key ) : emptyGet; 32217}; 32218 32219 32220/** 32221 * Determines whether an object can have data 32222 */ 32223jQuery.acceptData = function( owner ) { 32224 // Accepts only: 32225 // - Node 32226 // - Node.ELEMENT_NODE 32227 // - Node.DOCUMENT_NODE 32228 // - Object 32229 // - Any 32230 /* jshint -W018 */ 32231 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); 32232}; 32233 32234 32235function Data() { 32236 // Support: Android<4, 32237 // Old WebKit does not have Object.preventExtensions/freeze method, 32238 // return new empty object instead with no [[set]] accessor 32239 Object.defineProperty( this.cache = {}, 0, { 32240 get: function() { 32241 return {}; 32242 } 32243 }); 32244 32245 this.expando = jQuery.expando + Data.uid++; 32246} 32247 32248Data.uid = 1; 32249Data.accepts = jQuery.acceptData; 32250 32251Data.prototype = { 32252 key: function( owner ) { 32253 // We can accept data for non-element nodes in modern browsers, 32254 // but we should not, see #8335. 32255 // Always return the key for a frozen object. 32256 if ( !Data.accepts( owner ) ) { 32257 return 0; 32258 } 32259 32260 var descriptor = {}, 32261 // Check if the owner object already has a cache key 32262 unlock = owner[ this.expando ]; 32263 32264 // If not, create one 32265 if ( !unlock ) { 32266 unlock = Data.uid++; 32267 32268 // Secure it in a non-enumerable, non-writable property 32269 try { 32270 descriptor[ this.expando ] = { value: unlock }; 32271 Object.defineProperties( owner, descriptor ); 32272 32273 // Support: Android<4 32274 // Fallback to a less secure definition 32275 } catch ( e ) { 32276 descriptor[ this.expando ] = unlock; 32277 jQuery.extend( owner, descriptor ); 32278 } 32279 } 32280 32281 // Ensure the cache object 32282 if ( !this.cache[ unlock ] ) { 32283 this.cache[ unlock ] = {}; 32284 } 32285 32286 return unlock; 32287 }, 32288 set: function( owner, data, value ) { 32289 var prop, 32290 // There may be an unlock assigned to this node, 32291 // if there is no entry for this "owner", create one inline 32292 // and set the unlock as though an owner entry had always existed 32293 unlock = this.key( owner ), 32294 cache = this.cache[ unlock ]; 32295 32296 // Handle: [ owner, key, value ] args 32297 if ( typeof data === "string" ) { 32298 cache[ data ] = value; 32299 32300 // Handle: [ owner, { properties } ] args 32301 } else { 32302 // Fresh assignments by object are shallow copied
32303 if ( jQuery.isEmptyObject( cache ) ) { 32304 jQuery.extend( this.cache[ unlock ], data ); 32305 // Otherwise, copy the properties one-by-one to the cache object 32306 } else { 32307 for ( prop in data ) { 32308 cache[ prop ] = data[ prop ]; 32309 } 32310 } 32311 } 32312 return cache; 32313 }, 32314 get: function( owner, key ) { 32315 // Either a valid cache is found, or will be created. 32316 // New caches will be created and the unlock returned, 32317 // allowing direct access to the newly created 32318 // empty data object. A valid owner object must be provided. 32319 var cache = this.cache[ this.key( owner ) ]; 32320 32321 return key === undefined ? 32322 cache : cache[ key ]; 32323 }, 32324 access: function( owner, key, value ) { 32325 var stored; 32326 // In cases where either: 32327 // 32328 // 1. No key was specified 32329 // 2. A string key was specified, but no value provided 32330 // 32331 // Take the "read" path and allow the get method to determine 32332 // which value to return, respectively either: 32333 // 32334 // 1. The entire cache object 32335 // 2. The data stored at the key 32336 // 32337 if ( key === undefined || 32338 ((key && typeof key === "string") && value === undefined) ) { 32339 32340 stored = this.get( owner, key ); 32341 32342 return stored !== undefined ? 32343 stored : this.get( owner, jQuery.camelCase(key) ); 32344 } 32345 32346 // [*]When the key is not a string, or both a key and value 32347 // are specified, set or extend (existing objects) with either: 32348 // 32349 // 1. An object of properties 32350 // 2. A key and value 32351 // 32352 this.set( owner, key, value ); 32353 32354 // Since the "set" path can have two possible entry points 32355 // return the expected data based on which path was taken[*] 32356 return value !== undefined ? value : key; 32357 }, 32358 remove: function( owner, key ) { 32359 var i, name, camel, 32360 unlock = this.key( owner ), 32361 cache = this.cache[ unlock ]; 32362 32363 if ( key === undefined ) { 32364 this.cache[ unlock ] = {}; 32365 32366 } else { 32367 // Support array or space separated string of keys 32368 if ( jQuery.isArray( key ) ) { 32369 // If "name" is an array of keys... 32370 // When data is initially created, via ("key", "val") signature, 32371 // keys will be converted to camelCase. 32372 // Since there is no way to tell _how_ a key was added, remove 32373 // both plain key and camelCase key. #12786 32374 // This will only penalize the array argument path. 32375 name = key.concat( key.map( jQuery.camelCase ) ); 32376 } else { 32377 camel = jQuery.camelCase( key ); 32378 // Try the string as a key before any manipulation 32379 if ( key in cache ) { 32380 name = [ key, camel ]; 32381 } else { 32382 // If a key with the spaces exists, use it. 32383 // Otherwise, create an array by matching non-whitespace 32384 name = camel; 32385 name = name in cache ? 32386 [ name ] : ( name.match( rnotwhite ) || [] ); 32387 } 32388 } 32389 32390 i = name.length; 32391 while ( i-- ) { 32392 delete cache[ name[ i ] ]; 32393 } 32394 } 32395 }, 32396 hasData: function( owner ) { 32397 return !jQuery.isEmptyObject( 32398 this.cache[ owner[ this.expando ] ] || {} 32399 ); 32400 }, 32401 discard: function( owner ) { 32402 if ( owner[ this.expando ] ) { 32403 delete this.cache[ owner[ this.expando ] ]; 32404 } 32405 } 32406}; 32407var data_priv = new Data(); 32408 32409var data_user = new Data(); 32410 32411 32412 32413// Implementation Summary 32414// 32415// 1. Enforce API surface and semantic compatibility with 1.9.x branch 32416// 2. Improve the module's maintainability by reducing the storage 32417// paths to a single mechanism. 32418// 3. Use the same single mechanism to support "private" and "user" data. 32419// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) 32420// 5. Avoid exposing implementation details on user objects (eg. expando properties) 32421// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 32422 32423var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, 32424 rmultiDash = /([A-Z])/g; 32425 32426function dataAttr( elem, key, data ) { 32427 var name; 32428 32429 // If nothing was found internally, try to fetch any 32430 // data from the HTML5 data-* attribute 32431 if ( data === undefined && elem.nodeType === 1 ) { 32432 name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); 32433 data = elem.getAttribute( name ); 32434 32435 if ( typeof data === "string" ) { 32436 try { 32437 data = data === "true" ? true :
32438 data === "false" ? false : 32439 data === "null" ? null : 32440 // Only convert to a number if it doesn't change the string 32441 +data + "" === data ? +data : 32442 rbrace.test( data ) ? jQuery.parseJSON( data ) : 32443 data; 32444 } catch( e ) {} 32445 32446 // Make sure we set the data so it isn't changed later 32447 data_user.set( elem, key, data ); 32448 } else { 32449 data = undefined; 32450 } 32451 } 32452 return data; 32453} 32454 32455jQuery.extend({ 32456 hasData: function( elem ) { 32457 return data_user.hasData( elem ) || data_priv.hasData( elem ); 32458 }, 32459 32460 data: function( elem, name, data ) { 32461 return data_user.access( elem, name, data ); 32462 }, 32463 32464 removeData: function( elem, name ) { 32465 data_user.remove( elem, name ); 32466 }, 32467 32468 // TODO: Now that all calls to _data and _removeData have been replaced 32469 // with direct calls to data_priv methods, these can be deprecated. 32470 _data: function( elem, name, data ) { 32471 return data_priv.access( elem, name, data ); 32472 }, 32473 32474 _removeData: function( elem, name ) { 32475 data_priv.remove( elem, name ); 32476 } 32477}); 32478 32479jQuery.fn.extend({ 32480 data: function( key, value ) { 32481 var i, name, data, 32482 elem = this[ 0 ], 32483 attrs = elem && elem.attributes; 32484 32485 // Gets all values 32486 if ( key === undefined ) { 32487 if ( this.length ) { 32488 data = data_user.get( elem ); 32489 32490 if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { 32491 i = attrs.length; 32492 while ( i-- ) { 32493 32494 // Support: IE11+ 32495 // The attrs elements can be null (#14894) 32496 if ( attrs[ i ] ) { 32497 name = attrs[ i ].name; 32498 if ( name.indexOf( "data-" ) === 0 ) { 32499 name = jQuery.camelCase( name.slice(5) ); 32500 dataAttr( elem, name, data[ name ] ); 32501 } 32502 } 32503 } 32504 data_priv.set( elem, "hasDataAttrs", true ); 32505 } 32506 } 32507 32508 return data; 32509 } 32510 32511 // Sets multiple values 32512 if ( typeof key === "object" ) { 32513 return this.each(function() { 32514 data_user.set( this, key ); 32515 }); 32516 } 32517 32518 return access( this, function( value ) { 32519 var data, 32520 camelKey = jQuery.camelCase( key ); 32521 32522 // The calling jQuery object (element matches) is not empty 32523 // (and therefore has an element appears at this[ 0 ]) and the 32524 // `value` parameter was not undefined. An empty jQuery object 32525 // will result in `undefined` for elem = this[ 0 ] which will 32526 // throw an exception if an attempt to read a data cache is made. 32527 if ( elem && value === undefined ) { 32528 // Attempt to get data from the cache 32529 // with the key as-is 32530 data = data_user.get( elem, key ); 32531 if ( data !== undefined ) { 32532 return data; 32533 } 32534 32535 // Attempt to get data from the cache 32536 // with the key camelized 32537 data = data_user.get( elem, camelKey ); 32538 if ( data !== undefined ) { 32539 return data; 32540 } 32541 32542 // Attempt to "discover" the data in 32543 // HTML5 custom data-* attrs 32544 data = dataAttr( elem, camelKey, undefined ); 32545 if ( data !== undefined ) { 32546 return data; 32547 } 32548 32549 // We tried really hard, but the data doesn't exist. 32550 return; 32551 } 32552 32553 // Set the data... 32554 this.each(function() { 32555 // First, attempt to store a copy or reference of any 32556 // data that might've been store with a camelCased key. 32557 var data = data_user.get( this, camelKey ); 32558 32559 // For HTML5 data-* attribute interop, we have to 32560 // store property names with dashes in a camelCase form. 32561 // This might not apply to all properties...* 32562 data_user.set( this, camelKey, value ); 32563 32564 // *... In the case of properties that might _actually_ 32565 // have dashes, we need to also store a copy of that 32566 // unchanged property. 32567 if ( key.indexOf("-") !== -1 && data !== undefined ) { 32568 data_user.set( this, key, value ); 32569 } 32570 }); 32571 }, null, value, arguments.length > 1, null, true ); 32572 }, 32573 32574 removeData: function( key ) { 32575 return this.each(function() { 32576 data_user.remove( this, key ); 32577 }); 32578 } 32579}); 32580 32581 32582jQuery.extend({ 32583 queue: function( elem, type, data ) { 32584 var queue; 32585 32586 if ( elem ) { 32587 type = ( type || "fx" ) + "queue"; 32588 queue = data_priv.get( elem, type ); 32589 32590 // Speed up dequeue by getting out quickly if this is just a lookup 32591 if ( data ) { 32592 if ( !queue || jQuery.isArray( data ) ) { 32593 queue = data_priv.access( elem, type, jQuery.makeArray(data) ); 32594 } else { 32595 queue.push( data ); 32596 } 32597 } 32598 return queue || []; 32599 } 32600 }, 32601 32602 dequeue: function( elem, type ) {
vendor: 3,566 bytes, lines 32603-32744
32603 type = type || "fx"; 32604 32605 var queue = jQuery.queue( elem, type ), 32606 startLength = queue.length, 32607 fn = queue.shift(), 32608 hooks = jQuery._queueHooks( elem, type ), 32609 next = function() { 32610 jQuery.dequeue( elem, type ); 32611 }; 32612 32613 // If the fx queue is dequeued, always remove the progress sentinel 32614 if ( fn === "inprogress" ) { 32615 fn = queue.shift(); 32616 startLength--; 32617 } 32618 32619 if ( fn ) { 32620 32621 // Add a progress sentinel to prevent the fx queue from being 32622 // automatically dequeued 32623 if ( type === "fx" ) { 32624 queue.unshift( "inprogress" ); 32625 } 32626 32627 // Clear up the last queue stop function 32628 delete hooks.stop; 32629 fn.call( elem, next, hooks ); 32630 } 32631 32632 if ( !startLength && hooks ) { 32633 hooks.empty.fire(); 32634 } 32635 }, 32636 32637 // Not public - generate a queueHooks object, or return the current one 32638 _queueHooks: function( elem, type ) { 32639 var key = type + "queueHooks"; 32640 return data_priv.get( elem, key ) || data_priv.access( elem, key, { 32641 empty: jQuery.Callbacks("once memory").add(function() { 32642 data_priv.remove( elem, [ type + "queue", key ] ); 32643 }) 32644 }); 32645 } 32646}); 32647 32648jQuery.fn.extend({ 32649 queue: function( type, data ) { 32650 var setter = 2; 32651 32652 if ( typeof type !== "string" ) { 32653 data = type; 32654 type = "fx"; 32655 setter--; 32656 } 32657 32658 if ( arguments.length < setter ) { 32659 return jQuery.queue( this[0], type ); 32660 } 32661 32662 return data === undefined ? 32663 this : 32664 this.each(function() { 32665 var queue = jQuery.queue( this, type, data ); 32666 32667 // Ensure a hooks for this queue 32668 jQuery._queueHooks( this, type ); 32669 32670 if ( type === "fx" && queue[0] !== "inprogress" ) { 32671 jQuery.dequeue( this, type ); 32672 } 32673 }); 32674 }, 32675 dequeue: function( type ) { 32676 return this.each(function() { 32677 jQuery.dequeue( this, type ); 32678 }); 32679 }, 32680 clearQueue: function( type ) { 32681 return this.queue( type || "fx", [] ); 32682 }, 32683 // Get a promise resolved when queues of a certain type 32684 // are emptied (fx is the type by default) 32685 promise: function( type, obj ) { 32686 var tmp, 32687 count = 1, 32688 defer = jQuery.Deferred(), 32689 elements = this, 32690 i = this.length, 32691 resolve = function() { 32692 if ( !( --count ) ) { 32693 defer.resolveWith( elements, [ elements ] ); 32694 } 32695 }; 32696 32697 if ( typeof type !== "string" ) { 32698 obj = type; 32699 type = undefined; 32700 } 32701 type = type || "fx"; 32702 32703 while ( i-- ) { 32704 tmp = data_priv.get( elements[ i ], type + "queueHooks" ); 32705 if ( tmp && tmp.empty ) { 32706 count++; 32707 tmp.empty.add( resolve ); 32708 } 32709 } 32710 resolve(); 32711 return defer.promise( obj ); 32712 } 32713}); 32714var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; 32715 32716var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; 32717 32718var isHidden = function( elem, el ) { 32719 // isHidden might be called from jQuery#filter function; 32720 // in that case, element will be second argument 32721 elem = el || elem; 32722 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); 32723 }; 32724 32725var rcheckableType = (/^(?:checkbox|radio)$/i); 32726 32727 32728 32729(function() { 32730 var fragment = document.createDocumentFragment(), 32731 div = fragment.appendChild( document.createElement( "div" ) ), 32732 input = document.createElement( "input" ); 32733 32734 // Support: Safari<=5.1 32735 // Check state lost if the name is set (#11217) 32736 // Support: Windows Web Apps (WWA) 32737 // `name` and `type` must use .setAttribute for WWA (#14901) 32738 input.setAttribute( "type", "radio" ); 32739 input.setAttribute( "checked", "checked" ); 32740 input.setAttribute( "name", "t" ); 32741 32742 div.appendChild( input ); 32743 32744 // Support: Safari<=5.1, Android<4.2
32745 // Older WebKit doesn't clone checked state correctly in fragments 32746 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; 32747 32748 // Support: IE<=11+ 32749 // Make sure textarea (and checkbox) defaultValue is properly cloned 32750 div.innerHTML = "<textarea>x</textarea>"; 32751 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; 32752})(); 32753var strundefined = typeof undefined; 32754 32755 32756 32757support.focusinBubbles = "onfocusin" in window; 32758 32759 32760var 32761 rkeyEvent = /^key/, 32762 rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, 32763 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 32764 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; 32765 32766function returnTrue() { 32767 return true; 32768} 32769 32770function returnFalse() { 32771 return false; 32772} 32773 32774function safeActiveElement() { 32775 try { 32776 return document.activeElement; 32777 } catch ( err ) { } 32778} 32779 32780/* 32781 * Helper functions for managing events -- not part of the public interface. 32782 * Props to Dean Edwards' addEvent library for many of the ideas. 32783 */ 32784jQuery.event = { 32785 32786 global: {}, 32787 32788 add: function( elem, types, handler, data, selector ) { 32789 32790 var handleObjIn, eventHandle, tmp, 32791 events, t, handleObj, 32792 special, handlers, type, namespaces, origType, 32793 elemData = data_priv.get( elem ); 32794 32795 // Don't attach events to noData or text/comment nodes (but allow plain objects) 32796 if ( !elemData ) { 32797 return; 32798 } 32799 32800 // Caller can pass in an object of custom data in lieu of the handler 32801 if ( handler.handler ) { 32802 handleObjIn = handler; 32803 handler = handleObjIn.handler; 32804 selector = handleObjIn.selector; 32805 } 32806 32807 // Make sure that the handler has a unique ID, used to find/remove it later 32808 if ( !handler.guid ) { 32809 handler.guid = jQuery.guid++; 32810 } 32811 32812 // Init the element's event structure and main handler, if this is the first 32813 if ( !(events = elemData.events) ) { 32814 events = elemData.events = {}; 32815 } 32816 if ( !(eventHandle = elemData.handle) ) { 32817 eventHandle = elemData.handle = function( e ) { 32818 // Discard the second event of a jQuery.event.trigger() and 32819 // when an event is called after a page has unloaded 32820 return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? 32821 jQuery.event.dispatch.apply( elem, arguments ) : undefined; 32822 }; 32823 } 32824 32825 // Handle multiple events separated by a space 32826 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 32827 t = types.length; 32828 while ( t-- ) { 32829 tmp = rtypenamespace.exec( types[t] ) || []; 32830 type = origType = tmp[1]; 32831 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 32832 32833 // There *must* be a type, no attaching namespace-only handlers 32834 if ( !type ) { 32835 continue; 32836 } 32837 32838 // If event changes its type, use the special event handlers for the changed type 32839 special = jQuery.event.special[ type ] || {}; 32840 32841 // If selector defined, determine special event api type, otherwise given type 32842 type = ( selector ? special.delegateType : special.bindType ) || type; 32843 32844 // Update special based on newly reset type 32845 special = jQuery.event.special[ type ] || {}; 32846 32847 // handleObj is passed to all event handlers 32848 handleObj = jQuery.extend({ 32849 type: type, 32850 origType: origType, 32851 data: data, 32852 handler: handler, 32853 guid: handler.guid, 32854 selector: selector, 32855 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 32856 namespace: namespaces.join(".") 32857 }, handleObjIn ); 32858 32859 // Init the event handler queue if we're the first 32860 if ( !(handlers = events[ type ]) ) { 32861 handlers = events[ type ] = []; 32862 handlers.delegateCount = 0; 32863 32864 // Only use addEventListener if the special events handler returns false 32865 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 32866 if ( elem.addEventListener ) { 32867 elem.addEventListener( type, eventHandle, false ); 32868 } 32869 } 32870 } 32871 32872 if ( special.add ) { 32873 special.add.call( elem, handleObj ); 32874 32875 if ( !handleObj.handler.guid ) { 32876 handleObj.handler.guid = handler.guid; 32877 } 32878 } 32879 32880 // Add to the element's handler list, delegates in front 32881 if ( selector ) { 32882 handlers.splice( handlers.delegateCount++, 0, handleObj ); 32883 } else { 32884 handlers.push( handleObj ); 32885 } 32886 32887 // Keep track of which events have ever been used, for event optimization 32888 jQuery.event.global[ type ] = true; 32889 } 32890 32891 }, 32892 32893 // Detach an event or set of events from an element 32894 remove: function( elem, types, handler, selector, mappedTypes ) { 32895 32896 var j, origCount, tmp, 32897 events, t, handleObj, 32898 special, handlers, type, namespaces, origType, 32899 elemData = data_priv.hasData( elem ) && data_priv.get( elem ); 32900 32901 if ( !elemData || !(events = elemData.events) ) { 32902 return; 32903 } 32904
vendor: 8,359 bytes, lines 32905-33162
32905 // Once for each type.namespace in types; type may be omitted 32906 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 32907 t = types.length; 32908 while ( t-- ) { 32909 tmp = rtypenamespace.exec( types[t] ) || []; 32910 type = origType = tmp[1]; 32911 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 32912 32913 // Unbind all events (on this namespace, if provided) for the element 32914 if ( !type ) { 32915 for ( type in events ) { 32916 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 32917 } 32918 continue; 32919 } 32920 32921 special = jQuery.event.special[ type ] || {}; 32922 type = ( selector ? special.delegateType : special.bindType ) || type; 32923 handlers = events[ type ] || []; 32924 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); 32925 32926 // Remove matching events 32927 origCount = j = handlers.length; 32928 while ( j-- ) { 32929 handleObj = handlers[ j ]; 32930 32931 if ( ( mappedTypes || origType === handleObj.origType ) && 32932 ( !handler || handler.guid === handleObj.guid ) && 32933 ( !tmp || tmp.test( handleObj.namespace ) ) && 32934 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { 32935 handlers.splice( j, 1 ); 32936 32937 if ( handleObj.selector ) { 32938 handlers.delegateCount--; 32939 } 32940 if ( special.remove ) { 32941 special.remove.call( elem, handleObj ); 32942 } 32943 } 32944 } 32945 32946 // Remove generic event handler if we removed something and no more handlers exist 32947 // (avoids potential for endless recursion during removal of special event handlers) 32948 if ( origCount && !handlers.length ) { 32949 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 32950 jQuery.removeEvent( elem, type, elemData.handle ); 32951 } 32952 32953 delete events[ type ]; 32954 } 32955 } 32956 32957 // Remove the expando if it's no longer used 32958 if ( jQuery.isEmptyObject( events ) ) { 32959 delete elemData.handle; 32960 data_priv.remove( elem, "events" ); 32961 } 32962 }, 32963 32964 trigger: function( event, data, elem, onlyHandlers ) { 32965 32966 var i, cur, tmp, bubbleType, ontype, handle, special, 32967 eventPath = [ elem || document ], 32968 type = hasOwn.call( event, "type" ) ? event.type : event, 32969 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; 32970 32971 cur = tmp = elem = elem || document; 32972 32973 // Don't do events on text and comment nodes 32974 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { 32975 return; 32976 } 32977 32978 // focus/blur morphs to focusin/out; ensure we're not firing them right now 32979 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 32980 return; 32981 } 32982 32983 if ( type.indexOf(".") >= 0 ) { 32984 // Namespaced trigger; create a regexp to match event type in handle() 32985 namespaces = type.split("."); 32986 type = namespaces.shift(); 32987 namespaces.sort(); 32988 } 32989 ontype = type.indexOf(":") < 0 && "on" + type; 32990 32991 // Caller can pass in a jQuery.Event object, Object, or just an event type string 32992 event = event[ jQuery.expando ] ? 32993 event : 32994 new jQuery.Event( type, typeof event === "object" && event ); 32995 32996 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) 32997 event.isTrigger = onlyHandlers ? 2 : 3; 32998 event.namespace = namespaces.join("."); 32999 event.namespace_re = event.namespace ? 33000 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : 33001 null; 33002 33003 // Clean up the event in case it is being reused 33004 event.result = undefined; 33005 if ( !event.target ) { 33006 event.target = elem; 33007 } 33008 33009 // Clone any incoming data and prepend the event, creating the handler arg list 33010 data = data == null ? 33011 [ event ] : 33012 jQuery.makeArray( data, [ event ] ); 33013 33014 // Allow special events to draw outside the lines 33015 special = jQuery.event.special[ type ] || {}; 33016 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { 33017 return; 33018 } 33019 33020 // Determine event propagation path in advance, per W3C events spec (#9951) 33021 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 33022 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { 33023 33024 bubbleType = special.delegateType || type; 33025 if ( !rfocusMorph.test( bubbleType + type ) ) { 33026 cur = cur.parentNode; 33027 } 33028 for ( ; cur; cur = cur.parentNode ) { 33029 eventPath.push( cur ); 33030 tmp = cur; 33031 } 33032 33033 // Only add window if we got to document (e.g., not plain obj or detached DOM) 33034 if ( tmp === (elem.ownerDocument || document) ) { 33035 eventPath.push( tmp.defaultView || tmp.parentWindow || window ); 33036 } 33037 } 33038 33039 // Fire handlers on the event path 33040 i = 0; 33041 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { 33042 33043 event.type = i > 1 ? 33044 bubbleType : 33045 special.bindType || type; 33046 33047 // jQuery handler 33048 handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); 33049 if ( handle ) { 33050 handle.apply( cur, data ); 33051 } 33052 33053 // Native handler 33054 handle = ontype && cur[ ontype ]; 33055 if ( handle && handle.apply && jQuery.acceptData( cur ) ) { 33056 event.result = handle.apply( cur, data ); 33057 if ( event.result === false ) { 33058 event.preventDefault(); 33059 } 33060 } 33061 } 33062 event.type = type; 33063 33064 // If nobody prevented the default action, do it now 33065 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 33066 33067 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && 33068 jQuery.acceptData( elem ) ) { 33069 33070 // Call a native DOM method on the target with the same name name as the event. 33071 // Don't do default actions on window, that's where global variables be (#6170) 33072 if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { 33073 33074 // Don't re-trigger an onFOO event when we call its FOO() method 33075 tmp = elem[ ontype ]; 33076 33077 if ( tmp ) { 33078 elem[ ontype ] = null; 33079 } 33080 33081 // Prevent re-triggering of the same event, since we already bubbled it above 33082 jQuery.event.triggered = type; 33083 elem[ type ](); 33084 jQuery.event.triggered = undefined; 33085 33086 if ( tmp ) { 33087 elem[ ontype ] = tmp; 33088 } 33089 } 33090 } 33091 } 33092 33093 return event.result; 33094 }, 33095 33096 dispatch: function( event ) { 33097 33098 // Make a writable jQuery.Event from the native event object 33099 event = jQuery.event.fix( event ); 33100 33101 var i, j, ret, matched, handleObj, 33102 handlerQueue = [], 33103 args = slice.call( arguments ), 33104 handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], 33105 special = jQuery.event.special[ event.type ] || {}; 33106 33107 // Use the fix-ed jQuery.Event rather than the (read-only) native event 33108 args[0] = event; 33109 event.delegateTarget = this; 33110 33111 // Call the preDispatch hook for the mapped type, and let it bail if desired 33112 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 33113 return; 33114 } 33115 33116 // Determine handlers 33117 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 33118 33119 // Run delegates first; they may want to stop propagation beneath us 33120 i = 0; 33121 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { 33122 event.currentTarget = matched.elem; 33123 33124 j = 0; 33125 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { 33126 33127 // Triggered event must either 1) have no namespace, or 2) have namespace(s) 33128 // a subset or equal to those in the bound event (both can have no namespace). 33129 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { 33130 33131 event.handleObj = handleObj; 33132 event.data = handleObj.data; 33133 33134 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) 33135 .apply( matched.elem, args ); 33136 33137 if ( ret !== undefined ) { 33138 if ( (event.result = ret) === false ) { 33139 event.preventDefault(); 33140 event.stopPropagation(); 33141 } 33142 } 33143 } 33144 } 33145 } 33146 33147 // Call the postDispatch hook for the mapped type 33148 if ( special.postDispatch ) { 33149 special.postDispatch.call( this, event ); 33150 } 33151 33152 return event.result; 33153 }, 33154 33155 handlers: function( event, handlers ) { 33156 var i, matches, sel, handleObj, 33157 handlerQueue = [], 33158 delegateCount = handlers.delegateCount, 33159 cur = event.target; 33160 33161 // Find delegate handlers 33162 // Black-hole SVG <use> instance trees (#13180)
33163 // Avoid non-left-click bubbling in Firefox (#3861) 33164 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { 33165 33166 for ( ; cur !== this; cur = cur.parentNode || this ) { 33167 33168 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) 33169 if ( cur.disabled !== true || event.type !== "click" ) { 33170 matches = []; 33171 for ( i = 0; i < delegateCount; i++ ) { 33172 handleObj = handlers[ i ]; 33173 33174 // Don't conflict with Object.prototype properties (#13203) 33175 sel = handleObj.selector + " "; 33176 33177 if ( matches[ sel ] === undefined ) { 33178 matches[ sel ] = handleObj.needsContext ? 33179 jQuery( sel, this ).index( cur ) >= 0 : 33180 jQuery.find( sel, this, null, [ cur ] ).length; 33181 } 33182 if ( matches[ sel ] ) { 33183 matches.push( handleObj ); 33184 } 33185 } 33186 if ( matches.length ) { 33187 handlerQueue.push({ elem: cur, handlers: matches }); 33188 } 33189 } 33190 } 33191 } 33192 33193 // Add the remaining (directly-bound) handlers 33194 if ( delegateCount < handlers.length ) { 33195 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); 33196 } 33197 33198 return handlerQueue; 33199 }, 33200 33201 // Includes some event props shared by KeyEvent and MouseEvent 33202 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), 33203 33204 fixHooks: {}, 33205 33206 keyHooks: { 33207 props: "char charCode key keyCode".split(" "), 33208 filter: function( event, original ) { 33209 33210 // Add which for key events 33211 if ( event.which == null ) { 33212 event.which = original.charCode != null ? original.charCode : original.keyCode; 33213 } 33214 33215 return event; 33216 } 33217 }, 33218 33219 mouseHooks: { 33220 props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), 33221 filter: function( event, original ) { 33222 var eventDoc, doc, body, 33223 button = original.button; 33224 33225 // Calculate pageX/Y if missing and clientX/Y available 33226 if ( event.pageX == null && original.clientX != null ) { 33227 eventDoc = event.target.ownerDocument || document; 33228 doc = eventDoc.documentElement; 33229 body = eventDoc.body; 33230 33231 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); 33232 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); 33233 } 33234 33235 // Add which for click: 1 === left; 2 === middle; 3 === right 33236 // Note: button is not normalized, so don't use it 33237 if ( !event.which && button !== undefined ) { 33238 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); 33239 } 33240 33241 return event; 33242 } 33243 }, 33244 33245 fix: function( event ) { 33246 if ( event[ jQuery.expando ] ) { 33247 return event; 33248 } 33249 33250 // Create a writable copy of the event object and normalize some properties 33251 var i, prop, copy, 33252 type = event.type, 33253 originalEvent = event, 33254 fixHook = this.fixHooks[ type ]; 33255 33256 if ( !fixHook ) { 33257 this.fixHooks[ type ] = fixHook = 33258 rmouseEvent.test( type ) ? this.mouseHooks : 33259 rkeyEvent.test( type ) ? this.keyHooks : 33260 {}; 33261 } 33262 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; 33263 33264 event = new jQuery.Event( originalEvent ); 33265 33266 i = copy.length; 33267 while ( i-- ) { 33268 prop = copy[ i ]; 33269 event[ prop ] = originalEvent[ prop ]; 33270 } 33271 33272 // Support: Cordova 2.5 (WebKit) (#13255) 33273 // All events should have a target; Cordova deviceready doesn't 33274 if ( !event.target ) { 33275 event.target = document; 33276 } 33277 33278 // Support: Safari 6.0+, Chrome<28 33279 // Target should not be a text node (#504, #13143) 33280 if ( event.target.nodeType === 3 ) { 33281 event.target = event.target.parentNode; 33282 } 33283 33284 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; 33285 }, 33286 33287 special: { 33288 load: { 33289 // Prevent triggered image.load events from bubbling to window.load 33290 noBubble: true 33291 }, 33292 focus: { 33293 // Fire native event if possible so blur/focus sequence is correct 33294 trigger: function() { 33295 if ( this !== safeActiveElement() && this.focus ) { 33296 this.focus(); 33297 return false; 33298 } 33299 }, 33300 delegateType: "focusin" 33301 }, 33302 blur: { 33303 trigger: function() { 33304 if ( this === safeActiveElement() && this.blur ) { 33305 this.blur(); 33306 return false; 33307 } 33308 }, 33309 delegateType: "focusout" 33310 }, 33311 click: { 33312 // For checkbox, fire native event so checked state will be right 33313 trigger: function() { 33314 if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { 33315 this.click(); 33316 return false; 33317 } 33318 }, 33319 33320 // For cross-browser consistency, don't fire native .click() on links 33321 _default: function( event ) { 33322 return jQuery.nodeName( event.target, "a" ); 33323 } 33324 }, 33325 33326 beforeunload: { 33327 postDispatch: function( event ) { 33328
33329 // Support: Firefox 20+ 33330 // Firefox doesn't alert if the returnValue field is not set. 33331 if ( event.result !== undefined && event.originalEvent ) { 33332 event.originalEvent.returnValue = event.result; 33333 } 33334 } 33335 } 33336 }, 33337 33338 simulate: function( type, elem, event, bubble ) { 33339 // Piggyback on a donor event to simulate a different one. 33340 // Fake originalEvent to avoid donor's stopPropagation, but if the 33341 // simulated event prevents default then we do the same on the donor. 33342 var e = jQuery.extend( 33343 new jQuery.Event(), 33344 event, 33345 { 33346 type: type, 33347 isSimulated: true, 33348 originalEvent: {} 33349 } 33350 ); 33351 if ( bubble ) { 33352 jQuery.event.trigger( e, null, elem ); 33353 } else { 33354 jQuery.event.dispatch.call( elem, e ); 33355 } 33356 if ( e.isDefaultPrevented() ) { 33357 event.preventDefault(); 33358 } 33359 } 33360}; 33361 33362jQuery.removeEvent = function( elem, type, handle ) { 33363 if ( elem.removeEventListener ) { 33364 elem.removeEventListener( type, handle, false ); 33365 } 33366}; 33367 33368jQuery.Event = function( src, props ) { 33369 // Allow instantiation without the 'new' keyword 33370 if ( !(this instanceof jQuery.Event) ) { 33371 return new jQuery.Event( src, props ); 33372 } 33373 33374 // Event object 33375 if ( src && src.type ) { 33376 this.originalEvent = src; 33377 this.type = src.type; 33378 33379 // Events bubbling up the document may have been marked as prevented 33380 // by a handler lower down the tree; reflect the correct value. 33381 this.isDefaultPrevented = src.defaultPrevented || 33382 src.defaultPrevented === undefined && 33383 // Support: Android<4.0 33384 src.returnValue === false ? 33385 returnTrue : 33386 returnFalse; 33387 33388 // Event type 33389 } else { 33390 this.type = src; 33391 } 33392 33393 // Put explicitly provided properties onto the event object 33394 if ( props ) { 33395 jQuery.extend( this, props ); 33396 } 33397 33398 // Create a timestamp if incoming event doesn't have one 33399 this.timeStamp = src && src.timeStamp || jQuery.now(); 33400 33401 // Mark it as fixed 33402 this[ jQuery.expando ] = true; 33403}; 33404 33405// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 33406// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 33407jQuery.Event.prototype = { 33408 isDefaultPrevented: returnFalse, 33409 isPropagationStopped: returnFalse, 33410 isImmediatePropagationStopped: returnFalse, 33411 33412 preventDefault: function() { 33413 var e = this.originalEvent; 33414 33415 this.isDefaultPrevented = returnTrue; 33416 33417 if ( e && e.preventDefault ) { 33418 e.preventDefault(); 33419 } 33420 }, 33421 stopPropagation: function() { 33422 var e = this.originalEvent; 33423 33424 this.isPropagationStopped = returnTrue; 33425 33426 if ( e && e.stopPropagation ) { 33427 e.stopPropagation(); 33428 } 33429 }, 33430 stopImmediatePropagation: function() { 33431 var e = this.originalEvent; 33432 33433 this.isImmediatePropagationStopped = returnTrue; 33434 33435 if ( e && e.stopImmediatePropagation ) { 33436 e.stopImmediatePropagation(); 33437 } 33438 33439 this.stopPropagation(); 33440 } 33441}; 33442 33443// Create mouseenter/leave events using mouseover/out and event-time checks 33444// Support: Chrome 15+ 33445jQuery.each({ 33446 mouseenter: "mouseover", 33447 mouseleave: "mouseout", 33448 pointerenter: "pointerover", 33449 pointerleave: "pointerout" 33450}, function( orig, fix ) { 33451 jQuery.event.special[ orig ] = { 33452 delegateType: fix, 33453 bindType: fix, 33454 33455 handle: function( event ) { 33456 var ret, 33457 target = this, 33458 related = event.relatedTarget, 33459 handleObj = event.handleObj; 33460 33461 // For mousenter/leave call the handler if related is outside the target. 33462 // NB: No relatedTarget if the mouse left/entered the browser window 33463 if ( !related || (related !== target && !jQuery.contains( target, related )) ) { 33464 event.type = handleObj.origType; 33465 ret = handleObj.handler.apply( this, arguments ); 33466 event.type = fix; 33467 } 33468 return ret; 33469 } 33470 }; 33471}); 33472 33473// Support: Firefox, Chrome, Safari 33474// Create "bubbling" focus and blur events 33475if ( !support.focusinBubbles ) { 33476 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { 33477 33478 // Attach a single capturing handler on the document while someone wants focusin/focusout 33479 var handler = function( event ) { 33480 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); 33481 }; 33482 33483 jQuery.event.special[ fix ] = { 33484 setup: function() { 33485 var doc = this.ownerDocument || this, 33486 attaches = data_priv.access( doc, fix ); 33487 33488 if ( !attaches ) { 33489 doc.addEventListener( orig, handler, true ); 33490 } 33491 data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); 33492 }, 33493 teardown: function() { 33494 var doc = this.ownerDocument || this, 33495 attaches = data_priv.access( doc, fix ) - 1; 33496 33497 if ( !attaches ) { 33498 doc.removeEventListener( orig, handler, true ); 33499 data_priv.remove( doc, fix ); 33500 33501 } else { 33502 data_priv.access( doc, fix, attaches ); 33503 } 33504 } 33505 }; 33506 }); 33507} 33508 33509jQuery.fn.extend({ 33510 33511 on: function( types, selector, data, fn, /*INTERNAL*/ one ) { 33512 var origFn, type; 33513 33514 // Types can be a map of types/handlers 33515 if ( typeof types === "object" ) { 33516 // ( types-Object, selector, data ) 33517 if ( typeof selector !== "string" ) { 33518 // ( types-Object, data ) 33519 data = data || selector; 33520 selector = undefined; 33521 } 33522 for ( type in types ) { 33523 this.on( type, selector, data, types[ type ], one ); 33524 } 33525 return this; 33526 } 33527 33528 if ( data == null && fn == null ) { 33529 // ( types, fn ) 33530 fn = selector; 33531 data = selector = undefined; 33532 } else if ( fn == null ) { 33533 if ( typeof selector === "string" ) { 33534 // ( types, selector, fn ) 33535 fn = data; 33536 data = undefined; 33537 } else { 33538 // ( types, data, fn ) 33539 fn = data; 33540 data = selector; 33541 selector = undefined; 33542 } 33543 } 33544 if ( fn === false ) { 33545 fn = returnFalse; 33546 } else if ( !fn ) { 33547 return this; 33548 } 33549 33550 if ( one === 1 ) { 33551 origFn = fn; 33552 fn = function( event ) { 33553 // Can use an empty set, since event contains the info 33554 jQuery().off( event ); 33555 return origFn.apply( this, arguments ); 33556 }; 33557 // Use same guid so caller can remove using origFn 33558 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 33559 } 33560 return this.each( function() { 33561 jQuery.event.add( this, types, fn, data, selector ); 33562 }); 33563 }, 33564 one: function( types, selector, data, fn ) { 33565 return this.on( types, selector, data, fn, 1 ); 33566 }, 33567 off: function( types, selector, fn ) { 33568 var handleObj, type; 33569 if ( types && types.preventDefault && types.handleObj ) { 33570 // ( event ) dispatched jQuery.Event 33571 handleObj = types.handleObj; 33572 jQuery( types.delegateTarget ).off( 33573 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, 33574 handleObj.selector, 33575 handleObj.handler 33576 ); 33577 return this; 33578 } 33579 if ( typeof types === "object" ) { 33580 // ( types-object [, selector] ) 33581 for ( type in types ) { 33582 this.off( type, selector, types[ type ] ); 33583 } 33584 return this; 33585 } 33586 if ( selector === false || typeof selector === "function" ) { 33587 // ( types [, fn] ) 33588 fn = selector; 33589 selector = undefined; 33590 } 33591 if ( fn === false ) { 33592 fn = returnFalse; 33593 } 33594 return this.each(function() { 33595 jQuery.event.remove( this, types, fn, selector ); 33596 }); 33597 }, 33598 33599 trigger: function( type, data ) { 33600 return this.each(function() { 33601 jQuery.event.trigger( type, data, this ); 33602 }); 33603 }, 33604 triggerHandler: function( type, data ) { 33605 var elem = this[0]; 33606 if ( elem ) { 33607 return jQuery.event.trigger( type, data, elem, true ); 33608 } 33609 } 33610}); 33611 33612 33613var 33614 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, 33615 rtagName = /<([\w:]+)/,
33616 rhtml = /<|&#?\w+;/, 33617 rnoInnerhtml = /<(?:script|style|link)/i, 33618 // checked="checked" or checked 33619 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 33620 rscriptType = /^$|\/(?:java|ecma)script/i, 33621 rscriptTypeMasked = /^true\/(.*)/, 33622 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, 33623 33624 // We have to close these tags to support XHTML (#13200) 33625 wrapMap = { 33626 33627 // Support: IE9 33628 option: [ 1, "<select multiple='multiple'>", "</select>" ], 33629 33630 thead: [ 1, "<table>", "</table>" ], 33631 col: [ 2, "<table><colgroup>", "</colgroup></table>" ], 33632 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 33633 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 33634 33635 _default: [ 0, "", "" ] 33636 }; 33637 33638// Support: IE9 33639wrapMap.optgroup = wrapMap.option; 33640 33641wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 33642wrapMap.th = wrapMap.td; 33643 33644// Support: 1.x compatibility 33645// Manipulating tables requires a tbody 33646function manipulationTarget( elem, content ) { 33647 return jQuery.nodeName( elem, "table" ) && 33648 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? 33649 33650 elem.getElementsByTagName("tbody")[0] || 33651 elem.appendChild( elem.ownerDocument.createElement("tbody") ) : 33652 elem; 33653} 33654 33655// Replace/restore the type attribute of script elements for safe DOM manipulation 33656function disableScript( elem ) { 33657 elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; 33658 return elem; 33659} 33660function restoreScript( elem ) { 33661 var match = rscriptTypeMasked.exec( elem.type ); 33662 33663 if ( match ) { 33664 elem.type = match[ 1 ]; 33665 } else { 33666 elem.removeAttribute("type"); 33667 } 33668 33669 return elem; 33670} 33671 33672// Mark scripts as having already been evaluated 33673function setGlobalEval( elems, refElements ) { 33674 var i = 0, 33675 l = elems.length; 33676 33677 for ( ; i < l; i++ ) { 33678 data_priv.set( 33679 elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) 33680 ); 33681 } 33682} 33683 33684function cloneCopyEvent( src, dest ) { 33685 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; 33686 33687 if ( dest.nodeType !== 1 ) { 33688 return; 33689 } 33690 33691 // 1. Copy private data: events, handlers, etc. 33692 if ( data_priv.hasData( src ) ) { 33693 pdataOld = data_priv.access( src ); 33694 pdataCur = data_priv.set( dest, pdataOld ); 33695 events = pdataOld.events; 33696 33697 if ( events ) { 33698 delete pdataCur.handle; 33699 pdataCur.events = {}; 33700 33701 for ( type in events ) { 33702 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 33703 jQuery.event.add( dest, type, events[ type ][ i ] ); 33704 } 33705 } 33706 } 33707 } 33708 33709 // 2. Copy user data 33710 if ( data_user.hasData( src ) ) { 33711 udataOld = data_user.access( src ); 33712 udataCur = jQuery.extend( {}, udataOld ); 33713 33714 data_user.set( dest, udataCur ); 33715 } 33716} 33717 33718function getAll( context, tag ) { 33719 var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : 33720 context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : 33721 []; 33722 33723 return tag === undefined || tag && jQuery.nodeName( context, tag ) ? 33724 jQuery.merge( [ context ], ret ) : 33725 ret; 33726} 33727 33728// Fix IE bugs, see support tests 33729function fixInput( src, dest ) { 33730 var nodeName = dest.nodeName.toLowerCase(); 33731 33732 // Fails to persist the checked state of a cloned checkbox or radio button. 33733 if ( nodeName === "input" && rcheckableType.test( src.type ) ) { 33734 dest.checked = src.checked; 33735 33736 // Fails to return the selected option to the default selected state when cloning options 33737 } else if ( nodeName === "input" || nodeName === "textarea" ) { 33738 dest.defaultValue = src.defaultValue; 33739 } 33740} 33741 33742jQuery.extend({ 33743 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 33744 var i, l, srcElements, destElements, 33745 clone = elem.cloneNode( true ), 33746 inPage = jQuery.contains( elem.ownerDocument, elem ); 33747 33748 // Fix IE cloning issues 33749 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && 33750 !jQuery.isXMLDoc( elem ) ) { 33751 33752 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 33753 destElements = getAll( clone ); 33754 srcElements = getAll( elem ); 33755 33756 for ( i = 0, l = srcElements.length; i < l; i++ ) { 33757 fixInput( srcElements[ i ], destElements[ i ] ); 33758 } 33759 } 33760 33761 // Copy the events from the original to the clone 33762 if ( dataAndEvents ) { 33763 if ( deepDataAndEvents ) { 33764 srcElements = srcElements || getAll( elem ); 33765 destElements = destElements || getAll( clone ); 33766 33767 for ( i = 0, l = srcElements.length; i < l; i++ ) { 33768 cloneCopyEvent( srcElements[ i ], destElements[ i ] ); 33769 } 33770 } else { 33771 cloneCopyEvent( elem, clone ); 33772 } 33773 } 33774 33775 // Preserve script evaluation history 33776 destElements = getAll( clone, "script" ); 33777 if ( destElements.length > 0 ) { 33778 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); 33779 } 33780 33781 // Return the cloned set 33782 return clone; 33783 }, 33784 33785 buildFragment: function( elems, context, scripts, selection ) { 33786 var elem, tmp, tag, wrap, contains, j, 33787 fragment = context.createDocumentFragment(), 33788 nodes = [], 33789 i = 0, 33790 l = elems.length; 33791 33792 for ( ; i < l; i++ ) { 33793 elem = elems[ i ]; 33794 33795 if ( elem || elem === 0 ) { 33796 33797 // Add nodes directly 33798 if ( jQuery.type( elem ) === "object" ) {
vendor: 5,747 bytes, lines 33799-34014
33799 // Support: QtWebKit, PhantomJS 33800 // push.apply(_, arraylike) throws on ancient WebKit 33801 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); 33802 33803 // Convert non-html into a text node 33804 } else if ( !rhtml.test( elem ) ) { 33805 nodes.push( context.createTextNode( elem ) ); 33806 33807 // Convert html into DOM nodes 33808 } else { 33809 tmp = tmp || fragment.appendChild( context.createElement("div") ); 33810 33811 // Deserialize a standard representation 33812 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); 33813 wrap = wrapMap[ tag ] || wrapMap._default; 33814 tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ]; 33815 33816 // Descend through wrappers to the right content 33817 j = wrap[ 0 ]; 33818 while ( j-- ) { 33819 tmp = tmp.lastChild; 33820 } 33821 33822 // Support: QtWebKit, PhantomJS 33823 // push.apply(_, arraylike) throws on ancient WebKit 33824 jQuery.merge( nodes, tmp.childNodes ); 33825 33826 // Remember the top-level container 33827 tmp = fragment.firstChild; 33828 33829 // Ensure the created nodes are orphaned (#12392) 33830 tmp.textContent = ""; 33831 } 33832 } 33833 } 33834 33835 // Remove wrapper from fragment 33836 fragment.textContent = ""; 33837 33838 i = 0; 33839 while ( (elem = nodes[ i++ ]) ) { 33840 33841 // #4087 - If origin and destination elements are the same, and this is 33842 // that element, do not do anything 33843 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { 33844 continue; 33845 } 33846 33847 contains = jQuery.contains( elem.ownerDocument, elem ); 33848 33849 // Append to fragment 33850 tmp = getAll( fragment.appendChild( elem ), "script" ); 33851 33852 // Preserve script evaluation history 33853 if ( contains ) { 33854 setGlobalEval( tmp ); 33855 } 33856 33857 // Capture executables 33858 if ( scripts ) { 33859 j = 0; 33860 while ( (elem = tmp[ j++ ]) ) { 33861 if ( rscriptType.test( elem.type || "" ) ) { 33862 scripts.push( elem ); 33863 } 33864 } 33865 } 33866 } 33867 33868 return fragment; 33869 }, 33870 33871 cleanData: function( elems ) { 33872 var data, elem, type, key, 33873 special = jQuery.event.special, 33874 i = 0; 33875 33876 for ( ; (elem = elems[ i ]) !== undefined; i++ ) { 33877 if ( jQuery.acceptData( elem ) ) { 33878 key = elem[ data_priv.expando ]; 33879 33880 if ( key && (data = data_priv.cache[ key ]) ) { 33881 if ( data.events ) { 33882 for ( type in data.events ) { 33883 if ( special[ type ] ) { 33884 jQuery.event.remove( elem, type ); 33885 33886 // This is a shortcut to avoid jQuery.event.remove's overhead 33887 } else { 33888 jQuery.removeEvent( elem, type, data.handle ); 33889 } 33890 } 33891 } 33892 if ( data_priv.cache[ key ] ) { 33893 // Discard any remaining `private` data 33894 delete data_priv.cache[ key ]; 33895 } 33896 } 33897 } 33898 // Discard any remaining `user` data 33899 delete data_user.cache[ elem[ data_user.expando ] ]; 33900 } 33901 } 33902}); 33903 33904jQuery.fn.extend({ 33905 text: function( value ) { 33906 return access( this, function( value ) { 33907 return value === undefined ? 33908 jQuery.text( this ) : 33909 this.empty().each(function() { 33910 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 33911 this.textContent = value; 33912 } 33913 }); 33914 }, null, value, arguments.length ); 33915 }, 33916 33917 append: function() { 33918 return this.domManip( arguments, function( elem ) { 33919 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 33920 var target = manipulationTarget( this, elem ); 33921 target.appendChild( elem ); 33922 } 33923 }); 33924 }, 33925 33926 prepend: function() { 33927 return this.domManip( arguments, function( elem ) { 33928 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 33929 var target = manipulationTarget( this, elem ); 33930 target.insertBefore( elem, target.firstChild ); 33931 } 33932 }); 33933 }, 33934 33935 before: function() { 33936 return this.domManip( arguments, function( elem ) { 33937 if ( this.parentNode ) { 33938 this.parentNode.insertBefore( elem, this ); 33939 } 33940 }); 33941 }, 33942 33943 after: function() { 33944 return this.domManip( arguments, function( elem ) { 33945 if ( this.parentNode ) { 33946 this.parentNode.insertBefore( elem, this.nextSibling ); 33947 } 33948 }); 33949 }, 33950 33951 remove: function( selector, keepData /* Internal Use Only */ ) { 33952 var elem, 33953 elems = selector ? jQuery.filter( selector, this ) : this, 33954 i = 0; 33955 33956 for ( ; (elem = elems[i]) != null; i++ ) { 33957 if ( !keepData && elem.nodeType === 1 ) { 33958 jQuery.cleanData( getAll( elem ) ); 33959 } 33960 33961 if ( elem.parentNode ) { 33962 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { 33963 setGlobalEval( getAll( elem, "script" ) ); 33964 } 33965 elem.parentNode.removeChild( elem ); 33966 } 33967 } 33968 33969 return this; 33970 }, 33971 33972 empty: function() { 33973 var elem, 33974 i = 0; 33975 33976 for ( ; (elem = this[i]) != null; i++ ) { 33977 if ( elem.nodeType === 1 ) { 33978 33979 // Prevent memory leaks 33980 jQuery.cleanData( getAll( elem, false ) ); 33981 33982 // Remove any remaining nodes 33983 elem.textContent = ""; 33984 } 33985 } 33986 33987 return this; 33988 }, 33989 33990 clone: function( dataAndEvents, deepDataAndEvents ) { 33991 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 33992 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 33993 33994 return this.map(function() { 33995 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 33996 }); 33997 }, 33998 33999 html: function( value ) { 34000 return access( this, function( value ) { 34001 var elem = this[ 0 ] || {}, 34002 i = 0, 34003 l = this.length; 34004 34005 if ( value === undefined && elem.nodeType === 1 ) { 34006 return elem.innerHTML; 34007 } 34008 34009 // See if we can take a shortcut and just use innerHTML 34010 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 34011 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { 34012 34013 value = value.replace( rxhtmlTag, "<$1></$2>" ); 34014
34015 try { 34016 for ( ; i < l; i++ ) { 34017 elem = this[ i ] || {}; 34018 34019 // Remove element nodes and prevent memory leaks 34020 if ( elem.nodeType === 1 ) { 34021 jQuery.cleanData( getAll( elem, false ) ); 34022 elem.innerHTML = value; 34023 } 34024 } 34025 34026 elem = 0; 34027 34028 // If using innerHTML throws an exception, use the fallback method 34029 } catch( e ) {} 34030 } 34031 34032 if ( elem ) { 34033 this.empty().append( value ); 34034 } 34035 }, null, value, arguments.length ); 34036 }, 34037 34038 replaceWith: function() { 34039 var arg = arguments[ 0 ]; 34040 34041 // Make the changes, replacing each context element with the new content 34042 this.domManip( arguments, function( elem ) { 34043 arg = this.parentNode; 34044 34045 jQuery.cleanData( getAll( this ) ); 34046 34047 if ( arg ) { 34048 arg.replaceChild( elem, this ); 34049 } 34050 }); 34051 34052 // Force removal if there was no new content (e.g., from empty arguments) 34053 return arg && (arg.length || arg.nodeType) ? this : this.remove(); 34054 }, 34055 34056 detach: function( selector ) { 34057 return this.remove( selector, true ); 34058 }, 34059 34060 domManip: function( args, callback ) { 34061 34062 // Flatten any nested arrays 34063 args = concat.apply( [], args ); 34064 34065 var fragment, first, scripts, hasScripts, node, doc, 34066 i = 0, 34067 l = this.length, 34068 set = this, 34069 iNoClone = l - 1, 34070 value = args[ 0 ], 34071 isFunction = jQuery.isFunction( value ); 34072 34073 // We can't cloneNode fragments that contain checked, in WebKit 34074 if ( isFunction || 34075 ( l > 1 && typeof value === "string" && 34076 !support.checkClone && rchecked.test( value ) ) ) { 34077 return this.each(function( index ) { 34078 var self = set.eq( index ); 34079 if ( isFunction ) { 34080 args[ 0 ] = value.call( this, index, self.html() ); 34081 } 34082 self.domManip( args, callback ); 34083 }); 34084 } 34085 34086 if ( l ) { 34087 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); 34088 first = fragment.firstChild; 34089 34090 if ( fragment.childNodes.length === 1 ) { 34091 fragment = first; 34092 } 34093 34094 if ( first ) { 34095 scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); 34096 hasScripts = scripts.length; 34097 34098 // Use the original fragment for the last item instead of the first because it can end up 34099 // being emptied incorrectly in certain situations (#8070). 34100 for ( ; i < l; i++ ) { 34101 node = fragment; 34102 34103 if ( i !== iNoClone ) { 34104 node = jQuery.clone( node, true, true ); 34105 34106 // Keep references to cloned scripts for later restoration 34107 if ( hasScripts ) { 34108 // Support: QtWebKit 34109 // jQuery.merge because push.apply(_, arraylike) throws 34110 jQuery.merge( scripts, getAll( node, "script" ) ); 34111 } 34112 } 34113 34114 callback.call( this[ i ], node, i ); 34115 } 34116 34117 if ( hasScripts ) { 34118 doc = scripts[ scripts.length - 1 ].ownerDocument; 34119 34120 // Reenable scripts 34121 jQuery.map( scripts, restoreScript ); 34122 34123 // Evaluate executable scripts on first document insertion 34124 for ( i = 0; i < hasScripts; i++ ) { 34125 node = scripts[ i ]; 34126 if ( rscriptType.test( node.type || "" ) && 34127 !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { 34128 34129 if ( node.src ) { 34130 // Optional AJAX dependency, but won't run scripts if not present 34131 if ( jQuery._evalUrl ) { 34132 jQuery._evalUrl( node.src ); 34133 } 34134 } else { 34135 jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); 34136 } 34137 } 34138 } 34139 } 34140 } 34141 } 34142 34143 return this; 34144 } 34145}); 34146 34147jQuery.each({ 34148 appendTo: "append", 34149 prependTo: "prepend", 34150 insertBefore: "before", 34151 insertAfter: "after", 34152 replaceAll: "replaceWith" 34153}, function( name, original ) { 34154 jQuery.fn[ name ] = function( selector ) { 34155 var elems, 34156 ret = [], 34157 insert = jQuery( selector ), 34158 last = insert.length - 1, 34159 i = 0; 34160 34161 for ( ; i <= last; i++ ) { 34162 elems = i === last ? this : this.clone( true ); 34163 jQuery( insert[ i ] )[ original ]( elems ); 34164 34165 // Support: QtWebKit 34166 // .get() because push.apply(_, arraylike) throws 34167 push.apply( ret, elems.get() ); 34168 } 34169 34170 return this.pushStack( ret ); 34171 }; 34172}); 34173 34174 34175var iframe, 34176 elemdisplay = {}; 34177 34178/** 34179 * Retrieve the actual display of a element 34180 * @param {String} name nodeName of the element 34181 * @param {Object} doc Document object 34182 */ 34183// Called only from within defaultDisplay 34184function actualDisplay( name, doc ) { 34185 var style, 34186 elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), 34187 34188 // getDefaultComputedStyle might be reliably used only on attached element 34189 display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? 34190 34191 // Use of this method is a temporary fix (more like optimization) until something better comes along, 34192 // since it was removed from specification and supported only in FF 34193 style.display : jQuery.css( elem[ 0 ], "display" ); 34194 34195 // We don't have any data stored on the element, 34196 // so use "detach" method as fast way to get rid of the element 34197 elem.detach(); 34198
34199 return display; 34200} 34201 34202/** 34203 * Try to determine the default display value of an element 34204 * @param {String} nodeName 34205 */ 34206function defaultDisplay( nodeName ) { 34207 var doc = document, 34208 display = elemdisplay[ nodeName ]; 34209 34210 if ( !display ) { 34211 display = actualDisplay( nodeName, doc ); 34212 34213 // If the simple way fails, read from inside an iframe 34214 if ( display === "none" || !display ) { 34215 34216 // Use the already-created iframe if possible 34217 iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement ); 34218 34219 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse 34220 doc = iframe[ 0 ].contentDocument; 34221 34222 // Support: IE 34223 doc.write(); 34224 doc.close(); 34225 34226 display = actualDisplay( nodeName, doc ); 34227 iframe.detach(); 34228 } 34229 34230 // Store the correct default display 34231 elemdisplay[ nodeName ] = display; 34232 } 34233 34234 return display; 34235} 34236var rmargin = (/^margin/); 34237 34238var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); 34239 34240var getStyles = function( elem ) { 34241 // Support: IE<=11+, Firefox<=30+ (#15098, #14150) 34242 // IE throws on elements created in popups 34243 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" 34244 if ( elem.ownerDocument.defaultView.opener ) { 34245 return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); 34246 } 34247 34248 return window.getComputedStyle( elem, null ); 34249 }; 34250 34251 34252 34253function curCSS( elem, name, computed ) { 34254 var width, minWidth, maxWidth, ret, 34255 style = elem.style; 34256 34257 computed = computed || getStyles( elem ); 34258 34259 // Support: IE9 34260 // getPropertyValue is only needed for .css('filter') (#12537) 34261 if ( computed ) { 34262 ret = computed.getPropertyValue( name ) || computed[ name ]; 34263 } 34264 34265 if ( computed ) { 34266 34267 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { 34268 ret = jQuery.style( elem, name ); 34269 } 34270 34271 // Support: iOS < 6 34272 // A tribute to the "awesome hack by Dean Edwards" 34273 // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels 34274 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values 34275 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { 34276 34277 // Remember the original values 34278 width = style.width; 34279 minWidth = style.minWidth; 34280 maxWidth = style.maxWidth; 34281 34282 // Put in the new values to get a computed value out 34283 style.minWidth = style.maxWidth = style.width = ret; 34284 ret = computed.width; 34285 34286 // Revert the changed values 34287 style.width = width; 34288 style.minWidth = minWidth; 34289 style.maxWidth = maxWidth; 34290 } 34291 } 34292 34293 return ret !== undefined ? 34294 // Support: IE 34295 // IE returns zIndex value as an integer. 34296 ret + "" : 34297 ret; 34298} 34299 34300 34301function addGetHookIf( conditionFn, hookFn ) { 34302 // Define the hook, we'll check on the first run if it's really needed. 34303 return { 34304 get: function() { 34305 if ( conditionFn() ) { 34306 // Hook not needed (or it's not possible to use it due 34307 // to missing dependency), remove it. 34308 delete this.get; 34309 return; 34310 } 34311 34312 // Hook needed; redefine it so that the support test is not executed again. 34313 return (this.get = hookFn).apply( this, arguments ); 34314 } 34315 }; 34316} 34317 34318 34319(function() { 34320 var pixelPositionVal, boxSizingReliableVal, 34321 docElem = document.documentElement, 34322 container = document.createElement( "div" ), 34323 div = document.createElement( "div" ); 34324 34325 if ( !div.style ) { 34326 return; 34327 } 34328 34329 // Support: IE9-11+ 34330 // Style of cloned element affects source element cloned (#8908) 34331 div.style.backgroundClip = "content-box"; 34332 div.cloneNode( true ).style.backgroundClip = ""; 34333 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 34334 34335 container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" + 34336 "position:absolute"; 34337 container.appendChild( div ); 34338 34339 // Executing both pixelPosition & boxSizingReliable tests require only one layout 34340 // so they're executed at the same time to save the second computation. 34341 function computePixelPositionAndBoxSizingReliable() { 34342 div.style.cssText =
34343 // Support: Firefox<29, Android 2.3 34344 // Vendor-prefix box-sizing 34345 "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + 34346 "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + 34347 "border:1px;padding:1px;width:4px;position:absolute"; 34348 div.innerHTML = ""; 34349 docElem.appendChild( container ); 34350 34351 var divStyle = window.getComputedStyle( div, null ); 34352 pixelPositionVal = divStyle.top !== "1%"; 34353 boxSizingReliableVal = divStyle.width === "4px"; 34354 34355 docElem.removeChild( container ); 34356 } 34357 34358 // Support: node.js jsdom 34359 // Don't assume that getComputedStyle is a property of the global object 34360 if ( window.getComputedStyle ) { 34361 jQuery.extend( support, { 34362 pixelPosition: function() { 34363 34364 // This test is executed only once but we still do memoizing 34365 // since we can use the boxSizingReliable pre-computing. 34366 // No need to check if the test was already performed, though. 34367 computePixelPositionAndBoxSizingReliable(); 34368 return pixelPositionVal; 34369 }, 34370 boxSizingReliable: function() { 34371 if ( boxSizingReliableVal == null ) { 34372 computePixelPositionAndBoxSizingReliable(); 34373 } 34374 return boxSizingReliableVal; 34375 }, 34376 reliableMarginRight: function() { 34377 34378 // Support: Android 2.3 34379 // Check if div with explicit width and no margin-right incorrectly 34380 // gets computed margin-right based on width of container. (#3333) 34381 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 34382 // This support function is only executed once so no memoizing is needed. 34383 var ret, 34384 marginDiv = div.appendChild( document.createElement( "div" ) ); 34385 34386 // Reset CSS: box-sizing; display; margin; border; padding 34387 marginDiv.style.cssText = div.style.cssText = 34388 // Support: Firefox<29, Android 2.3 34389 // Vendor-prefix box-sizing 34390 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + 34391 "box-sizing:content-box;display:block;margin:0;border:0;padding:0"; 34392 marginDiv.style.marginRight = marginDiv.style.width = "0"; 34393 div.style.width = "1px"; 34394 docElem.appendChild( container ); 34395 34396 ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight ); 34397 34398 docElem.removeChild( container ); 34399 div.removeChild( marginDiv ); 34400 34401 return ret; 34402 } 34403 }); 34404 } 34405})(); 34406 34407 34408// A method for quickly swapping in/out CSS properties to get correct calculations. 34409jQuery.swap = function( elem, options, callback, args ) { 34410 var ret, name, 34411 old = {}; 34412 34413 // Remember the old values, and insert the new ones 34414 for ( name in options ) { 34415 old[ name ] = elem.style[ name ]; 34416 elem.style[ name ] = options[ name ]; 34417 } 34418 34419 ret = callback.apply( elem, args || [] ); 34420 34421 // Revert the old values 34422 for ( name in options ) { 34423 elem.style[ name ] = old[ name ]; 34424 } 34425 34426 return ret; 34427}; 34428 34429 34430var 34431 // Swappable if display is none or starts with table except "table", "table-cell", or "table-caption" 34432 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 34433 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 34434 rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), 34435 rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ), 34436 34437 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 34438 cssNormalTransform = { 34439 letterSpacing: "0", 34440 fontWeight: "400" 34441 }, 34442 34443 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; 34444 34445// Return a css property mapped to a potentially vendor prefixed property 34446function vendorPropName( style, name ) { 34447 34448 // Shortcut for names that are not vendor prefixed 34449 if ( name in style ) { 34450 return name; 34451 } 34452 34453 // Check for vendor prefixed names 34454 var capName = name[0].toUpperCase() + name.slice(1), 34455 origName = name, 34456 i = cssPrefixes.length; 34457 34458 while ( i-- ) { 34459 name = cssPrefixes[ i ] + capName; 34460 if ( name in style ) { 34461 return name; 34462 } 34463 } 34464 34465 return origName; 34466} 34467 34468function setPositiveNumber( elem, value, subtract ) { 34469 var matches = rnumsplit.exec( value ); 34470 return matches ? 34471 // Guard against undefined "subtract", e.g., when used as in cssHooks 34472 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : 34473 value; 34474} 34475 34476function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { 34477 var i = extra === ( isBorderBox ? "border" : "content" ) ? 34478 // If we already have the right measurement, avoid augmentation 34479 4 : 34480 // Otherwise initialize for horizontal or vertical properties 34481 name === "width" ? 1 : 0, 34482 34483 val = 0; 34484 34485 for ( ; i < 4; i += 2 ) { 34486 // Both box models exclude margin, so add it if we want it 34487 if ( extra === "margin" ) { 34488 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); 34489 } 34490 34491 if ( isBorderBox ) { 34492 // border-box includes padding, so remove it if we want content 34493 if ( extra === "content" ) { 34494 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 34495 } 34496 34497 // At this point, extra isn't border nor margin, so remove border 34498 if ( extra !== "margin" ) { 34499 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 34500 } 34501 } else { 34502 // At this point, extra isn't content, so add padding 34503 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 34504 34505 // At this point, extra isn't content nor padding, so add border 34506 if ( extra !== "padding" ) { 34507 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 34508 } 34509 } 34510 } 34511 34512 return val; 34513} 34514 34515function getWidthOrHeight( elem, name, extra ) { 34516 34517 // Start with offset property, which is equivalent to the border-box value 34518 var valueIsBorderBox = true, 34519 val = name === "width" ? elem.offsetWidth : elem.offsetHeight, 34520 styles = getStyles( elem ), 34521 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; 34522 34523 // Some non-html elements return undefined for offsetWidth, so check for null/undefined 34524 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 34525 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 34526 if ( val <= 0 || val == null ) { 34527 // Fall back to computed then uncomputed css if necessary 34528 val = curCSS( elem, name, styles ); 34529 if ( val < 0 || val == null ) { 34530 val = elem.style[ name ]; 34531 } 34532 34533 // Computed unit is not pixels. Stop here and return. 34534 if ( rnumnonpx.test(val) ) { 34535 return val; 34536 } 34537 34538 // Check for style in case a browser which returns unreliable values 34539 // for getComputedStyle silently falls back to the reliable elem.style 34540 valueIsBorderBox = isBorderBox && 34541 ( support.boxSizingReliable() || val === elem.style[ name ] ); 34542 34543 // Normalize "", auto, and prepare for extra 34544 val = parseFloat( val ) || 0; 34545 } 34546 34547 // Use the active box-sizing model to add/subtract irrelevant styles 34548 return ( val + 34549 augmentWidthOrHeight( 34550 elem, 34551 name, 34552 extra || ( isBorderBox ? "border" : "content" ), 34553 valueIsBorderBox, 34554 styles 34555 ) 34556 ) + "px"; 34557} 34558 34559function showHide( elements, show ) { 34560 var display, elem, hidden, 34561 values = [], 34562 index = 0, 34563 length = elements.length; 34564 34565 for ( ; index < length; index++ ) { 34566 elem = elements[ index ]; 34567 if ( !elem.style ) { 34568 continue; 34569 } 34570 34571 values[ index ] = data_priv.get( elem, "olddisplay" ); 34572 display = elem.style.display; 34573 if ( show ) { 34574 // Reset the inline display of this element to learn if it is 34575 // being hidden by cascaded rules or not 34576 if ( !values[ index ] && display === "none" ) { 34577 elem.style.display = ""; 34578 } 34579 34580 // Set elements which have been overridden with display: none 34581 // in a stylesheet to whatever the default browser style is 34582 // for such an element 34583 if ( elem.style.display === "" && isHidden( elem ) ) { 34584 values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) ); 34585 } 34586 } else { 34587 hidden = isHidden( elem ); 34588 34589 if ( display !== "none" || !hidden ) { 34590 data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "dis
34590play" ) ); 34591 } 34592 } 34593 } 34594 34595 // Set the display of most of the elements in a second loop 34596 // to avoid the constant reflow 34597 for ( index = 0; index < length; index++ ) { 34598 elem = elements[ index ]; 34599 if ( !elem.style ) { 34600 continue; 34601 } 34602 if ( !show || elem.style.display === "none" || elem.style.display === "" ) { 34603 elem.style.display = show ? values[ index ] || "" : "none"; 34604 } 34605 } 34606 34607 return elements; 34608} 34609 34610jQuery.extend({ 34611 34612 // Add in style property hooks for overriding the default 34613 // behavior of getting and setting a style property 34614 cssHooks: { 34615 opacity: { 34616 get: function( elem, computed ) { 34617 if ( computed ) { 34618 34619 // We should always get a number back from opacity 34620 var ret = curCSS( elem, "opacity" ); 34621 return ret === "" ? "1" : ret; 34622 } 34623 } 34624 } 34625 }, 34626 34627 // Don't automatically add "px" to these possibly-unitless properties 34628 cssNumber: { 34629 "columnCount": true, 34630 "fillOpacity": true, 34631 "flexGrow": true, 34632 "flexShrink": true, 34633 "fontWeight": true, 34634 "lineHeight": true, 34635 "opacity": true, 34636 "order": true, 34637 "orphans": true, 34638 "widows": true, 34639 "zIndex": true, 34640 "zoom": true 34641 }, 34642 34643 // Add in properties whose names you wish to fix before 34644 // setting or getting the value 34645 cssProps: { 34646 "float": "cssFloat" 34647 }, 34648 34649 // Get and set the style property on a DOM Node 34650 style: function( elem, name, value, extra ) { 34651 34652 // Don't set styles on text and comment nodes 34653 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 34654 return; 34655 } 34656 34657 // Make sure that we're working with the right name 34658 var ret, type, hooks, 34659 origName = jQuery.camelCase( name ), 34660 style = elem.style; 34661 34662 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); 34663 34664 // Gets hook for the prefixed version, then unprefixed version 34665 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 34666 34667 // Check if we're setting a value 34668 if ( value !== undefined ) { 34669 type = typeof value; 34670 34671 // Convert "+=" or "-=" to relative numbers (#7345) 34672 if ( type === "string" && (ret = rrelNum.exec( value )) ) { 34673 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); 34674 // Fixes bug #9237 34675 type = "number"; 34676 } 34677 34678 // Make sure that null and NaN values aren't set (#7116) 34679 if ( value == null || value !== value ) { 34680 return; 34681 } 34682 34683 // If a number, add 'px' to the (except for certain CSS properties) 34684 if ( type === "number" && !jQuery.cssNumber[ origName ] ) { 34685 value += "px"; 34686 } 34687 34688 // Support: IE9-11+ 34689 // background-* props affect original clone's values 34690 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { 34691 style[ name ] = "inherit"; 34692 } 34693 34694 // If a hook was provided, use that value, otherwise just set the specified value 34695 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { 34696 style[ name ] = value; 34697 } 34698 34699 } else { 34700 // If a hook was provided get the non-computed value from there 34701 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { 34702 return ret; 34703 } 34704 34705 // Otherwise just get the value from the style object 34706 return style[ name ]; 34707 } 34708 }, 34709 34710 css: function( elem, name, extra, styles ) { 34711 var val, num, hooks, 34712 origName = jQuery.camelCase( name ); 34713 34714 // Make sure that we're working with the right name 34715 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); 34716 34717 // Try prefixed name followed by the unprefixed name 34718 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 34719 34720 // If a hook was provided get the computed value from there 34721 if ( hooks && "get" in hooks ) { 34722 val = hooks.get( elem, true, extra ); 34723 } 34724 34725 // Otherwise, if a way to get the computed value exists, use that 34726 if ( val === undefined ) { 34727 val = curCSS( elem, name, styles ); 34728 } 34729 34730 // Convert "normal" to computed value 34731 if ( val === "normal" && name in cssNormalTransform ) { 34732 val = cssNormalTransform[ name ]; 34733 } 34734 34735 // Make numeric if forced or a qualifier was provided and val looks numeric 34736 if ( extra === "" || extra ) { 34737 num = parseFloat( val ); 34738 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; 34739 } 34740 return val; 34741 } 34742}); 34743 34744jQuery.each([ "height", "width" ], function( i, name ) { 34745 jQuery.cssHooks[ name ] = { 34746 get: function( elem, computed, extra ) { 34747 if ( computed ) { 34748 34749 // Certain elements can have dimension info if we invisibly show them 34750 // but it must have a current display style that would benefit
34751 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ? 34752 jQuery.swap( elem, cssShow, function() { 34753 return getWidthOrHeight( elem, name, extra ); 34754 }) : 34755 getWidthOrHeight( elem, name, extra ); 34756 } 34757 }, 34758 34759 set: function( elem, value, extra ) { 34760 var styles = extra && getStyles( elem ); 34761 return setPositiveNumber( elem, value, extra ? 34762 augmentWidthOrHeight( 34763 elem, 34764 name, 34765 extra, 34766 jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 34767 styles 34768 ) : 0 34769 ); 34770 } 34771 }; 34772}); 34773 34774// Support: Android 2.3 34775jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, 34776 function( elem, computed ) { 34777 if ( computed ) { 34778 return jQuery.swap( elem, { "display": "inline-block" }, 34779 curCSS, [ elem, "marginRight" ] ); 34780 } 34781 } 34782); 34783 34784// These hooks are used by animate to expand properties 34785jQuery.each({ 34786 margin: "", 34787 padding: "", 34788 border: "Width" 34789}, function( prefix, suffix ) { 34790 jQuery.cssHooks[ prefix + suffix ] = { 34791 expand: function( value ) { 34792 var i = 0, 34793 expanded = {}, 34794 34795 // Assumes a single number if not a string 34796 parts = typeof value === "string" ? value.split(" ") : [ value ]; 34797 34798 for ( ; i < 4; i++ ) { 34799 expanded[ prefix + cssExpand[ i ] + suffix ] = 34800 parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; 34801 } 34802 34803 return expanded; 34804 } 34805 }; 34806 34807 if ( !rmargin.test( prefix ) ) { 34808 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; 34809 } 34810}); 34811 34812jQuery.fn.extend({ 34813 css: function( name, value ) { 34814 return access( this, function( elem, name, value ) { 34815 var styles, len, 34816 map = {}, 34817 i = 0; 34818 34819 if ( jQuery.isArray( name ) ) { 34820 styles = getStyles( elem ); 34821 len = name.length; 34822 34823 for ( ; i < len; i++ ) { 34824 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); 34825 } 34826 34827 return map; 34828 } 34829 34830 return value !== undefined ? 34831 jQuery.style( elem, name, value ) : 34832 jQuery.css( elem, name ); 34833 }, name, value, arguments.length > 1 ); 34834 }, 34835 show: function() { 34836 return showHide( this, true ); 34837 }, 34838 hide: function() { 34839 return showHide( this ); 34840 }, 34841 toggle: function( state ) { 34842 if ( typeof state === "boolean" ) { 34843 return state ? this.show() : this.hide(); 34844 } 34845 34846 return this.each(function() { 34847 if ( isHidden( this ) ) { 34848 jQuery( this ).show(); 34849 } else { 34850 jQuery( this ).hide(); 34851 } 34852 }); 34853 } 34854}); 34855 34856 34857function Tween( elem, options, prop, end, easing ) { 34858 return new Tween.prototype.init( elem, options, prop, end, easing ); 34859} 34860jQuery.Tween = Tween; 34861 34862Tween.prototype = { 34863 constructor: Tween, 34864 init: function( elem, options, prop, end, easing, unit ) { 34865 this.elem = elem; 34866 this.prop = prop; 34867 this.easing = easing || "swing"; 34868 this.options = options; 34869 this.start = this.now = this.cur(); 34870 this.end = end; 34871 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 34872 }, 34873 cur: function() { 34874 var hooks = Tween.propHooks[ this.prop ]; 34875 34876 return hooks && hooks.get ? 34877 hooks.get( this ) : 34878 Tween.propHooks._default.get( this ); 34879 }, 34880 run: function( percent ) { 34881 var eased, 34882 hooks = Tween.propHooks[ this.prop ]; 34883 34884 if ( this.options.duration ) { 34885 this.pos = eased = jQuery.easing[ this.easing ]( 34886 percent, this.options.duration * percent, 0, 1, this.options.duration 34887 ); 34888 } else { 34889 this.pos = eased = percent; 34890 } 34891 this.now = ( this.end - this.start ) * eased + this.start; 34892 34893 if ( this.options.step ) { 34894 this.options.step.call( this.elem, this.now, this ); 34895 } 34896 34897 if ( hooks && hooks.set ) { 34898 hooks.set( this ); 34899 } else { 34900 Tween.propHooks._default.set( this ); 34901 } 34902 return this; 34903 } 34904}; 34905 34906Tween.prototype.init.prototype = Tween.prototype; 34907 34908Tween.propHooks = { 34909 _default: { 34910 get: function( tween ) { 34911 var result; 34912 34913 if ( tween.elem[ tween.prop ] != null && 34914 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { 34915 return tween.elem[ tween.prop ]; 34916 } 34917 34918 // Passing an empty string as a 3rd parameter to .css will automatically 34919 // attempt a parseFloat and fallback to a string if the parse fails. 34920 // Simple values such as "10px" are parsed to Float; 34921 // complex values such as "rotate(1rad)" are returned as-is. 34922 result = jQuery.css( tween.elem, tween.prop, "" ); 34923 // Empty strings, null, undefined and "auto" are converted to 0. 34924 return !result || result === "auto" ? 0 : result; 34925 }, 34926 set: function( tween ) { 34927 // Use step hook for back compat. 34928 // Use cssHook if its there. 34929 // Use .style if available and use plain properties where available. 34930 if ( jQuery.fx.step[ tween.prop ] ) { 34931 jQuery.fx.step[ tween.prop ]( tween ); 34932 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { 34933 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); 34934 } else { 34935 tween.elem[ tween.prop ] = tween.now; 34936 } 34937 } 34938 } 34939}; 34940 34941// Support: IE9
34942// Panic based approach to setting things on disconnected nodes 34943Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { 34944 set: function( tween ) { 34945 if ( tween.elem.nodeType && tween.elem.parentNode ) { 34946 tween.elem[ tween.prop ] = tween.now; 34947 } 34948 } 34949}; 34950 34951jQuery.easing = { 34952 linear: function( p ) { 34953 return p; 34954 }, 34955 swing: function( p ) { 34956 return 0.5 - Math.cos( p * Math.PI ) / 2; 34957 } 34958}; 34959 34960jQuery.fx = Tween.prototype.init; 34961 34962// Back Compat <1.8 extension point 34963jQuery.fx.step = {}; 34964 34965 34966 34967 34968var 34969 fxNow, timerId, 34970 rfxtypes = /^(?:toggle|show|hide)$/, 34971 rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ), 34972 rrun = /queueHooks$/, 34973 animationPrefilters = [ defaultPrefilter ], 34974 tweeners = { 34975 "*": [ function( prop, value ) { 34976 var tween = this.createTween( prop, value ), 34977 target = tween.cur(), 34978 parts = rfxnum.exec( value ), 34979 unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), 34980 34981 // Starting value computation is required for potential unit mismatches 34982 start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && 34983 rfxnum.exec( jQuery.css( tween.elem, prop ) ), 34984 scale = 1, 34985 maxIterations = 20; 34986 34987 if ( start && start[ 3 ] !== unit ) { 34988 // Trust units reported by jQuery.css 34989 unit = unit || start[ 3 ]; 34990 34991 // Make sure we update the tween properties later on 34992 parts = parts || []; 34993 34994 // Iteratively approximate from a nonzero starting point 34995 start = +target || 1; 34996 34997 do { 34998 // If previous iteration zeroed out, double until we get *something*. 34999 // Use string for doubling so we don't accidentally see scale as unchanged below 35000 scale = scale || ".5"; 35001 35002 // Adjust and apply 35003 start = start / scale; 35004 jQuery.style( tween.elem, prop, start + unit ); 35005 35006 // Update scale, tolerating zero or NaN from tween.cur(), 35007 // break the loop if scale is unchanged or perfect, or if we've just had enough 35008 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); 35009 } 35010 35011 // Update tween properties 35012 if ( parts ) { 35013 start = tween.start = +start || +target || 0; 35014 tween.unit = unit; 35015 // If a +=/-= token was provided, we're doing a relative animation 35016 tween.end = parts[ 1 ] ? 35017 start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : 35018 +parts[ 2 ]; 35019 } 35020 35021 return tween; 35022 } ] 35023 }; 35024 35025// Animations created synchronously will run synchronously 35026function createFxNow() { 35027 setTimeout(function() { 35028 fxNow = undefined; 35029 }); 35030 return ( fxNow = jQuery.now() ); 35031} 35032 35033// Generate parameters to create a standard animation 35034function genFx( type, includeWidth ) { 35035 var which, 35036 i = 0, 35037 attrs = { height: type }; 35038 35039 // If we include width, step value is 1 to do all cssExpand values, 35040 // otherwise step value is 2 to skip over Left and Right 35041 includeWidth = includeWidth ? 1 : 0; 35042 for ( ; i < 4 ; i += 2 - includeWidth ) { 35043 which = cssExpand[ i ]; 35044 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; 35045 } 35046 35047 if ( includeWidth ) { 35048 attrs.opacity = attrs.width = type; 35049 } 35050 35051 return attrs; 35052} 35053 35054function createTween( value, prop, animation ) { 35055 var tween, 35056 collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), 35057 index = 0, 35058 length = collection.length; 35059 for ( ; index < length; index++ ) { 35060 if ( (tween = collection[ index ].call( animation, prop, value )) ) { 35061 35062 // We're done with this property 35063 return tween; 35064 } 35065 } 35066} 35067 35068function defaultPrefilter( elem, props, opts ) { 35069 /* jshint validthis: true */ 35070 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, 35071 anim = this, 35072 orig = {}, 35073 style = elem.style, 35074 hidden = elem.nodeType && isHidden( elem ), 35075 dataShow = data_priv.get( elem, "fxshow" ); 35076 35077 // Handle queue: false promises 35078 if ( !opts.queue ) { 35079 hooks = jQuery._queueHooks( elem, "fx" ); 35080 if ( hooks.unqueued == null ) { 35081 hooks.unqueued = 0; 35082 oldfire = hooks.empty.fire; 35083 hooks.empty.fire = function() { 35084 if ( !hooks.unqueued ) { 35085 oldfire(); 35086 } 35087 }; 35088 } 35089 hooks.unqueued++; 35090 35091 anim.always(function() { 35092 // Ensure the complete handler is called before this completes 35093 anim.always(function() { 35094 hooks.unqueued--; 35095 if ( !jQuery.queue( elem, "fx" ).length ) { 35096 hooks.empty.fire(); 35097 } 35098 }); 35099 }); 35100 } 35101 35102 // Height/width overflow pass 35103 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { 35104 // Make sure that nothing sneaks out
35105 // Record all 3 overflow attributes because IE9-10 do not 35106 // change the overflow attribute when overflowX and 35107 // overflowY are set to the same value 35108 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; 35109 35110 // Set display property to inline-block for height/width 35111 // animations on inline elements that are having width/height animated 35112 display = jQuery.css( elem, "display" ); 35113 35114 // Test default display if display is currently "none" 35115 checkDisplay = display === "none" ? 35116 data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; 35117 35118 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { 35119 style.display = "inline-block"; 35120 } 35121 } 35122 35123 if ( opts.overflow ) { 35124 style.overflow = "hidden"; 35125 anim.always(function() { 35126 style.overflow = opts.overflow[ 0 ]; 35127 style.overflowX = opts.overflow[ 1 ]; 35128 style.overflowY = opts.overflow[ 2 ]; 35129 }); 35130 } 35131 35132 // show/hide pass 35133 for ( prop in props ) { 35134 value = props[ prop ]; 35135 if ( rfxtypes.exec( value ) ) { 35136 delete props[ prop ]; 35137 toggle = toggle || value === "toggle"; 35138 if ( value === ( hidden ? "hide" : "show" ) ) { 35139 35140 // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden 35141 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { 35142 hidden = true; 35143 } else { 35144 continue; 35145 } 35146 } 35147 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); 35148 35149 // Any non-fx value stops us from restoring the original display value 35150 } else { 35151 display = undefined; 35152 } 35153 } 35154 35155 if ( !jQuery.isEmptyObject( orig ) ) { 35156 if ( dataShow ) { 35157 if ( "hidden" in dataShow ) { 35158 hidden = dataShow.hidden; 35159 } 35160 } else { 35161 dataShow = data_priv.access( elem, "fxshow", {} ); 35162 } 35163 35164 // Store state if its toggle - enables .stop().toggle() to "reverse" 35165 if ( toggle ) { 35166 dataShow.hidden = !hidden; 35167 } 35168 if ( hidden ) { 35169 jQuery( elem ).show(); 35170 } else { 35171 anim.done(function() { 35172 jQuery( elem ).hide(); 35173 }); 35174 } 35175 anim.done(function() { 35176 var prop; 35177 35178 data_priv.remove( elem, "fxshow" ); 35179 for ( prop in orig ) { 35180 jQuery.style( elem, prop, orig[ prop ] ); 35181 } 35182 }); 35183 for ( prop in orig ) { 35184 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); 35185 35186 if ( !( prop in dataShow ) ) { 35187 dataShow[ prop ] = tween.start; 35188 if ( hidden ) { 35189 tween.end = tween.start; 35190 tween.start = prop === "width" || prop === "height" ? 1 : 0; 35191 } 35192 } 35193 } 35194 35195 // If this is a noop like .hide().hide(), restore an overwritten display value 35196 } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) { 35197 style.display = display; 35198 } 35199} 35200 35201function propFilter( props, specialEasing ) { 35202 var index, name, easing, value, hooks; 35203 35204 // camelCase, specialEasing and expand cssHook pass 35205 for ( index in props ) { 35206 name = jQuery.camelCase( index ); 35207 easing = specialEasing[ name ]; 35208 value = props[ index ]; 35209 if ( jQuery.isArray( value ) ) { 35210 easing = value[ 1 ]; 35211 value = props[ index ] = value[ 0 ]; 35212 } 35213 35214 if ( index !== name ) { 35215 props[ name ] = value; 35216 delete props[ index ]; 35217 } 35218 35219 hooks = jQuery.cssHooks[ name ]; 35220 if ( hooks && "expand" in hooks ) { 35221 value = hooks.expand( value ); 35222 delete props[ name ]; 35223 35224 // Not quite $.extend, this won't overwrite existing keys. 35225 // Reusing 'index' because we have the correct "name" 35226 for ( index in value ) { 35227 if ( !( index in props ) ) { 35228 props[ index ] = value[ index ]; 35229 specialEasing[ index ] = easing; 35230 } 35231 } 35232 } else { 35233 specialEasing[ name ] = easing; 35234 } 35235 } 35236} 35237 35238function Animation( elem, properties, options ) { 35239 var result, 35240 stopped, 35241 index = 0, 35242 length = animationPrefilters.length, 35243 deferred = jQuery.Deferred().always( function() { 35244 // Don't match elem in the :animated selector 35245 delete tick.elem; 35246 }), 35247 tick = function() { 35248 if ( stopped ) { 35249 return false; 35250 } 35251 var currentTime = fxNow || createFxNow(), 35252 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
vendor: 8,530 bytes, lines 35253-35567
35253 // Support: Android 2.3 35254 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) 35255 temp = remaining / animation.duration || 0, 35256 percent = 1 - temp, 35257 index = 0, 35258 length = animation.tweens.length; 35259 35260 for ( ; index < length ; index++ ) { 35261 animation.tweens[ index ].run( percent ); 35262 } 35263 35264 deferred.notifyWith( elem, [ animation, percent, remaining ]); 35265 35266 if ( percent < 1 && length ) { 35267 return remaining; 35268 } else { 35269 deferred.resolveWith( elem, [ animation ] ); 35270 return false; 35271 } 35272 }, 35273 animation = deferred.promise({ 35274 elem: elem, 35275 props: jQuery.extend( {}, properties ), 35276 opts: jQuery.extend( true, { specialEasing: {} }, options ), 35277 originalProperties: properties, 35278 originalOptions: options, 35279 startTime: fxNow || createFxNow(), 35280 duration: options.duration, 35281 tweens: [], 35282 createTween: function( prop, end ) { 35283 var tween = jQuery.Tween( elem, animation.opts, prop, end, 35284 animation.opts.specialEasing[ prop ] || animation.opts.easing ); 35285 animation.tweens.push( tween ); 35286 return tween; 35287 }, 35288 stop: function( gotoEnd ) { 35289 var index = 0, 35290 // If we are going to the end, we want to run all the tweens 35291 // otherwise we skip this part 35292 length = gotoEnd ? animation.tweens.length : 0; 35293 if ( stopped ) { 35294 return this; 35295 } 35296 stopped = true; 35297 for ( ; index < length ; index++ ) { 35298 animation.tweens[ index ].run( 1 ); 35299 } 35300 35301 // Resolve when we played the last frame; otherwise, reject 35302 if ( gotoEnd ) { 35303 deferred.resolveWith( elem, [ animation, gotoEnd ] ); 35304 } else { 35305 deferred.rejectWith( elem, [ animation, gotoEnd ] ); 35306 } 35307 return this; 35308 } 35309 }), 35310 props = animation.props; 35311 35312 propFilter( props, animation.opts.specialEasing ); 35313 35314 for ( ; index < length ; index++ ) { 35315 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); 35316 if ( result ) { 35317 return result; 35318 } 35319 } 35320 35321 jQuery.map( props, createTween, animation ); 35322 35323 if ( jQuery.isFunction( animation.opts.start ) ) { 35324 animation.opts.start.call( elem, animation ); 35325 } 35326 35327 jQuery.fx.timer( 35328 jQuery.extend( tick, { 35329 elem: elem, 35330 anim: animation, 35331 queue: animation.opts.queue 35332 }) 35333 ); 35334 35335 // attach callbacks from options 35336 return animation.progress( animation.opts.progress ) 35337 .done( animation.opts.done, animation.opts.complete ) 35338 .fail( animation.opts.fail ) 35339 .always( animation.opts.always ); 35340} 35341 35342jQuery.Animation = jQuery.extend( Animation, { 35343 35344 tweener: function( props, callback ) { 35345 if ( jQuery.isFunction( props ) ) { 35346 callback = props; 35347 props = [ "*" ]; 35348 } else { 35349 props = props.split(" "); 35350 } 35351 35352 var prop, 35353 index = 0, 35354 length = props.length; 35355 35356 for ( ; index < length ; index++ ) { 35357 prop = props[ index ]; 35358 tweeners[ prop ] = tweeners[ prop ] || []; 35359 tweeners[ prop ].unshift( callback ); 35360 } 35361 }, 35362 35363 prefilter: function( callback, prepend ) { 35364 if ( prepend ) { 35365 animationPrefilters.unshift( callback ); 35366 } else { 35367 animationPrefilters.push( callback ); 35368 } 35369 } 35370}); 35371 35372jQuery.speed = function( speed, easing, fn ) { 35373 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 35374 complete: fn || !fn && easing || 35375 jQuery.isFunction( speed ) && speed, 35376 duration: speed, 35377 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing 35378 }; 35379 35380 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : 35381 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; 35382 35383 // Normalize opt.queue - true/undefined/null -> "fx" 35384 if ( opt.queue == null || opt.queue === true ) { 35385 opt.queue = "fx"; 35386 } 35387 35388 // Queueing 35389 opt.old = opt.complete; 35390 35391 opt.complete = function() { 35392 if ( jQuery.isFunction( opt.old ) ) { 35393 opt.old.call( this ); 35394 } 35395 35396 if ( opt.queue ) { 35397 jQuery.dequeue( this, opt.queue ); 35398 } 35399 }; 35400 35401 return opt; 35402}; 35403 35404jQuery.fn.extend({ 35405 fadeTo: function( speed, to, easing, callback ) { 35406 35407 // Show any hidden elements after setting opacity to 0 35408 return this.filter( isHidden ).css( "opacity", 0 ).show() 35409 35410 // Animate to the value specified 35411 .end().animate({ opacity: to }, speed, easing, callback ); 35412 }, 35413 animate: function( prop, speed, easing, callback ) { 35414 var empty = jQuery.isEmptyObject( prop ), 35415 optall = jQuery.speed( speed, easing, callback ), 35416 doAnimation = function() { 35417 // Operate on a copy of prop so per-property easing won't be lost 35418 var anim = Animation( this, jQuery.extend( {}, prop ), optall ); 35419 35420 // Empty animations, or finishing resolves immediately 35421 if ( empty || data_priv.get( this, "finish" ) ) { 35422 anim.stop( true ); 35423 } 35424 }; 35425 doAnimation.finish = doAnimation; 35426 35427 return empty || optall.queue === false ? 35428 this.each( doAnimation ) : 35429 this.queue( optall.queue, doAnimation ); 35430 }, 35431 stop: function( type, clearQueue, gotoEnd ) { 35432 var stopQueue = function( hooks ) { 35433 var stop = hooks.stop; 35434 delete hooks.stop; 35435 stop( gotoEnd ); 35436 }; 35437 35438 if ( typeof type !== "string" ) { 35439 gotoEnd = clearQueue; 35440 clearQueue = type; 35441 type = undefined; 35442 } 35443 if ( clearQueue && type !== false ) { 35444 this.queue( type || "fx", [] ); 35445 } 35446 35447 return this.each(function() { 35448 var dequeue = true, 35449 index = type != null && type + "queueHooks", 35450 timers = jQuery.timers, 35451 data = data_priv.get( this ); 35452 35453 if ( index ) { 35454 if ( data[ index ] && data[ index ].stop ) { 35455 stopQueue( data[ index ] ); 35456 } 35457 } else { 35458 for ( index in data ) { 35459 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { 35460 stopQueue( data[ index ] ); 35461 } 35462 } 35463 } 35464 35465 for ( index = timers.length; index--; ) { 35466 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { 35467 timers[ index ].anim.stop( gotoEnd ); 35468 dequeue = false; 35469 timers.splice( index, 1 ); 35470 } 35471 } 35472 35473 // Start the next in the queue if the last step wasn't forced. 35474 // Timers currently will call their complete callbacks, which 35475 // will dequeue but only if they were gotoEnd. 35476 if ( dequeue || !gotoEnd ) { 35477 jQuery.dequeue( this, type ); 35478 } 35479 }); 35480 }, 35481 finish: function( type ) { 35482 if ( type !== false ) { 35483 type = type || "fx"; 35484 } 35485 return this.each(function() { 35486 var index, 35487 data = data_priv.get( this ), 35488 queue = data[ type + "queue" ], 35489 hooks = data[ type + "queueHooks" ], 35490 timers = jQuery.timers, 35491 length = queue ? queue.length : 0; 35492 35493 // Enable finishing flag on private data 35494 data.finish = true; 35495 35496 // Empty the queue first 35497 jQuery.queue( this, type, [] ); 35498 35499 if ( hooks && hooks.stop ) { 35500 hooks.stop.call( this, true ); 35501 } 35502 35503 // Look for any active animations, and finish them 35504 for ( index = timers.length; index--; ) { 35505 if ( timers[ index ].elem === this && timers[ index ].queue === type ) { 35506 timers[ index ].anim.stop( true ); 35507 timers.splice( index, 1 ); 35508 } 35509 } 35510 35511 // Look for any animations in the old queue and finish them 35512 for ( index = 0; index < length; index++ ) { 35513 if ( queue[ index ] && queue[ index ].finish ) { 35514 queue[ index ].finish.call( this ); 35515 } 35516 } 35517 35518 // Turn off finishing flag 35519 delete data.finish; 35520 }); 35521 } 35522}); 35523 35524jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { 35525 var cssFn = jQuery.fn[ name ]; 35526 jQuery.fn[ name ] = function( speed, easing, callback ) { 35527 return speed == null || typeof speed === "boolean" ? 35528 cssFn.apply( this, arguments ) : 35529 this.animate( genFx( name, true ), speed, easing, callback ); 35530 }; 35531}); 35532 35533// Generate shortcuts for custom animations 35534jQuery.each({ 35535 slideDown: genFx("show"), 35536 slideUp: genFx("hide"), 35537 slideToggle: genFx("toggle"), 35538 fadeIn: { opacity: "show" }, 35539 fadeOut: { opacity: "hide" }, 35540 fadeToggle: { opacity: "toggle" } 35541}, function( name, props ) { 35542 jQuery.fn[ name ] = function( speed, easing, callback ) { 35543 return this.animate( props, speed, easing, callback ); 35544 }; 35545}); 35546 35547jQuery.timers = []; 35548jQuery.fx.tick = function() { 35549 var timer, 35550 i = 0, 35551 timers = jQuery.timers; 35552 35553 fxNow = jQuery.now(); 35554 35555 for ( ; i < timers.length; i++ ) { 35556 timer = timers[ i ]; 35557 // Checks the timer has not already been removed 35558 if ( !timer() && timers[ i ] === timer ) { 35559 timers.splice( i--, 1 ); 35560 } 35561 } 35562 35563 if ( !timers.length ) { 35564 jQuery.fx.stop(); 35565 } 35566 fxNow = undefined; 35567};
35568 35569jQuery.fx.timer = function( timer ) { 35570 jQuery.timers.push( timer ); 35571 if ( timer() ) { 35572 jQuery.fx.start(); 35573 } else { 35574 jQuery.timers.pop(); 35575 } 35576}; 35577 35578jQuery.fx.interval = 13; 35579 35580jQuery.fx.start = function() { 35581 if ( !timerId ) { 35582 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); 35583 } 35584}; 35585 35586jQuery.fx.stop = function() { 35587 clearInterval( timerId ); 35588 timerId = null; 35589}; 35590 35591jQuery.fx.speeds = { 35592 slow: 600, 35593 fast: 200, 35594 // Default speed 35595 _default: 400 35596}; 35597 35598 35599// Based off of the plugin by Clint Helfers, with permission. 35600// http://blindsignals.com/index.php/2009/07/jquery-delay/ 35601jQuery.fn.delay = function( time, type ) { 35602 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 35603 type = type || "fx"; 35604 35605 return this.queue( type, function( next, hooks ) { 35606 var timeout = setTimeout( next, time ); 35607 hooks.stop = function() { 35608 clearTimeout( timeout ); 35609 }; 35610 }); 35611}; 35612 35613 35614(function() { 35615 var input = document.createElement( "input" ), 35616 select = document.createElement( "select" ), 35617 opt = select.appendChild( document.createElement( "option" ) ); 35618 35619 input.type = "checkbox"; 35620 35621 // Support: iOS<=5.1, Android<=4.2+ 35622 // Default value for a checkbox should be "on" 35623 support.checkOn = input.value !== ""; 35624 35625 // Support: IE<=11+ 35626 // Must access selectedIndex to make default options select 35627 support.optSelected = opt.selected; 35628 35629 // Support: Android<=2.3 35630 // Options inside disabled selects are incorrectly marked as disabled 35631 select.disabled = true; 35632 support.optDisabled = !opt.disabled; 35633 35634 // Support: IE<=11+ 35635 // An input loses its value after becoming a radio 35636 input = document.createElement( "input" ); 35637 input.value = "t"; 35638 input.type = "radio"; 35639 support.radioValue = input.value === "t"; 35640})(); 35641 35642 35643var nodeHook, boolHook, 35644 attrHandle = jQuery.expr.attrHandle; 35645 35646jQuery.fn.extend({ 35647 attr: function( name, value ) { 35648 return access( this, jQuery.attr, name, value, arguments.length > 1 ); 35649 }, 35650 35651 removeAttr: function( name ) { 35652 return this.each(function() { 35653 jQuery.removeAttr( this, name ); 35654 }); 35655 } 35656}); 35657 35658jQuery.extend({ 35659 attr: function( elem, name, value ) { 35660 var hooks, ret, 35661 nType = elem.nodeType; 35662 35663 // don't get/set attributes on text, comment and attribute nodes 35664 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 35665 return; 35666 } 35667 35668 // Fallback to prop when attributes are not supported 35669 if ( typeof elem.getAttribute === strundefined ) { 35670 return jQuery.prop( elem, name, value ); 35671 } 35672 35673 // All attributes are lowercase 35674 // Grab necessary hook if one is defined 35675 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 35676 name = name.toLowerCase(); 35677 hooks = jQuery.attrHooks[ name ] || 35678 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); 35679 } 35680 35681 if ( value !== undefined ) { 35682 35683 if ( value === null ) { 35684 jQuery.removeAttr( elem, name ); 35685 35686 } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { 35687 return ret; 35688 35689 } else { 35690 elem.setAttribute( name, value + "" ); 35691 return value; 35692 } 35693 35694 } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { 35695 return ret; 35696 35697 } else { 35698 ret = jQuery.find.attr( elem, name ); 35699 35700 // Non-existent attributes return null, we normalize to undefined 35701 return ret == null ? 35702 undefined : 35703 ret; 35704 } 35705 }, 35706 35707 removeAttr: function( elem, value ) { 35708 var name, propName, 35709 i = 0, 35710 attrNames = value && value.match( rnotwhite ); 35711 35712 if ( attrNames && elem.nodeType === 1 ) { 35713 while ( (name = attrNames[i++]) ) { 35714 propName = jQuery.propFix[ name ] || name; 35715 35716 // Boolean attributes get special treatment (#10870) 35717 if ( jQuery.expr.match.bool.test( name ) ) { 35718 // Set corresponding property to false 35719 elem[ propName ] = false; 35720 } 35721 35722 elem.removeAttribute( name ); 35723 } 35724 } 35725 }, 35726 35727 attrHooks: {
35728 type: { 35729 set: function( elem, value ) { 35730 if ( !support.radioValue && value === "radio" && 35731 jQuery.nodeName( elem, "input" ) ) { 35732 var val = elem.value; 35733 elem.setAttribute( "type", value ); 35734 if ( val ) { 35735 elem.value = val; 35736 } 35737 return value; 35738 } 35739 } 35740 } 35741 } 35742}); 35743 35744// Hooks for boolean attributes 35745boolHook = { 35746 set: function( elem, value, name ) { 35747 if ( value === false ) { 35748 // Remove boolean attributes when set to false 35749 jQuery.removeAttr( elem, name ); 35750 } else { 35751 elem.setAttribute( name, name ); 35752 } 35753 return name; 35754 } 35755}; 35756jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { 35757 var getter = attrHandle[ name ] || jQuery.find.attr; 35758 35759 attrHandle[ name ] = function( elem, name, isXML ) { 35760 var ret, handle; 35761 if ( !isXML ) { 35762 // Avoid an infinite loop by temporarily removing this function from the getter 35763 handle = attrHandle[ name ]; 35764 attrHandle[ name ] = ret; 35765 ret = getter( elem, name, isXML ) != null ? 35766 name.toLowerCase() : 35767 null; 35768 attrHandle[ name ] = handle; 35769 } 35770 return ret; 35771 }; 35772}); 35773 35774 35775 35776 35777var rfocusable = /^(?:input|select|textarea|button)$/i; 35778 35779jQuery.fn.extend({ 35780 prop: function( name, value ) { 35781 return access( this, jQuery.prop, name, value, arguments.length > 1 ); 35782 }, 35783 35784 removeProp: function( name ) { 35785 return this.each(function() { 35786 delete this[ jQuery.propFix[ name ] || name ]; 35787 }); 35788 } 35789}); 35790 35791jQuery.extend({ 35792 propFix: { 35793 "for": "htmlFor", 35794 "class": "className" 35795 }, 35796 35797 prop: function( elem, name, value ) { 35798 var ret, hooks, notxml, 35799 nType = elem.nodeType; 35800 35801 // Don't get/set properties on text, comment and attribute nodes 35802 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 35803 return; 35804 } 35805 35806 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); 35807 35808 if ( notxml ) { 35809 // Fix name and attach hooks 35810 name = jQuery.propFix[ name ] || name; 35811 hooks = jQuery.propHooks[ name ]; 35812 } 35813 35814 if ( value !== undefined ) { 35815 return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? 35816 ret : 35817 ( elem[ name ] = value ); 35818 35819 } else { 35820 return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? 35821 ret : 35822 elem[ name ]; 35823 } 35824 }, 35825 35826 propHooks: { 35827 tabIndex: { 35828 get: function( elem ) { 35829 return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ? 35830 elem.tabIndex : 35831 -1; 35832 } 35833 } 35834 } 35835}); 35836 35837if ( !support.optSelected ) { 35838 jQuery.propHooks.selected = { 35839 get: function( elem ) { 35840 var parent = elem.parentNode; 35841 if ( parent && parent.parentNode ) { 35842 parent.parentNode.selectedIndex; 35843 } 35844 return null; 35845 } 35846 }; 35847} 35848 35849jQuery.each([ 35850 "tabIndex", 35851 "readOnly", 35852 "maxLength", 35853 "cellSpacing", 35854 "cellPadding", 35855 "rowSpan", 35856 "colSpan", 35857 "useMap", 35858 "frameBorder", 35859 "contentEditable" 35860], function() { 35861 jQuery.propFix[ this.toLowerCase() ] = this; 35862}); 35863 35864 35865 35866 35867var rclass = /[\t\r\n\f]/g; 35868 35869jQuery.fn.extend({ 35870 addClass: function( value ) { 35871 var classes, elem, cur, clazz, j, finalValue, 35872 proceed = typeof value === "string" && value, 35873 i = 0, 35874 len = this.length; 35875 35876 if ( jQuery.isFunction( value ) ) { 35877 return this.each(function( j ) { 35878 jQuery( this ).addClass( value.call( this, j, this.className ) ); 35879 }); 35880 } 35881 35882 if ( proceed ) { 35883 // The disjunction here is for better compressibility (see removeClass) 35884 classes = ( value || "" ).match( rnotwhite ) || []; 35885 35886 for ( ; i < len; i++ ) { 35887 elem = this[ i ]; 35888 cur = elem.nodeType === 1 && ( elem.className ? 35889 ( " " + elem.className + " " ).replace( rclass, " " ) : 35890 " " 35891 ); 35892 35893 if ( cur ) { 35894 j = 0; 35895 while ( (clazz = classes[j++]) ) { 35896 if ( cur.indexOf( " " + clazz + " " ) < 0 ) { 35897 cur += clazz + " "; 35898 } 35899 } 35900 35901 // only assign if different to avoid unneeded rendering. 35902 finalValue = jQuery.trim( cur ); 35903 if ( elem.className !== finalValue ) { 35904 elem.className = finalValue; 35905 } 35906 } 35907 } 35908 } 35909 35910 return this; 35911 }, 35912 35913 removeClass: function( value ) { 35914 var classes, elem, cur, clazz, j, finalValue, 35915 proceed = arguments.length === 0 || typeof value === "string" && value, 35916 i = 0, 35917 len = this.length; 35918 35919 if ( jQuery.isFunction( value ) ) { 35920 return this.each(function( j ) { 35921 jQuery( this ).removeClass( value.call( this, j, this.className ) ); 35922 }); 35923 } 35924 if ( proceed ) { 35925 classes = ( value || "" ).match( rnotwhite ) || []; 35926 35927 for ( ; i < len; i++ ) { 35928 elem = this[ i ]; 35929 // This expression is here for better compressibility (see addClass) 35930 cur = elem.nodeType === 1 && ( elem.className ? 35931 ( " " + elem.className + " " ).replace( rclass, " " ) : 35932 "" 35933 ); 35934 35935 if ( cur ) { 35936 j = 0; 35937 while ( (clazz = classes[j++]) ) {
35938 // Remove *all* instances 35939 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { 35940 cur = cur.replace( " " + clazz + " ", " " ); 35941 } 35942 } 35943 35944 // Only assign if different to avoid unneeded rendering. 35945 finalValue = value ? jQuery.trim( cur ) : ""; 35946 if ( elem.className !== finalValue ) { 35947 elem.className = finalValue; 35948 } 35949 } 35950 } 35951 } 35952 35953 return this; 35954 }, 35955 35956 toggleClass: function( value, stateVal ) { 35957 var type = typeof value; 35958 35959 if ( typeof stateVal === "boolean" && type === "string" ) { 35960 return stateVal ? this.addClass( value ) : this.removeClass( value ); 35961 } 35962 35963 if ( jQuery.isFunction( value ) ) { 35964 return this.each(function( i ) { 35965 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); 35966 }); 35967 } 35968 35969 return this.each(function() { 35970 if ( type === "string" ) { 35971 // Toggle individual class names 35972 var className, 35973 i = 0, 35974 self = jQuery( this ), 35975 classNames = value.match( rnotwhite ) || []; 35976 35977 while ( (className = classNames[ i++ ]) ) { 35978 // Check each className given, space separated list 35979 if ( self.hasClass( className ) ) { 35980 self.removeClass( className ); 35981 } else { 35982 self.addClass( className ); 35983 } 35984 } 35985 35986 // Toggle whole class name 35987 } else if ( type === strundefined || type === "boolean" ) { 35988 if ( this.className ) { 35989 // store className if set 35990 data_priv.set( this, "__className__", this.className ); 35991 } 35992 35993 // If the element has a class name or if we're passed `false`, 35994 // then remove the whole classname (if there was one, the above saved it). 35995 // Otherwise bring back whatever was previously saved (if anything), 35996 // falling back to the empty string if nothing was stored. 35997 this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || ""; 35998 } 35999 }); 36000 }, 36001 36002 hasClass: function( selector ) { 36003 var className = " " + selector + " ", 36004 i = 0, 36005 l = this.length; 36006 for ( ; i < l; i++ ) { 36007 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { 36008 return true; 36009 } 36010 } 36011 36012 return false; 36013 } 36014}); 36015 36016 36017 36018 36019var rreturn = /\r/g; 36020 36021jQuery.fn.extend({ 36022 val: function( value ) { 36023 var hooks, ret, isFunction, 36024 elem = this[0]; 36025 36026 if ( !arguments.length ) { 36027 if ( elem ) { 36028 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; 36029 36030 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { 36031 return ret; 36032 } 36033 36034 ret = elem.value; 36035 36036 return typeof ret === "string" ? 36037 // Handle most common string cases 36038 ret.replace(rreturn, "") : 36039 // Handle cases where value is null/undef or number 36040 ret == null ? "" : ret; 36041 } 36042 36043 return; 36044 } 36045 36046 isFunction = jQuery.isFunction( value ); 36047 36048 return this.each(function( i ) { 36049 var val; 36050 36051 if ( this.nodeType !== 1 ) { 36052 return; 36053 } 36054 36055 if ( isFunction ) { 36056 val = value.call( this, i, jQuery( this ).val() ); 36057 } else { 36058 val = value; 36059 } 36060 36061 // Treat null/undefined as ""; convert numbers to string 36062 if ( val == null ) { 36063 val = ""; 36064 36065 } else if ( typeof val === "number" ) { 36066 val += ""; 36067 36068 } else if ( jQuery.isArray( val ) ) { 36069 val = jQuery.map( val, function( value ) { 36070 return value == null ? "" : value + ""; 36071 }); 36072 } 36073 36074 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; 36075 36076 // If set returns undefined, fall back to normal setting 36077 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { 36078 this.value = val; 36079 } 36080 }); 36081 } 36082}); 36083 36084jQuery.extend({ 36085 valHooks: { 36086 option: { 36087 get: function( elem ) { 36088 var val = jQuery.find.attr( elem, "value" ); 36089 return val != null ? 36090 val : 36091 // Support: IE10-11+ 36092 // option.text throws exceptions (#14686, #14858) 36093 jQuery.trim( jQuery.text( elem ) ); 36094 } 36095 }, 36096 select: { 36097 get: function( elem ) { 36098 var value, option, 36099 options = elem.options, 36100 index = elem.selectedIndex, 36101 one = elem.type === "select-one" || index < 0, 36102 values = one ? null : [], 36103 max = one ? index + 1 : options.length, 36104 i = index < 0 ? 36105 max : 36106 one ? index : 0; 36107 36108 // Loop through all the selected options 36109 for ( ; i < max; i++ ) { 36110 option = options[ i ]; 36111 36112 // IE6-9 doesn't update selected after form reset (#2551) 36113 if ( ( option.selected || i === index ) && 36114 // Don't return options that are disabled or in a disabled optgroup 36115 ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) && 36116 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { 36117 36118 // Get the specific value for the option 36119 value = jQuery( option ).val(); 36120 36121 // We don't need an array for one selects 36122 if ( one ) { 36123 return value; 36124 } 36125 36126 // Multi-Selects return an array 36127 values.push( value ); 36128 } 36129 } 36130 36131 return values; 36132 }, 36133 36134 set: function( elem, value ) { 36135 var optionSet, option, 36136 options = elem.options, 36137 values = jQuery.makeArray( value ), 36138 i = options.length; 36139 36140 while ( i-- ) { 36141 option = options[ i ]; 36142 if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) { 36143 optionSet = true; 36144 } 36145 } 36146 36147 // Force browsers to behave consistently when non-matching value is set 36148 if ( !optionSet ) { 36149 elem.selectedIndex = -1; 36150 } 36151 return values; 36152 } 36153 } 36154 } 36155}); 36156 36157// Radios and checkboxes getter/setter 36158jQuery.each([ "radio", "checkbox" ], function() { 36159 jQuery.valHooks[ this ] = { 36160 set: function( elem, value ) { 36161 if ( jQuery.isArray( value ) ) { 36162 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); 36163 } 36164 } 36165 }; 36166 if ( !support.checkOn ) { 36167 jQuery.valHooks[ this ].get = function( elem ) { 36168 return elem.getAttribute("value") === null ? "on" : elem.value; 36169 }; 36170 } 36171}); 36172 36173 36174 36175 36176// Return jQuery for attributes-only inclusion 36177 36178 36179jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + 36180 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 36181 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { 36182 36183 // Handle event binding 36184 jQuery.fn[ name ] = function( data, fn ) { 36185 return arguments.length > 0 ? 36186 this.on( name, null, data, fn ) : 36187 this.trigger( name ); 36188 }; 36189}); 36190 36191jQuery.fn.extend({ 36192 hover: function( fnOver, fnOut ) { 36193 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); 36194 }, 36195 36196 bind: function( types, data, fn ) { 36197 return this.on( types, null, data, fn ); 36198 }, 36199 unbind: function( types, fn ) { 36200 return this.off( types, null, fn ); 36201 }, 36202 36203 delegate: function( selector, types, data, fn ) { 36204 return this.on( types, selector, data, fn ); 36205 }, 36206 undelegate: function( selector, types, fn ) { 36207 // ( namespace ) or ( selector, types [, fn] ) 36208 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); 36209 } 36210}); 36211 36212 36213var nonce = jQuery.now(); 36214 36215var rquery = (/\?/); 36216 36217 36218 36219// Support: Android 2.3 36220// Workaround failure to string-cast null input 36221jQuery.parseJSON = function( data ) { 36222 return JSON.parse( data + "" ); 36223}; 36224 36225 36226// Cross-browser xml parsing 36227jQuery.parseXML = function( data ) { 36228 var xml, tmp; 36229 if ( !data || typeof data !== "string" ) { 36230 return null; 36231 } 36232 36233 // Support: IE9 36234 try { 36235 tmp = new DOMParser(); 36236 xml = tmp.parseFromString( data, "text/xml" ); 36237 } catch ( e ) { 36238 xml = undefined; 36239 } 36240 36241 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { 36242 jQuery.error( "Invalid XML: " + data ); 36243 } 36244 return xml; 36245}; 36246 36247 36248var 36249 rhash = /#.*$/, 36250 rts = /([?&])_=[^&]*/, 36251 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
vendor: 4,413 bytes, lines 36252-36392
36252 // #7653, #8125, #8152: local protocol detection 36253 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, 36254 rnoContent = /^(?:GET|HEAD)$/, 36255 rprotocol = /^\/\//, 36256 rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, 36257 36258 /* Prefilters 36259 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 36260 * 2) These are called: 36261 * - BEFORE asking for a transport 36262 * - AFTER param serialization (s.data is a string if s.processData is true) 36263 * 3) key is the dataType 36264 * 4) the catchall symbol "*" can be used 36265 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 36266 */ 36267 prefilters = {}, 36268 36269 /* Transports bindings 36270 * 1) key is the dataType 36271 * 2) the catchall symbol "*" can be used 36272 * 3) selection will start with transport dataType and THEN go to "*" if needed 36273 */ 36274 transports = {}, 36275 36276 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression 36277 allTypes = "*/".concat( "*" ), 36278 36279 // Document location 36280 ajaxLocation = window.location.href, 36281 36282 // Segment location into parts 36283 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; 36284 36285// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 36286function addToPrefiltersOrTransports( structure ) { 36287 36288 // dataTypeExpression is optional and defaults to "*" 36289 return function( dataTypeExpression, func ) { 36290 36291 if ( typeof dataTypeExpression !== "string" ) { 36292 func = dataTypeExpression; 36293 dataTypeExpression = "*"; 36294 } 36295 36296 var dataType, 36297 i = 0, 36298 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; 36299 36300 if ( jQuery.isFunction( func ) ) { 36301 // For each dataType in the dataTypeExpression 36302 while ( (dataType = dataTypes[i++]) ) { 36303 // Prepend if requested 36304 if ( dataType[0] === "+" ) { 36305 dataType = dataType.slice( 1 ) || "*"; 36306 (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); 36307 36308 // Otherwise append 36309 } else { 36310 (structure[ dataType ] = structure[ dataType ] || []).push( func ); 36311 } 36312 } 36313 } 36314 }; 36315} 36316 36317// Base inspection function for prefilters and transports 36318function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { 36319 36320 var inspected = {}, 36321 seekingTransport = ( structure === transports ); 36322 36323 function inspect( dataType ) { 36324 var selected; 36325 inspected[ dataType ] = true; 36326 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { 36327 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); 36328 if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { 36329 options.dataTypes.unshift( dataTypeOrTransport ); 36330 inspect( dataTypeOrTransport ); 36331 return false; 36332 } else if ( seekingTransport ) { 36333 return !( selected = dataTypeOrTransport ); 36334 } 36335 }); 36336 return selected; 36337 } 36338 36339 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); 36340} 36341 36342// A special extend for ajax options 36343// that takes "flat" options (not to be deep extended) 36344// Fixes #9887 36345function ajaxExtend( target, src ) { 36346 var key, deep, 36347 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 36348 36349 for ( key in src ) { 36350 if ( src[ key ] !== undefined ) { 36351 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; 36352 } 36353 } 36354 if ( deep ) { 36355 jQuery.extend( true, target, deep ); 36356 } 36357 36358 return target; 36359} 36360 36361/* Handles responses to an ajax request: 36362 * - finds the right dataType (mediates between content-type and expected dataType) 36363 * - returns the corresponding response 36364 */ 36365function ajaxHandleResponses( s, jqXHR, responses ) { 36366 36367 var ct, type, finalDataType, firstDataType, 36368 contents = s.contents, 36369 dataTypes = s.dataTypes; 36370 36371 // Remove auto dataType and get content-type in the process 36372 while ( dataTypes[ 0 ] === "*" ) { 36373 dataTypes.shift(); 36374 if ( ct === undefined ) { 36375 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); 36376 } 36377 } 36378 36379 // Check if we're dealing with a known content-type 36380 if ( ct ) { 36381 for ( type in contents ) { 36382 if ( contents[ type ] && contents[ type ].test( ct ) ) { 36383 dataTypes.unshift( type ); 36384 break; 36385 } 36386 } 36387 } 36388 36389 // Check to see if we have a response for the expected dataType 36390 if ( dataTypes[ 0 ] in responses ) { 36391 finalDataType = dataTypes[ 0 ]; 36392 } else {
vendor: 4,724 bytes, lines 36393-36583
36393 // Try convertible dataTypes 36394 for ( type in responses ) { 36395 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { 36396 finalDataType = type; 36397 break; 36398 } 36399 if ( !firstDataType ) { 36400 firstDataType = type; 36401 } 36402 } 36403 // Or just use first one 36404 finalDataType = finalDataType || firstDataType; 36405 } 36406 36407 // If we found a dataType 36408 // We add the dataType to the list if needed 36409 // and return the corresponding response 36410 if ( finalDataType ) { 36411 if ( finalDataType !== dataTypes[ 0 ] ) { 36412 dataTypes.unshift( finalDataType ); 36413 } 36414 return responses[ finalDataType ]; 36415 } 36416} 36417 36418/* Chain conversions given the request and the original response 36419 * Also sets the responseXXX fields on the jqXHR instance 36420 */ 36421function ajaxConvert( s, response, jqXHR, isSuccess ) { 36422 var conv2, current, conv, tmp, prev, 36423 converters = {}, 36424 // Work with a copy of dataTypes in case we need to modify it for conversion 36425 dataTypes = s.dataTypes.slice(); 36426 36427 // Create converters map with lowercased keys 36428 if ( dataTypes[ 1 ] ) { 36429 for ( conv in s.converters ) { 36430 converters[ conv.toLowerCase() ] = s.converters[ conv ]; 36431 } 36432 } 36433 36434 current = dataTypes.shift(); 36435 36436 // Convert to each sequential dataType 36437 while ( current ) { 36438 36439 if ( s.responseFields[ current ] ) { 36440 jqXHR[ s.responseFields[ current ] ] = response; 36441 } 36442 36443 // Apply the dataFilter if provided 36444 if ( !prev && isSuccess && s.dataFilter ) { 36445 response = s.dataFilter( response, s.dataType ); 36446 } 36447 36448 prev = current; 36449 current = dataTypes.shift(); 36450 36451 if ( current ) { 36452 36453 // There's only work to do if current dataType is non-auto 36454 if ( current === "*" ) { 36455 36456 current = prev; 36457 36458 // Convert response if prev dataType is non-auto and differs from current 36459 } else if ( prev !== "*" && prev !== current ) { 36460 36461 // Seek a direct converter 36462 conv = converters[ prev + " " + current ] || converters[ "* " + current ]; 36463 36464 // If none found, seek a pair 36465 if ( !conv ) { 36466 for ( conv2 in converters ) { 36467 36468 // If conv2 outputs current 36469 tmp = conv2.split( " " ); 36470 if ( tmp[ 1 ] === current ) { 36471 36472 // If prev can be converted to accepted input 36473 conv = converters[ prev + " " + tmp[ 0 ] ] || 36474 converters[ "* " + tmp[ 0 ] ]; 36475 if ( conv ) { 36476 // Condense equivalence converters 36477 if ( conv === true ) { 36478 conv = converters[ conv2 ]; 36479 36480 // Otherwise, insert the intermediate dataType 36481 } else if ( converters[ conv2 ] !== true ) { 36482 current = tmp[ 0 ]; 36483 dataTypes.unshift( tmp[ 1 ] ); 36484 } 36485 break; 36486 } 36487 } 36488 } 36489 } 36490 36491 // Apply converter (if not an equivalence) 36492 if ( conv !== true ) { 36493 36494 // Unless errors are allowed to bubble, catch and return them 36495 if ( conv && s[ "throws" ] ) { 36496 response = conv( response ); 36497 } else { 36498 try { 36499 response = conv( response ); 36500 } catch ( e ) { 36501 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; 36502 } 36503 } 36504 } 36505 } 36506 } 36507 } 36508 36509 return { state: "success", data: response }; 36510} 36511 36512jQuery.extend({ 36513 36514 // Counter for holding the number of active queries 36515 active: 0, 36516 36517 // Last-Modified header cache for next request 36518 lastModified: {}, 36519 etag: {}, 36520 36521 ajaxSettings: { 36522 url: ajaxLocation, 36523 type: "GET", 36524 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), 36525 global: true, 36526 processData: true, 36527 async: true, 36528 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 36529 /* 36530 timeout: 0, 36531 data: null, 36532 dataType: null, 36533 username: null, 36534 password: null, 36535 cache: null, 36536 throws: false, 36537 traditional: false, 36538 headers: {}, 36539 */ 36540 36541 accepts: { 36542 "*": allTypes, 36543 text: "text/plain", 36544 html: "text/html", 36545 xml: "application/xml, text/xml", 36546 json: "application/json, text/javascript" 36547 }, 36548 36549 contents: { 36550 xml: /xml/, 36551 html: /html/, 36552 json: /json/ 36553 }, 36554 36555 responseFields: { 36556 xml: "responseXML", 36557 text: "responseText", 36558 json: "responseJSON" 36559 }, 36560 36561 // Data converters 36562 // Keys separate source (or catchall "*") and destination types with a single space 36563 converters: { 36564 36565 // Convert anything to text 36566 "* text": String, 36567 36568 // Text to html (true = no transformation) 36569 "text html": true, 36570 36571 // Evaluate text as a json expression 36572 "text json": jQuery.parseJSON, 36573 36574 // Parse text as xml 36575 "text xml": jQuery.parseXML 36576 }, 36577 36578 // For options that shouldn't be deep extended: 36579 // you can add your own custom options here if 36580 // and when you create one that shouldn't be 36581 // deep extended (see ajaxExtend) 36582 flatOptions: { 36583 url: true,
36584 context: true 36585 } 36586 }, 36587 36588 // Creates a full fledged settings object into target 36589 // with both ajaxSettings and settings fields. 36590 // If target is omitted, writes into ajaxSettings. 36591 ajaxSetup: function( target, settings ) { 36592 return settings ? 36593 36594 // Building a settings object 36595 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : 36596 36597 // Extending ajaxSettings 36598 ajaxExtend( jQuery.ajaxSettings, target ); 36599 }, 36600 36601 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 36602 ajaxTransport: addToPrefiltersOrTransports( transports ), 36603 36604 // Main method 36605 ajax: function( url, options ) { 36606 36607 // If url is an object, simulate pre-1.5 signature 36608 if ( typeof url === "object" ) { 36609 options = url; 36610 url = undefined; 36611 } 36612 36613 // Force options to be an object 36614 options = options || {}; 36615 36616 var transport, 36617 // URL without anti-cache param 36618 cacheURL, 36619 // Response headers 36620 responseHeadersString, 36621 responseHeaders, 36622 // timeout handle 36623 timeoutTimer, 36624 // Cross-domain detection vars 36625 parts, 36626 // To know if global events are to be dispatched 36627 fireGlobals, 36628 // Loop variable 36629 i, 36630 // Create the final options object 36631 s = jQuery.ajaxSetup( {}, options ), 36632 // Callbacks context 36633 callbackContext = s.context || s, 36634 // Context for global events is callbackContext if it is a DOM node or jQuery collection 36635 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? 36636 jQuery( callbackContext ) : 36637 jQuery.event, 36638 // Deferreds 36639 deferred = jQuery.Deferred(), 36640 completeDeferred = jQuery.Callbacks("once memory"), 36641 // Status-dependent callbacks 36642 statusCode = s.statusCode || {}, 36643 // Headers (they are sent all at once) 36644 requestHeaders = {}, 36645 requestHeadersNames = {}, 36646 // The jqXHR state 36647 state = 0, 36648 // Default abort message 36649 strAbort = "canceled", 36650 // Fake xhr 36651 jqXHR = { 36652 readyState: 0, 36653 36654 // Builds headers hashtable if needed 36655 getResponseHeader: function( key ) { 36656 var match; 36657 if ( state === 2 ) { 36658 if ( !responseHeaders ) { 36659 responseHeaders = {}; 36660 while ( (match = rheaders.exec( responseHeadersString )) ) { 36661 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; 36662 } 36663 } 36664 match = responseHeaders[ key.toLowerCase() ]; 36665 } 36666 return match == null ? null : match; 36667 }, 36668 36669 // Raw string 36670 getAllResponseHeaders: function() { 36671 return state === 2 ? responseHeadersString : null; 36672 }, 36673 36674 // Caches the header 36675 setRequestHeader: function( name, value ) { 36676 var lname = name.toLowerCase(); 36677 if ( !state ) { 36678 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; 36679 requestHeaders[ name ] = value; 36680 } 36681 return this; 36682 }, 36683 36684 // Overrides response content-type header 36685 overrideMimeType: function( type ) { 36686 if ( !state ) { 36687 s.mimeType = type; 36688 } 36689 return this; 36690 }, 36691 36692 // Status-dependent callbacks 36693 statusCode: function( map ) { 36694 var code; 36695 if ( map ) { 36696 if ( state < 2 ) { 36697 for ( code in map ) { 36698 // Lazy-add the new callback in a way that preserves old ones 36699 statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; 36700 } 36701 } else { 36702 // Execute the appropriate callbacks 36703 jqXHR.always( map[ jqXHR.status ] ); 36704 } 36705 } 36706 return this; 36707 }, 36708 36709 // Cancel the request 36710 abort: function( statusText ) { 36711 var finalText = statusText || strAbort; 36712 if ( transport ) { 36713 transport.abort( finalText ); 36714 } 36715 done( 0, finalText ); 36716 return this; 36717 } 36718 }; 36719 36720 // Attach deferreds 36721 deferred.promise( jqXHR ).complete = completeDeferred.add; 36722 jqXHR.success = jqXHR.done; 36723 jqXHR.error = jqXHR.fail; 36724 36725 // Remove hash character (#7531: and string promotion) 36726 // Add protocol if not provided (prefilters might expect it) 36727 // Handle falsy url in the settings object (#10093: consistency with old signature) 36728 // We also use the url parameter if available 36729 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ) 36730 .replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); 36731 36732 // Alias method option to type as per ticket #12004 36733 s.type = options.method || options.type || s.method || s.type; 36734 36735 // Extract dataTypes list 36736 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; 36737 36738 // A cross-domain request is in order when we have a protocol:host:port mismatch 36739 if ( s.crossDomain == null ) { 36740 parts = rurl.exec( s.url.toLowerCase() ); 36741 s.crossDomain = !!( parts && 36742 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || 36743 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== 36744 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) 36745 ); 36746 } 36747 36748 // Convert data if not already a string 36749 if ( s.data && s.processData && typeof s.data !== "string" ) { 36750 s.data = jQuery.param( s.data, s.traditional ); 36751 } 36752 36753 // Apply prefilters 36754 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 36755 36756 // If request was aborted inside a prefilter, stop there 36757 if ( state === 2 ) { 36758 return jqXHR; 36759 } 36760 36761 // We can fire global events as of now if asked to 36762 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) 36763 fireGlobals = jQuery.event && s.global; 36764 36765 // Watch for a new set of requests 36766 if ( fireGlobals && jQuery.active++ === 0 ) { 36767 jQuery.event.trigger("ajaxStart"); 36768 } 36769 36770 // Uppercase the type 36771 s.type = s.type.toUpperCase(); 36772 36773 // Determine if request has content 36774 s.hasContent = !rnoContent.test( s.type ); 36775 36776 // Save the URL in case we're toying with the If-Modified-Since 36777 // and/or If-None-Match header later on 36778 cacheURL = s.url; 36779 36780 // More options handling for requests with no content 36781 if ( !s.hasContent ) { 36782 36783 // If data is available, append data to url 36784 if ( s.data ) {
36785 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); 36786 // #9682: remove data so that it's not used in an eventual retry 36787 delete s.data; 36788 } 36789 36790 // Add anti-cache in url if needed 36791 if ( s.cache === false ) { 36792 s.url = rts.test( cacheURL ) ? 36793 36794 // If there is already a '_' parameter, set its value 36795 cacheURL.replace( rts, "$1_=" + nonce++ ) : 36796 36797 // Otherwise add one to the end 36798 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; 36799 } 36800 } 36801 36802 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 36803 if ( s.ifModified ) { 36804 if ( jQuery.lastModified[ cacheURL ] ) { 36805 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); 36806 } 36807 if ( jQuery.etag[ cacheURL ] ) { 36808 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); 36809 } 36810 } 36811 36812 // Set the correct header, if data is being sent 36813 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 36814 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 36815 } 36816 36817 // Set the Accepts header for the server, depending on the dataType 36818 jqXHR.setRequestHeader( 36819 "Accept", 36820 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? 36821 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 36822 s.accepts[ "*" ] 36823 ); 36824 36825 // Check for headers option 36826 for ( i in s.headers ) { 36827 jqXHR.setRequestHeader( i, s.headers[ i ] ); 36828 } 36829 36830 // Allow custom headers/mimetypes and early abort 36831 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { 36832 // Abort if not done already and return 36833 return jqXHR.abort(); 36834 } 36835 36836 // Aborting is no longer a cancellation 36837 strAbort = "abort"; 36838 36839 // Install callbacks on deferreds 36840 for ( i in { success: 1, error: 1, complete: 1 } ) { 36841 jqXHR[ i ]( s[ i ] ); 36842 } 36843 36844 // Get transport 36845 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 36846 36847 // If no transport, we auto-abort 36848 if ( !transport ) { 36849 done( -1, "No Transport" ); 36850 } else { 36851 jqXHR.readyState = 1; 36852 36853 // Send global event 36854 if ( fireGlobals ) { 36855 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 36856 } 36857 // Timeout 36858 if ( s.async && s.timeout > 0 ) { 36859 timeoutTimer = setTimeout(function() { 36860 jqXHR.abort("timeout"); 36861 }, s.timeout ); 36862 } 36863 36864 try { 36865 state = 1; 36866 transport.send( requestHeaders, done ); 36867 } catch ( e ) { 36868 // Propagate exception as error if not done 36869 if ( state < 2 ) { 36870 done( -1, e ); 36871 // Simply rethrow otherwise 36872 } else { 36873 throw e; 36874 } 36875 } 36876 } 36877 36878 // Callback for when everything is done 36879 function done( status, nativeStatusText, responses, headers ) { 36880 var isSuccess, success, error, response, modified, 36881 statusText = nativeStatusText; 36882 36883 // Called once 36884 if ( state === 2 ) { 36885 return; 36886 } 36887 36888 // State is "done" now 36889 state = 2; 36890 36891 // Clear timeout if it exists 36892 if ( timeoutTimer ) { 36893 clearTimeout( timeoutTimer ); 36894 } 36895 36896 // Dereference transport for early garbage collection 36897 // (no matter how long the jqXHR object will be used) 36898 transport = undefined; 36899 36900 // Cache response headers 36901 responseHeadersString = headers || ""; 36902 36903 // Set readyState 36904 jqXHR.readyState = status > 0 ? 4 : 0; 36905 36906 // Determine if successful 36907 isSuccess = status >= 200 && status < 300 || status === 304; 36908 36909 // Get response data 36910 if ( responses ) { 36911 response = ajaxHandleResponses( s, jqXHR, responses ); 36912 } 36913 36914 // Convert no matter what (that way responseXXX fields are always set) 36915 response = ajaxConvert( s, response, jqXHR, isSuccess ); 36916 36917 // If successful, handle type chaining 36918 if ( isSuccess ) { 36919 36920 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 36921 if ( s.ifModified ) { 36922 modified = jqXHR.getResponseHeader("Last-Modified"); 36923 if ( modified ) { 36924 jQuery.lastModified[ cacheURL ] = modified; 36925 } 36926 modified = jqXHR.getResponseHeader("etag"); 36927 if ( modified ) { 36928 jQuery.etag[ cacheURL ] = modified; 36929 } 36930 } 36931 36932 // if no content 36933 if ( status === 204 || s.type === "HEAD" ) { 36934 statusText = "nocontent"; 36935 36936 // if not modified 36937 } else if ( status === 304 ) { 36938 statusText = "notmodified"; 36939 36940 // If we have data, let's convert it 36941 } else { 36942 statusText = response.state; 36943 success = response.data; 36944 error = response.error; 36945 isSuccess = !error; 36946 } 36947 } else { 36948 // Extract error from statusText and normalize for non-aborts 36949 error = statusText; 36950 if ( status || !statusText ) { 36951 statusText = "error"; 36952 if ( status < 0 ) { 36953 status = 0; 36954 } 36955 } 36956 } 36957 36958 // Set data for the fake xhr object 36959 jqXHR.status = status; 36960 jqXHR.statusText = ( nativeStatusText || statusText ) + ""; 36961 36962 // Success/Error 36963 if ( isSuccess ) { 36964 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 36965 } else { 36966 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 36967 } 36968 36969 // Status-dependent callbacks 36970 jqXHR.statusCode( statusCode ); 36971 statusCode = undefined; 36972 36973 if ( fireGlobals ) { 36974 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", 36975 [ jqXHR, s, isSuccess ? success : error ] ); 36976 } 36977 36978 // Complete 36979 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 36980 36981 if ( fireGlobals ) { 36982 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 36983 // Handle the global AJAX counter 36984 if ( !( --jQuery.active ) ) { 36985 jQuery.event.trigger("ajaxStop"); 36986 } 36987 } 36988 } 36989 36990 return jqXHR; 36991 }, 36992 36993 getJSON: function( url, data, callback ) { 36994 return jQuery.get( url, data, callback, "json" ); 36995 }, 36996 36997 getScript: function( url, callback ) { 36998 return jQuery.get( url, undefined, callback, "script" ); 36999 } 37000}); 37001 37002jQuery.each( [ "get", "post" ], function( i, method ) { 37003 jQuery[ method ] = function( url, data, callback, type ) { 37004 // Shift arguments if data argument was omitted 37005 if ( jQuery.isFunction( data ) ) { 37006 type = type || callback; 37007 callback = data; 37008 data = undefined; 37009 } 37010 37011 return jQuery.ajax({ 37012 url: url, 37013 type: method, 37014 dataType: type, 37015 data: data, 37016 success: callback 37017 }); 37018 }; 37019}); 37020 37021 37022jQuery._evalUrl = function( url ) { 37023 return jQuery.ajax({ 37024 url: url, 37025 type: "GET", 37026 dataType: "script", 37027 async: false, 37028 global: false, 37029 "throws": true 37030 }); 37031}; 37032 37033 37034jQuery.fn.extend({ 37035 wrapAll: function( html ) { 37036 var wrap; 37037 37038 if ( jQuery.isFunction( html ) ) { 37039 return this.each(function( i ) { 37040 jQuery( this ).wrapAll( html.call(this, i) ); 37041 }); 37042 } 37043 37044 if ( this[ 0 ] ) { 37045 37046 // The elements to wrap the target around 37047 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); 37048 37049 if ( this[ 0 ].parentNode ) { 37050 wrap.insertBefore( this[ 0 ] ); 37051 } 37052 37053 wrap.map(function() { 37054 var elem = this; 37055 37056 while ( elem.firstElementChild ) { 37057 elem = elem.firstElementChild; 37058 } 37059 37060 return elem; 37061 }).append( this ); 37062 } 37063 37064 return this; 37065 }, 37066 37067 wrapInner: function( html ) { 37068 if ( jQuery.isFunction( html ) ) { 37069 return this.each(function( i ) { 37070 jQuery( this ).wrapInner( html.call(this, i) ); 37071 }); 37072 } 37073 37074 return this.each(function() { 37075 var self = jQuery( this ), 37076 contents = self.contents(); 37077 37078 if ( contents.length ) { 37079 contents.wrapAll( html ); 37080 37081 } else { 37082 self.append( html ); 37083 } 37084 }); 37085 }, 37086 37087 wrap: function( html ) { 37088 var isFunction = jQuery.isFunction( html ); 37089 37090 return this.each(function( i ) { 37091 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); 37092 }); 37093 }, 37094 37095 unwrap: function() { 37096 return this.parent().each(function() { 37097 if ( !jQuery.nodeName( this, "body" ) ) { 37098 jQuery( this ).replaceWith( this.childNodes ); 37099 } 37100 }).end(); 37101 } 37102}); 37103 37104 37105jQuery.expr.filters.hidden = function( elem ) { 37106 // Support: Opera <= 12.12 37107 // Opera reports offsetWidths and offsetHeights less than zero on some elements 37108 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
37109}; 37110jQuery.expr.filters.visible = function( elem ) { 37111 return !jQuery.expr.filters.hidden( elem ); 37112}; 37113 37114 37115 37116 37117var r20 = /%20/g, 37118 rbracket = /\[\]$/, 37119 rCRLF = /\r?\n/g, 37120 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 37121 rsubmittable = /^(?:input|select|textarea|keygen)/i; 37122 37123function buildParams( prefix, obj, traditional, add ) { 37124 var name; 37125 37126 if ( jQuery.isArray( obj ) ) { 37127 // Serialize array item. 37128 jQuery.each( obj, function( i, v ) { 37129 if ( traditional || rbracket.test( prefix ) ) { 37130 // Treat each array item as a scalar. 37131 add( prefix, v ); 37132 37133 } else { 37134 // Item is non-scalar (array or object), encode its numeric index. 37135 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); 37136 } 37137 }); 37138 37139 } else if ( !traditional && jQuery.type( obj ) === "object" ) { 37140 // Serialize object item. 37141 for ( name in obj ) { 37142 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 37143 } 37144 37145 } else { 37146 // Serialize scalar item. 37147 add( prefix, obj ); 37148 } 37149} 37150 37151// Serialize an array of form elements or a set of 37152// key/values into a query string 37153jQuery.param = function( a, traditional ) { 37154 var prefix, 37155 s = [], 37156 add = function( key, value ) { 37157 // If value is a function, invoke it and return its value 37158 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); 37159 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); 37160 }; 37161 37162 // Set traditional to true for jQuery <= 1.3.2 behavior. 37163 if ( traditional === undefined ) { 37164 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; 37165 } 37166 37167 // If an array was passed in, assume that it is an array of form elements. 37168 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 37169 // Serialize the form elements 37170 jQuery.each( a, function() { 37171 add( this.name, this.value ); 37172 }); 37173 37174 } else { 37175 // If traditional, encode the "old" way (the way 1.3.2 or older 37176 // did it), otherwise encode params recursively. 37177 for ( prefix in a ) { 37178 buildParams( prefix, a[ prefix ], traditional, add ); 37179 } 37180 } 37181 37182 // Return the resulting serialization 37183 return s.join( "&" ).replace( r20, "+" ); 37184}; 37185 37186jQuery.fn.extend({ 37187 serialize: function() { 37188 return jQuery.param( this.serializeArray() ); 37189 }, 37190 serializeArray: function() { 37191 return this.map(function() { 37192 // Can add propHook for "elements" to filter or add form elements 37193 var elements = jQuery.prop( this, "elements" ); 37194 return elements ? jQuery.makeArray( elements ) : this; 37195 }) 37196 .filter(function() { 37197 var type = this.type; 37198 37199 // Use .is( ":disabled" ) so that fieldset[disabled] works 37200 return this.name && !jQuery( this ).is( ":disabled" ) && 37201 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && 37202 ( this.checked || !rcheckableType.test( type ) ); 37203 }) 37204 .map(function( i, elem ) { 37205 var val = jQuery( this ).val(); 37206 37207 return val == null ? 37208 null : 37209 jQuery.isArray( val ) ? 37210 jQuery.map( val, function( val ) { 37211 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 37212 }) : 37213 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 37214 }).get(); 37215 } 37216}); 37217 37218 37219jQuery.ajaxSettings.xhr = function() { 37220 try { 37221 return new XMLHttpRequest(); 37222 } catch( e ) {} 37223}; 37224 37225var xhrId = 0, 37226 xhrCallbacks = {}, 37227 xhrSuccessStatus = { 37228 // file protocol always yields status code 0, assume 200 37229 0: 200, 37230 // Support: IE9 37231 // #1450: sometimes IE returns 1223 when it should be 204 37232 1223: 204 37233 }, 37234 xhrSupported = jQuery.ajaxSettings.xhr(); 37235 37236// Support: IE9 37237// Open requests must be manually aborted on unload (#5280) 37238// See https://support.microsoft.com/kb/2856746 for more info 37239if ( window.attachEvent ) { 37240 window.attachEvent( "onunload", function() { 37241 for ( var key in xhrCallbacks ) { 37242 xhrCallbacks[ key ](); 37243 } 37244 }); 37245} 37246 37247support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 37248support.ajax = xhrSupported = !!xhrSupported; 37249 37250jQuery.ajaxTransport(function( options ) { 37251 var callback; 37252 37253 // Cross domain only allowed if supported through XMLHttpRequest 37254 if ( support.cors || xhrSupported && !options.crossDomain ) { 37255 return { 37256 send: function( headers, complete ) { 37257 var i, 37258 xhr = options.xhr(), 37259 id = ++xhrId; 37260 37261 xhr.open( options.type, options.url, options.async, options.username, options.password ); 37262 37263 // Apply custom fields if provided 37264 if ( options.xhrFields ) { 37265 for ( i in options.xhrFields ) { 37266 xhr[ i ] = options.xhrFields[ i ]; 37267 } 37268 } 37269 37270 // Override mime type if needed 37271 if ( options.mimeType && xhr.overrideMimeType ) { 37272 xhr.overrideMimeType( options.mimeType ); 37273 } 37274 37275 // X-Requested-With header 37276 // For cross-domain requests, seeing as conditions for a preflight are 37277 // akin to a jigsaw puzzle, we simply never set it to be sure. 37278 // (it can always be set on a per-request basis or even using ajaxSetup)
37279 // For same-domain requests, won't change header if already provided. 37280 if ( !options.crossDomain && !headers["X-Requested-With"] ) { 37281 headers["X-Requested-With"] = "XMLHttpRequest"; 37282 } 37283 37284 // Set headers 37285 for ( i in headers ) { 37286 xhr.setRequestHeader( i, headers[ i ] ); 37287 } 37288 37289 // Callback 37290 callback = function( type ) { 37291 return function() { 37292 if ( callback ) { 37293 delete xhrCallbacks[ id ]; 37294 callback = xhr.onload = xhr.onerror = null; 37295 37296 if ( type === "abort" ) { 37297 xhr.abort(); 37298 } else if ( type === "error" ) { 37299 complete( 37300 // file: protocol always yields status 0; see #8605, #14207 37301 xhr.status, 37302 xhr.statusText 37303 ); 37304 } else { 37305 complete( 37306 xhrSuccessStatus[ xhr.status ] || xhr.status, 37307 xhr.statusText, 37308 // Support: IE9 37309 // Accessing binary-data responseText throws an exception 37310 // (#11426) 37311 typeof xhr.responseText === "string" ? { 37312 text: xhr.responseText 37313 } : undefined, 37314 xhr.getAllResponseHeaders() 37315 ); 37316 } 37317 } 37318 }; 37319 }; 37320 37321 // Listen to events 37322 xhr.onload = callback(); 37323 xhr.onerror = callback("error"); 37324 37325 // Create the abort callback 37326 callback = xhrCallbacks[ id ] = callback("abort"); 37327 37328 try { 37329 // Do send the request (this may raise an exception) 37330 xhr.send( options.hasContent && options.data || null ); 37331 } catch ( e ) { 37332 // #14683: Only rethrow if this hasn't been notified as an error yet 37333 if ( callback ) { 37334 throw e; 37335 } 37336 } 37337 }, 37338 37339 abort: function() { 37340 if ( callback ) { 37341 callback(); 37342 } 37343 } 37344 }; 37345 } 37346}); 37347 37348 37349 37350 37351// Install script dataType 37352jQuery.ajaxSetup({ 37353 accepts: { 37354 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" 37355 }, 37356 contents: { 37357 script: /(?:java|ecma)script/ 37358 }, 37359 converters: { 37360 "text script": function( text ) { 37361 jQuery.globalEval( text ); 37362 return text; 37363 } 37364 } 37365}); 37366 37367// Handle cache's special case and crossDomain 37368jQuery.ajaxPrefilter( "script", function( s ) { 37369 if ( s.cache === undefined ) { 37370 s.cache = false; 37371 } 37372 if ( s.crossDomain ) { 37373 s.type = "GET"; 37374 } 37375}); 37376 37377// Bind script tag hack transport 37378jQuery.ajaxTransport( "script", function( s ) { 37379 // This transport only deals with cross domain requests 37380 if ( s.crossDomain ) { 37381 var script, callback; 37382 return { 37383 send: function( _, complete ) { 37384 script = jQuery("<script>").prop({ 37385 async: true, 37386 charset: s.scriptCharset, 37387 src: s.url 37388 }).on( 37389 "load error", 37390 callback = function( evt ) { 37391 script.remove(); 37392 callback = null; 37393 if ( evt ) { 37394 complete( evt.type === "error" ? 404 : 200, evt.type ); 37395 } 37396 } 37397 ); 37398 document.head.appendChild( script[ 0 ] ); 37399 }, 37400 abort: function() { 37401 if ( callback ) { 37402 callback(); 37403 } 37404 } 37405 }; 37406 } 37407}); 37408 37409 37410 37411 37412var oldCallbacks = [], 37413 rjsonp = /(=)\?(?=&|$)|\?\?/; 37414 37415// Default jsonp settings 37416jQuery.ajaxSetup({ 37417 jsonp: "callback", 37418 jsonpCallback: function() { 37419 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); 37420 this[ callback ] = true; 37421 return callback; 37422 } 37423}); 37424 37425// Detect, normalize options and install callbacks for jsonp requests 37426jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 37427 37428 var callbackName, overwritten, responseContainer, 37429 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 37430 "url" : 37431 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" 37432 ); 37433 37434 // Handle iff the expected data type is "jsonp" or we have a parameter to set 37435 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 37436 37437 // Get callback name, remembering preexisting value associated with it 37438 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? 37439 s.jsonpCallback() : 37440 s.jsonpCallback; 37441 37442 // Insert callback into url or form data 37443 if ( jsonProp ) { 37444 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 37445 } else if ( s.jsonp !== false ) { 37446 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 37447 } 37448 37449 // Use data converter to retrieve json after script execution
37450 s.converters["script json"] = function() { 37451 if ( !responseContainer ) { 37452 jQuery.error( callbackName + " was not called" ); 37453 } 37454 return responseContainer[ 0 ]; 37455 }; 37456 37457 // force json dataType 37458 s.dataTypes[ 0 ] = "json"; 37459 37460 // Install callback 37461 overwritten = window[ callbackName ]; 37462 window[ callbackName ] = function() { 37463 responseContainer = arguments; 37464 }; 37465 37466 // Clean-up function (fires after converters) 37467 jqXHR.always(function() { 37468 // Restore preexisting value 37469 window[ callbackName ] = overwritten; 37470 37471 // Save back as free 37472 if ( s[ callbackName ] ) { 37473 // make sure that re-using the options doesn't screw things around 37474 s.jsonpCallback = originalSettings.jsonpCallback; 37475 37476 // save the callback name for future use 37477 oldCallbacks.push( callbackName ); 37478 } 37479 37480 // Call if it was a function and we have a response 37481 if ( responseContainer && jQuery.isFunction( overwritten ) ) { 37482 overwritten( responseContainer[ 0 ] ); 37483 } 37484 37485 responseContainer = overwritten = undefined; 37486 }); 37487 37488 // Delegate to script 37489 return "script"; 37490 } 37491}); 37492 37493 37494 37495 37496// data: string of html 37497// context (optional): If specified, the fragment will be created in this context, defaults to document 37498// keepScripts (optional): If true, will include scripts passed in the html string 37499jQuery.parseHTML = function( data, context, keepScripts ) { 37500 if ( !data || typeof data !== "string" ) { 37501 return null; 37502 } 37503 if ( typeof context === "boolean" ) { 37504 keepScripts = context; 37505 context = false; 37506 } 37507 context = context || document; 37508 37509 var parsed = rsingleTag.exec( data ), 37510 scripts = !keepScripts && []; 37511 37512 // Single tag 37513 if ( parsed ) { 37514 return [ context.createElement( parsed[1] ) ]; 37515 } 37516 37517 parsed = jQuery.buildFragment( [ data ], context, scripts ); 37518 37519 if ( scripts && scripts.length ) {
37520 jQuery( scripts ).remove(); 37521 } 37522 37523 return jQuery.merge( [], parsed.childNodes ); 37524}; 37525 37526 37527// Keep a copy of the old load method 37528var _load = jQuery.fn.load; 37529 37530/** 37531 * Load a url into a page 37532 */ 37533jQuery.fn.load = function( url, params, callback ) { 37534 if ( typeof url !== "string" && _load ) { 37535 return _load.apply( this, arguments ); 37536 } 37537 37538 var selector, type, response, 37539 self = this, 37540 off = url.indexOf(" "); 37541 37542 if ( off >= 0 ) { 37543 selector = jQuery.trim( url.slice( off ) ); 37544 url = url.slice( 0, off ); 37545 } 37546 37547 // If it's a function 37548 if ( jQuery.isFunction( params ) ) { 37549 37550 // We assume that it's the callback 37551 callback = params; 37552 params = undefined; 37553 37554 // Otherwise, build a param string 37555 } else if ( params && typeof params === "object" ) { 37556 type = "POST"; 37557 } 37558 37559 // If we have elements to modify, make the request 37560 if ( self.length > 0 ) { 37561 jQuery.ajax({ 37562 url: url, 37563 37564 // if "type" variable is undefined, then "GET" method will be used 37565 type: type, 37566 dataType: "html", 37567 data: params 37568 }).done(function( responseText ) { 37569 37570 // Save response for use in complete callback 37571 response = arguments; 37572 37573 self.html( selector ? 37574 37575 // If a selector was specified, locate the right elements in a dummy div 37576 // Exclude scripts to avoid IE 'Permission Denied' errors 37577 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : 37578 37579 // Otherwise use the full result 37580 responseText ); 37581 37582 }).complete( callback && function( jqXHR, status ) { 37583 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); 37584 }); 37585 } 37586 37587 return this; 37588}; 37589 37590 37591 37592 37593// Attach a bunch of functions for handling common AJAX events 37594jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { 37595 jQuery.fn[ type ] = function( fn ) { 37596 return this.on( type, fn ); 37597 }; 37598}); 37599 37600 37601 37602 37603jQuery.expr.filters.animated = function( elem ) { 37604 return jQuery.grep(jQuery.timers, function( fn ) { 37605 return elem === fn.elem; 37606 }).length; 37607}; 37608 37609 37610 37611 37612var docElem = window.document.documentElement; 37613 37614/** 37615 * Gets a window from an element 37616 */ 37617function getWindow( elem ) { 37618 return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView; 37619} 37620 37621jQuery.offset = { 37622 setOffset: function( elem, options, i ) { 37623 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, 37624 position = jQuery.css( elem, "position" ), 37625 curElem = jQuery( elem ), 37626 props = {}; 37627 37628 // Set position first, in-case top/left are set even on static elem 37629 if ( position === "static" ) { 37630 elem.style.position = "relative"; 37631 } 37632 37633 curOffset = curElem.offset(); 37634 curCSSTop = jQuery.css( elem, "top" ); 37635 curCSSLeft = jQuery.css( elem, "left" ); 37636 calculatePosition = ( position === "absolute" || position === "fixed" ) && 37637 ( curCSSTop + curCSSLeft ).indexOf("auto") > -1; 37638 37639 // Need to be able to calculate position if either 37640 // top or left is auto and position is either absolute or fixed 37641 if ( calculatePosition ) { 37642 curPosition = curElem.position(); 37643 curTop = curPosition.top; 37644 curLeft = curPosition.left; 37645 37646 } else { 37647 curTop = parseFloat( curCSSTop ) || 0; 37648 curLeft = parseFloat( curCSSLeft ) || 0; 37649 } 37650 37651 if ( jQuery.isFunction( options ) ) { 37652 options = options.call( elem, i, curOffset ); 37653 } 37654 37655 if ( options.top != null ) { 37656 props.top = ( options.top - curOffset.top ) + curTop; 37657 } 37658 if ( options.left != null ) { 37659 props.left = ( options.left - curOffset.left ) + curLeft; 37660 } 37661 37662 if ( "using" in options ) { 37663 options.using.call( elem, props ); 37664 37665 } else { 37666 curElem.css( props ); 37667 } 37668 } 37669}; 37670 37671jQuery.fn.extend({ 37672 offset: function( options ) { 37673 if ( arguments.length ) { 37674 return options === undefined ? 37675 this : 37676 this.each(function( i ) { 37677 jQuery.offset.setOffset( this, options, i ); 37678 }); 37679 } 37680 37681 var docElem, win, 37682 elem = this[ 0 ], 37683 box = { top: 0, left: 0 }, 37684 doc = elem && elem.ownerDocument; 37685 37686 if ( !doc ) { 37687 return; 37688 } 37689 37690 docElem = doc.documentElement; 37691 37692 // Make sure it's not a disconnected DOM node 37693 if ( !jQuery.contains( docElem, elem ) ) { 37694 return box; 37695 } 37696
37697 // Support: BlackBerry 5, iOS 3 (original iPhone) 37698 // If we don't have gBCR, just use 0,0 rather than error 37699 if ( typeof elem.getBoundingClientRect !== strundefined ) { 37700 box = elem.getBoundingClientRect(); 37701 } 37702 win = getWindow( doc ); 37703 return { 37704 top: box.top + win.pageYOffset - docElem.clientTop, 37705 left: box.left + win.pageXOffset - docElem.clientLeft 37706 }; 37707 }, 37708 37709 position: function() { 37710 if ( !this[ 0 ] ) { 37711 return; 37712 } 37713 37714 var offsetParent, offset, 37715 elem = this[ 0 ], 37716 parentOffset = { top: 0, left: 0 }; 37717 37718 // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent 37719 if ( jQuery.css( elem, "position" ) === "fixed" ) { 37720 // Assume getBoundingClientRect is there when computed position is fixed 37721 offset = elem.getBoundingClientRect(); 37722 37723 } else { 37724 // Get *real* offsetParent 37725 offsetParent = this.offsetParent(); 37726 37727 // Get correct offsets 37728 offset = this.offset(); 37729 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { 37730 parentOffset = offsetParent.offset(); 37731 } 37732 37733 // Add offsetParent borders 37734 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); 37735 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); 37736 } 37737 37738 // Subtract parent offsets and element margins 37739 return { 37740 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), 37741 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) 37742 }; 37743 }, 37744 37745 offsetParent: function() { 37746 return this.map(function() { 37747 var offsetParent = this.offsetParent || docElem; 37748 37749 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) { 37750 offsetParent = offsetParent.offsetParent; 37751 } 37752 37753 return offsetParent || docElem; 37754 }); 37755 } 37756}); 37757 37758// Create scrollLeft and scrollTop methods 37759jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { 37760 var top = "pageYOffset" === prop; 37761 37762 jQuery.fn[ method ] = function( val ) { 37763 return access( this, function( elem, method, val ) { 37764 var win = getWindow( elem ); 37765 37766 if ( val === undefined ) { 37767 return win ? win[ prop ] : elem[ method ]; 37768 } 37769 37770 if ( win ) { 37771 win.scrollTo( 37772 !top ? val : window.pageXOffset, 37773 top ? val : window.pageYOffset 37774 ); 37775 37776 } else { 37777 elem[ method ] = val; 37778 } 37779 }, method, val, arguments.length, null ); 37780 }; 37781}); 37782 37783// Support: Safari<7+, Chrome<37+ 37784// Add the top/left cssHooks using jQuery.fn.position 37785// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 37786// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280 37787// getComputedStyle returns percent when specified for top/left/bottom/right; 37788// rather than make the css module depend on the offset module, just check for it here 37789jQuery.each( [ "top", "left" ], function( i, prop ) { 37790 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, 37791 function( elem, computed ) { 37792 if ( computed ) { 37793 computed = curCSS( elem, prop ); 37794 // If curCSS returns percentage, fallback to offset 37795 return rnumnonpx.test( computed ) ? 37796 jQuery( elem ).position()[ prop ] + "px" : 37797 computed; 37798 } 37799 } 37800 ); 37801}); 37802 37803 37804// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 37805jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { 37806 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { 37807 // Margin is only for outerHeight, outerWidth 37808 jQuery.fn[ funcName ] = function( margin, value ) { 37809 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), 37810 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); 37811 37812 return access( this, function( elem, type, value ) { 37813 var doc; 37814 37815 if ( jQuery.isWindow( elem ) ) { 37816 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there 37817 // isn't a whole lot we can do. See pull request at this URL for discussion: 37818 // https://github.com/jquery/jquery/pull/764 37819 return elem.document.documentElement[ "client" + name ]; 37820 } 37821 37822 // Get document width or height 37823 if ( elem.nodeType === 9 ) { 37824 doc = elem.documentElement; 37825 37826 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], 37827 // whichever is greatest 37828 return Math.max( 37829 elem.body[ "scroll" + name ], doc[ "scroll" + name ], 37830 elem.body[ "offset" + name ], doc[ "offset" + name ], 37831 doc[ "client" + name ] 37832 ); 37833 } 37834 37835 return value === undefined ? 37836 // Get width or height on the element, requesting but not forcing parseFloat 37837 jQuery.css( elem, type, extra ) : 37838 37839 // Set width or height on the element 37840 jQuery.style( elem, type, value, extra ); 37841 }, type, chainable ? margin : undefined, chainable, null ); 37842 }; 37843 }); 37844}); 37845 37846 37847// The number of elements contained in the matched element set 37848jQuery.fn.size = function() { 37849 return this.length; 37850}; 37851 37852jQuery.fn.andSelf = jQuery.fn.addBack; 37853 37854 37855 37856 37857// Register as a named AMD module, since jQuery can be concatenated with other 37858// files that may use define, but not via a proper concatenation script that 37859// understands anonymous AMD modules. A named AMD is safest and most robust 37860// way to register. Lowercase jquery is used because AMD module names are 37861// derived from file names, and jQuery is normally delivered in a lowercase 37862// file name. Do this after creating the global so that if an AMD module wants 37863// to call noConflict to hide this version of jQuery, it will work. 37864 37865// Note that for maximum portability, libraries that are not jQuery should 37866// declare themselves as anonymous modules, and avoid setting a global if an 37867// AMD loader is present. jQuery is a special case. For more information, see 37868// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon 37869 37870if ( typeof define === "function" && define.amd ) { 37871 define( "jquery", [], function() { 37872 return jQuery; 37873 }); 37874} 37875 37876 37877 37878 37879var 37880 // Map over jQuery in case of overwrite 37881 _jQuery = window.jQuery, 37882 37883 // Map over the $ in case of overwrite 37884 _$ = window.$; 37885 37886jQuery.noConflict = function( deep ) { 37887 if ( window.$ === jQuery ) { 37888 window.$ = _$; 37889 } 37890 37891 if ( deep && window.jQuery === jQuery ) { 37892 window.jQuery = _jQuery; 37893 } 37894 37895 return jQuery; 37896}; 37897 37898// Expose jQuery and $ identifiers, even in AMD 37899// (#7102#comment:10, https://github.com/jquery/jquery/pull/557) 37900 // and CommonJS for browser emulators (#13566) 37901 /* 37902if ( typeof noGlobal === strundefined ) { 37903 window.jQuery = window.$ = jQuery; 37904} 37905*/ 37906 37907 37908 37909return jQuery; 37910 37911})); 37912 37913}, 37914'jquery-ui/ui/dialog':function(){ 37915/*! 37916 * jQuery UI Dialog 1.11.2 37917 * http://jqueryui.com
vendor: 20,485 bytes, lines 37918-38700
37918 * 37919 * Copyright 2014 jQuery Foundation and other contributors 37920 * Released under the MIT license. 37921 * http://jquery.org/license 37922 * 37923 * http://api.jqueryui.com/dialog/ 37924 */ 37925(function( factory ) { 37926 if ( typeof define === "function" && define.amd ) { 37927 37928 // AMD. Register as an anonymous module. 37929 define([ 37930 "jquery", 37931 "./core", 37932 "./widget", 37933 "./button", 37934 "./draggable", 37935 "./mouse", 37936 "./position", 37937 "./resizable" 37938 ], factory ); 37939 } else { 37940 37941 // Browser globals 37942 factory( jQuery ); 37943 } 37944}(function( $ ) { 37945 37946return $.widget( "ui.dialog", { 37947 version: "1.11.2", 37948 options: { 37949 appendTo: "body", 37950 autoOpen: true, 37951 buttons: [], 37952 closeOnEscape: true, 37953 closeText: "Close", 37954 dialogClass: "", 37955 draggable: true, 37956 hide: null, 37957 height: "auto", 37958 maxHeight: null, 37959 maxWidth: null, 37960 minHeight: 150, 37961 minWidth: 150, 37962 modal: false, 37963 position: { 37964 my: "center", 37965 at: "center", 37966 of: window, 37967 collision: "fit", 37968 // Ensure the titlebar is always visible 37969 using: function( pos ) { 37970 var topOffset = $( this ).css( pos ).offset().top; 37971 if ( topOffset < 0 ) { 37972 $( this ).css( "top", pos.top - topOffset ); 37973 } 37974 } 37975 }, 37976 resizable: true, 37977 show: null, 37978 title: null, 37979 width: 300, 37980 37981 // callbacks 37982 beforeClose: null, 37983 close: null, 37984 drag: null, 37985 dragStart: null, 37986 dragStop: null, 37987 focus: null, 37988 open: null, 37989 resize: null, 37990 resizeStart: null, 37991 resizeStop: null 37992 }, 37993 37994 sizeRelatedOptions: { 37995 buttons: true, 37996 height: true, 37997 maxHeight: true, 37998 maxWidth: true, 37999 minHeight: true, 38000 minWidth: true, 38001 width: true 38002 }, 38003 38004 resizableRelatedOptions: { 38005 maxHeight: true, 38006 maxWidth: true, 38007 minHeight: true, 38008 minWidth: true 38009 }, 38010 38011 _create: function() { 38012 this.originalCss = { 38013 display: this.element[ 0 ].style.display, 38014 width: this.element[ 0 ].style.width, 38015 minHeight: this.element[ 0 ].style.minHeight, 38016 maxHeight: this.element[ 0 ].style.maxHeight, 38017 height: this.element[ 0 ].style.height 38018 }; 38019 this.originalPosition = { 38020 parent: this.element.parent(), 38021 index: this.element.parent().children().index( this.element ) 38022 }; 38023 this.originalTitle = this.element.attr( "title" ); 38024 this.options.title = this.options.title || this.originalTitle; 38025 38026 this._createWrapper(); 38027 38028 this.element 38029 .show() 38030 .removeAttr( "title" ) 38031 .addClass( "ui-dialog-content ui-widget-content" ) 38032 .appendTo( this.uiDialog ); 38033 38034 this._createTitlebar(); 38035 this._createButtonPane(); 38036 38037 if ( this.options.draggable && $.fn.draggable ) { 38038 this._makeDraggable(); 38039 } 38040 if ( this.options.resizable && $.fn.resizable ) { 38041 this._makeResizable(); 38042 } 38043 38044 this._isOpen = false; 38045 38046 this._trackFocus(); 38047 }, 38048 38049 _init: function() { 38050 if ( this.options.autoOpen ) { 38051 this.open(); 38052 } 38053 }, 38054 38055 _appendTo: function() { 38056 var element = this.options.appendTo; 38057 if ( element && (element.jquery || element.nodeType) ) { 38058 return $( element ); 38059 } 38060 return this.document.find( element || "body" ).eq( 0 ); 38061 }, 38062 38063 _destroy: function() { 38064 var next, 38065 originalPosition = this.originalPosition; 38066 38067 this._destroyOverlay(); 38068 38069 this.element 38070 .removeUniqueId() 38071 .removeClass( "ui-dialog-content ui-widget-content" ) 38072 .css( this.originalCss ) 38073 // Without detaching first, the following becomes really slow 38074 .detach(); 38075 38076 this.uiDialog.stop( true, true ).remove(); 38077 38078 if ( this.originalTitle ) { 38079 this.element.attr( "title", this.originalTitle ); 38080 } 38081 38082 next = originalPosition.parent.children().eq( originalPosition.index ); 38083 // Don't try to place the dialog next to itself (#8613) 38084 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { 38085 next.before( this.element ); 38086 } else { 38087 originalPosition.parent.append( this.element ); 38088 } 38089 }, 38090 38091 widget: function() { 38092 return this.uiDialog; 38093 }, 38094 38095 disable: $.noop, 38096 enable: $.noop, 38097 38098 close: function( event ) { 38099 var activeElement, 38100 that = this; 38101 38102 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 38103 return; 38104 } 38105 38106 this._isOpen = false; 38107 this._focusedElement = null; 38108 this._destroyOverlay(); 38109 this._untrackInstance(); 38110 38111 if ( !this.opener.filter( ":focusable" ).focus().length ) { 38112 38113 // support: IE9 38114 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 38115 try { 38116 activeElement = this.document[ 0 ].activeElement; 38117 38118 // Support: IE9, IE10 38119 // If the <body> is blurred, IE will switch windows, see #4520 38120 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { 38121 38122 // Hiding a focused element doesn't trigger blur in WebKit 38123 // so in case we have nothing to focus on, explicitly blur the active element 38124 // https://bugs.webkit.org/show_bug.cgi?id=47182 38125 $( activeElement ).blur(); 38126 } 38127 } catch ( error ) {} 38128 } 38129 38130 this._hide( this.uiDialog, this.options.hide, function() { 38131 that._trigger( "close", event ); 38132 }); 38133 }, 38134 38135 isOpen: function() { 38136 return this._isOpen; 38137 }, 38138 38139 moveToTop: function() { 38140 this._moveToTop(); 38141 }, 38142 38143 _moveToTop: function( event, silent ) { 38144 var moved = false, 38145 zIndicies = this.uiDialog.siblings( ".ui-front:visible" ).map(function() { 38146 return +$( this ).css( "z-index" ); 38147 }).get(), 38148 zIndexMax = Math.max.apply( null, zIndicies ); 38149 38150 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { 38151 this.uiDialog.css( "z-index", zIndexMax + 1 ); 38152 moved = true; 38153 } 38154 38155 if ( moved && !silent ) { 38156 this._trigger( "focus", event ); 38157 } 38158 return moved; 38159 }, 38160 38161 open: function() { 38162 var that = this; 38163 if ( this._isOpen ) { 38164 if ( this._moveToTop() ) { 38165 this._focusTabbable(); 38166 } 38167 return; 38168 } 38169 38170 this._isOpen = true; 38171 this.opener = $( this.document[ 0 ].activeElement ); 38172 38173 this._size(); 38174 this._position(); 38175 this._createOverlay(); 38176 this._moveToTop( null, true ); 38177 38178 // Ensure the overlay is moved to the top with the dialog, but only when 38179 // opening. The overlay shouldn't move after the dialog is open so that 38180 // modeless dialogs opened after the modal dialog stack properly. 38181 if ( this.overlay ) { 38182 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 ); 38183 } 38184 38185 this._show( this.uiDialog, this.options.show, function() { 38186 that._focusTabbable(); 38187 that._trigger( "focus" ); 38188 }); 38189 38190 // Track the dialog immediately upon openening in case a focus event 38191 // somehow occurs outside of the dialog before an element inside the 38192 // dialog is focused (#10152) 38193 this._makeFocusTarget(); 38194 38195 this._trigger( "open" ); 38196 }, 38197 38198 _focusTabbable: function() { 38199 // Set focus to the first match: 38200 // 1. An element that was focused previously 38201 // 2. First element inside the dialog matching [autofocus] 38202 // 3. Tabbable element inside the content element 38203 // 4. Tabbable element inside the buttonpane 38204 // 5. The close button 38205 // 6. The dialog itself 38206 var hasFocus = this._focusedElement; 38207 if ( !hasFocus ) { 38208 hasFocus = this.element.find( "[autofocus]" ); 38209 } 38210 if ( !hasFocus.length ) { 38211 hasFocus = this.element.find( ":tabbable" ); 38212 } 38213 if ( !hasFocus.length ) { 38214 hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); 38215 } 38216 if ( !hasFocus.length ) { 38217 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); 38218 } 38219 if ( !hasFocus.length ) { 38220 hasFocus = this.uiDialog; 38221 } 38222 hasFocus.eq( 0 ).focus(); 38223 }, 38224 38225 _keepFocus: function( event ) { 38226 function checkFocus() { 38227 var activeElement = this.document[0].activeElement, 38228 isActive = this.uiDialog[0] === activeElement || 38229 $.contains( this.uiDialog[0], activeElement ); 38230 if ( !isActive ) { 38231 this._focusTabbable(); 38232 } 38233 } 38234 event.preventDefault(); 38235 checkFocus.call( this ); 38236 // support: IE 38237 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() 38238 // so we check again later 38239 this._delay( checkFocus ); 38240 }, 38241 38242 _createWrapper: function() { 38243 this.uiDialog = $("<div>") 38244 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + 38245 this.options.dialogClass ) 38246 .hide() 38247 .attr({ 38248 // Setting tabIndex makes the div focusable 38249 tabIndex: -1, 38250 role: "dialog" 38251 }) 38252 .appendTo( this._appendTo() ); 38253 38254 this._on( this.uiDialog, { 38255 keydown: function( event ) { 38256 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 38257 event.keyCode === $.ui.keyCode.ESCAPE ) { 38258 event.preventDefault(); 38259 this.close( event ); 38260 return; 38261 } 38262 38263 // prevent tabbing out of dialogs 38264 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) { 38265 return; 38266 } 38267 var tabbables = this.uiDialog.find( ":tabbable" ), 38268 first = tabbables.filter( ":first" ), 38269 last = tabbables.filter( ":last" ); 38270 38271 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { 38272 this._delay(function() { 38273 first.focus(); 38274 }); 38275 event.preventDefault(); 38276 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { 38277 this._delay(function() { 38278 last.focus(); 38279 }); 38280 event.preventDefault(); 38281 } 38282 }, 38283 mousedown: function( event ) { 38284 if ( this._moveToTop( event ) ) { 38285 this._focusTabbable(); 38286 } 38287 } 38288 }); 38289 38290 // We assume that any existing aria-describedby attribute means 38291 // that the dialog content is marked up properly 38292 // otherwise we brute force the content as the description 38293 if ( !this.element.find( "[aria-describedby]" ).length ) { 38294 this.uiDialog.attr({ 38295 "aria-describedby": this.element.uniqueId().attr( "id" ) 38296 }); 38297 } 38298 }, 38299 38300 _createTitlebar: function() { 38301 var uiDialogTitle; 38302 38303 this.uiDialogTitlebar = $( "<div>" ) 38304 .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" ) 38305 .prependTo( this.uiDialog ); 38306 this._on( this.uiDialogTitlebar, { 38307 mousedown: function( event ) { 38308 // Don't prevent click on close button (#8838) 38309 // Focusing a dialog that is partially scrolled out of view 38310 // causes the browser to scroll it into view, preventing the click event 38311 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { 38312 // Dialog isn't getting focus when dragging (#8063) 38313 this.uiDialog.focus(); 38314 } 38315 } 38316 }); 38317 38318 // support: IE 38319 // Use type="button" to prevent enter keypresses in textboxes from closing the 38320 // dialog in IE (#9312) 38321 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 38322 .button({ 38323 label: this.options.closeText, 38324 icons: { 38325 primary: "ui-icon-closethick" 38326 }, 38327 text: false 38328 }) 38329 .addClass( "ui-dialog-titlebar-close" ) 38330 .appendTo( this.uiDialogTitlebar ); 38331 this._on( this.uiDialogTitlebarClose, { 38332 click: function( event ) { 38333 event.preventDefault(); 38334 this.close( event ); 38335 } 38336 }); 38337 38338 uiDialogTitle = $( "<span>" ) 38339 .uniqueId() 38340 .addClass( "ui-dialog-title" ) 38341 .prependTo( this.uiDialogTitlebar ); 38342 this._title( uiDialogTitle ); 38343 38344 this.uiDialog.attr({ 38345 "aria-labelledby": uiDialogTitle.attr( "id" ) 38346 }); 38347 }, 38348 38349 _title: function( title ) { 38350 if ( !this.options.title ) { 38351 title.html( " " ); 38352 } 38353 title.text( this.options.title ); 38354 }, 38355 38356 _createButtonPane: function() { 38357 this.uiDialogButtonPane = $( "<div>" ) 38358 .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); 38359 38360 this.uiButtonSet = $( "<div>" ) 38361 .addClass( "ui-dialog-buttonset" ) 38362 .appendTo( this.uiDialogButtonPane ); 38363 38364 this._createButtons(); 38365 }, 38366 38367 _createButtons: function() { 38368 var that = this, 38369 buttons = this.options.buttons; 38370 38371 // if we already have a button pane, remove it 38372 this.uiDialogButtonPane.remove(); 38373 this.uiButtonSet.empty(); 38374 38375 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { 38376 this.uiDialog.removeClass( "ui-dialog-buttons" ); 38377 return; 38378 } 38379 38380 $.each( buttons, function( name, props ) { 38381 var click, buttonOptions; 38382 props = $.isFunction( props ) ? 38383 { click: props, text: name } : 38384 props; 38385 // Default to a non-submitting button 38386 props = $.extend( { type: "button" }, props ); 38387 // Change the context for the click callback to be the main element 38388 click = props.click; 38389 props.click = function() { 38390 click.apply( that.element[ 0 ], arguments ); 38391 }; 38392 buttonOptions = { 38393 icons: props.icons, 38394 text: props.showText 38395 }; 38396 delete props.icons; 38397 delete props.showText; 38398 $( "<button></button>", props ) 38399 .button( buttonOptions ) 38400 .appendTo( that.uiButtonSet ); 38401 }); 38402 this.uiDialog.addClass( "ui-dialog-buttons" ); 38403 this.uiDialogButtonPane.appendTo( this.uiDialog ); 38404 }, 38405 38406 _makeDraggable: function() { 38407 var that = this, 38408 options = this.options; 38409 38410 function filteredUi( ui ) { 38411 return { 38412 position: ui.position, 38413 offset: ui.offset 38414 }; 38415 } 38416 38417 this.uiDialog.draggable({ 38418 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 38419 handle: ".ui-dialog-titlebar", 38420 containment: "document", 38421 start: function( event, ui ) { 38422 $( this ).addClass( "ui-dialog-dragging" ); 38423 that._blockFrames(); 38424 that._trigger( "dragStart", event, filteredUi( ui ) ); 38425 }, 38426 drag: function( event, ui ) { 38427 that._trigger( "drag", event, filteredUi( ui ) ); 38428 }, 38429 stop: function( event, ui ) { 38430 var left = ui.offset.left - that.document.scrollLeft(), 38431 top = ui.offset.top - that.document.scrollTop(); 38432 38433 options.position = { 38434 my: "left top", 38435 at: "left" + (left >= 0 ? "+" : "") + left + " " + 38436 "top" + (top >= 0 ? "+" : "") + top, 38437 of: that.window 38438 }; 38439 $( this ).removeClass( "ui-dialog-dragging" ); 38440 that._unblockFrames(); 38441 that._trigger( "dragStop", event, filteredUi( ui ) ); 38442 } 38443 }); 38444 }, 38445 38446 _makeResizable: function() { 38447 var that = this, 38448 options = this.options, 38449 handles = options.resizable, 38450 // .ui-resizable has position: relative defined in the stylesheet 38451 // but dialogs have to use absolute or fixed positioning 38452 position = this.uiDialog.css("position"), 38453 resizeHandles = typeof handles === "string" ? 38454 handles : 38455 "n,e,s,w,se,sw,ne,nw"; 38456 38457 function filteredUi( ui ) { 38458 return { 38459 originalPosition: ui.originalPosition, 38460 originalSize: ui.originalSize, 38461 position: ui.position, 38462 size: ui.size 38463 }; 38464 } 38465 38466 this.uiDialog.resizable({ 38467 cancel: ".ui-dialog-content", 38468 containment: "document", 38469 alsoResize: this.element, 38470 maxWidth: options.maxWidth, 38471 maxHeight: options.maxHeight, 38472 minWidth: options.minWidth, 38473 minHeight: this._minHeight(), 38474 handles: resizeHandles, 38475 start: function( event, ui ) { 38476 $( this ).addClass( "ui-dialog-resizing" ); 38477 that._blockFrames(); 38478 that._trigger( "resizeStart", event, filteredUi( ui ) ); 38479 }, 38480 resize: function( event, ui ) { 38481 that._trigger( "resize", event, filteredUi( ui ) ); 38482 }, 38483 stop: function( event, ui ) { 38484 var offset = that.uiDialog.offset(), 38485 left = offset.left - that.document.scrollLeft(), 38486 top = offset.top - that.document.scrollTop(); 38487 38488 options.height = that.uiDialog.height(); 38489 options.width = that.uiDialog.width(); 38490 options.position = { 38491 my: "left top", 38492 at: "left" + (left >= 0 ? "+" : "") + left + " " + 38493 "top" + (top >= 0 ? "+" : "") + top, 38494 of: that.window 38495 }; 38496 $( this ).removeClass( "ui-dialog-resizing" ); 38497 that._unblockFrames(); 38498 that._trigger( "resizeStop", event, filteredUi( ui ) ); 38499 } 38500 }) 38501 .css( "position", position ); 38502 }, 38503 38504 _trackFocus: function() { 38505 this._on( this.widget(), { 38506 focusin: function( event ) { 38507 this._makeFocusTarget(); 38508 this._focusedElement = $( event.target ); 38509 } 38510 }); 38511 }, 38512 38513 _makeFocusTarget: function() { 38514 this._untrackInstance(); 38515 this._trackingInstances().unshift( this ); 38516 }, 38517 38518 _untrackInstance: function() { 38519 var instances = this._trackingInstances(), 38520 exists = $.inArray( this, instances ); 38521 if ( exists !== -1 ) { 38522 instances.splice( exists, 1 ); 38523 } 38524 }, 38525 38526 _trackingInstances: function() { 38527 var instances = this.document.data( "ui-dialog-instances" ); 38528 if ( !instances ) { 38529 instances = []; 38530 this.document.data( "ui-dialog-instances", instances ); 38531 } 38532 return instances; 38533 }, 38534 38535 _minHeight: function() { 38536 var options = this.options; 38537 38538 return options.height === "auto" ? 38539 options.minHeight : 38540 Math.min( options.minHeight, options.height ); 38541 }, 38542 38543 _position: function() { 38544 // Need to show the dialog to get the actual offset in the position plugin 38545 var isVisible = this.uiDialog.is( ":visible" ); 38546 if ( !isVisible ) { 38547 this.uiDialog.show(); 38548 } 38549 this.uiDialog.position( this.options.position ); 38550 if ( !isVisible ) { 38551 this.uiDialog.hide(); 38552 } 38553 }, 38554 38555 _setOptions: function( options ) { 38556 var that = this, 38557 resize = false, 38558 resizableOptions = {}; 38559 38560 $.each( options, function( key, value ) { 38561 that._setOption( key, value ); 38562 38563 if ( key in that.sizeRelatedOptions ) { 38564 resize = true; 38565 } 38566 if ( key in that.resizableRelatedOptions ) { 38567 resizableOptions[ key ] = value; 38568 } 38569 }); 38570 38571 if ( resize ) { 38572 this._size(); 38573 this._position(); 38574 } 38575 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 38576 this.uiDialog.resizable( "option", resizableOptions ); 38577 } 38578 }, 38579 38580 _setOption: function( key, value ) { 38581 var isDraggable, isResizable, 38582 uiDialog = this.uiDialog; 38583 38584 if ( key === "dialogClass" ) { 38585 uiDialog 38586 .removeClass( this.options.dialogClass ) 38587 .addClass( value ); 38588 } 38589 38590 if ( key === "disabled" ) { 38591 return; 38592 } 38593 38594 this._super( key, value ); 38595 38596 if ( key === "appendTo" ) { 38597 this.uiDialog.appendTo( this._appendTo() ); 38598 } 38599 38600 if ( key === "buttons" ) { 38601 this._createButtons(); 38602 } 38603 38604 if ( key === "closeText" ) { 38605 this.uiDialogTitlebarClose.button({ 38606 // Ensure that we always pass a string 38607 label: "" + value 38608 }); 38609 } 38610 38611 if ( key === "draggable" ) { 38612 isDraggable = uiDialog.is( ":data(ui-draggable)" ); 38613 if ( isDraggable && !value ) { 38614 uiDialog.draggable( "destroy" ); 38615 } 38616 38617 if ( !isDraggable && value ) { 38618 this._makeDraggable(); 38619 } 38620 } 38621 38622 if ( key === "position" ) { 38623 this._position(); 38624 } 38625 38626 if ( key === "resizable" ) { 38627 // currently resizable, becoming non-resizable 38628 isResizable = uiDialog.is( ":data(ui-resizable)" ); 38629 if ( isResizable && !value ) { 38630 uiDialog.resizable( "destroy" ); 38631 } 38632 38633 // currently resizable, changing handles 38634 if ( isResizable && typeof value === "string" ) { 38635 uiDialog.resizable( "option", "handles", value ); 38636 } 38637 38638 // currently non-resizable, becoming resizable 38639 if ( !isResizable && value !== false ) { 38640 this._makeResizable(); 38641 } 38642 } 38643 38644 if ( key === "title" ) { 38645 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); 38646 } 38647 }, 38648 38649 _size: function() { 38650 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 38651 // divs will both have width and height set, so we need to reset them 38652 var nonContentHeight, minContentHeight, maxContentHeight, 38653 options = this.options; 38654 38655 // Reset content sizing 38656 this.element.show().css({ 38657 width: "auto", 38658 minHeight: 0, 38659 maxHeight: "none", 38660 height: 0 38661 }); 38662 38663 if ( options.minWidth > options.width ) { 38664 options.width = options.minWidth; 38665 } 38666 38667 // reset wrapper sizing 38668 // determine the height of all the non-content elements 38669 nonContentHeight = this.uiDialog.css({ 38670 height: "auto", 38671 width: options.width 38672 }) 38673 .outerHeight(); 38674 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 38675 maxContentHeight = typeof options.maxHeight === "number" ? 38676 Math.max( 0, options.maxHeight - nonContentHeight ) : 38677 "none"; 38678 38679 if ( options.height === "auto" ) { 38680 this.element.css({ 38681 minHeight: minContentHeight, 38682 maxHeight: maxContentHeight, 38683 height: "auto" 38684 }); 38685 } else { 38686 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 38687 } 38688 38689 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 38690 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 38691 } 38692 }, 38693 38694 _blockFrames: function() { 38695 this.iframeBlocks = this.document.find( "iframe" ).map(function() { 38696 var iframe = $( this ); 38697 38698 return $( "<div>" ) 38699 .css({ 38700 position: "absolute",
vendor: 4,490 bytes, lines 38701-38891
38701 width: iframe.outerWidth(), 38702 height: iframe.outerHeight() 38703 }) 38704 .appendTo( iframe.parent() ) 38705 .offset( iframe.offset() )[0]; 38706 }); 38707 }, 38708 38709 _unblockFrames: function() { 38710 if ( this.iframeBlocks ) { 38711 this.iframeBlocks.remove(); 38712 delete this.iframeBlocks; 38713 } 38714 }, 38715 38716 _allowInteraction: function( event ) { 38717 if ( $( event.target ).closest( ".ui-dialog" ).length ) { 38718 return true; 38719 } 38720 38721 // TODO: Remove hack when datepicker implements 38722 // the .ui-front logic (#8989) 38723 return !!$( event.target ).closest( ".ui-datepicker" ).length; 38724 }, 38725 38726 _createOverlay: function() { 38727 if ( !this.options.modal ) { 38728 return; 38729 } 38730 38731 // We use a delay in case the overlay is created from an 38732 // event that we're going to be cancelling (#2804) 38733 var isOpening = true; 38734 this._delay(function() { 38735 isOpening = false; 38736 }); 38737 38738 if ( !this.document.data( "ui-dialog-overlays" ) ) { 38739 38740 // Prevent use of anchors and inputs 38741 // Using _on() for an event handler shared across many instances is 38742 // safe because the dialogs stack and must be closed in reverse order 38743 this._on( this.document, { 38744 focusin: function( event ) { 38745 if ( isOpening ) { 38746 return; 38747 } 38748 38749 if ( !this._allowInteraction( event ) ) { 38750 event.preventDefault(); 38751 this._trackingInstances()[ 0 ]._focusTabbable(); 38752 } 38753 } 38754 }); 38755 } 38756 38757 this.overlay = $( "<div>" ) 38758 .addClass( "ui-widget-overlay ui-front" ) 38759 .appendTo( this._appendTo() ); 38760 this._on( this.overlay, { 38761 mousedown: "_keepFocus" 38762 }); 38763 this.document.data( "ui-dialog-overlays", 38764 (this.document.data( "ui-dialog-overlays" ) || 0) + 1 ); 38765 }, 38766 38767 _destroyOverlay: function() { 38768 if ( !this.options.modal ) { 38769 return; 38770 } 38771 38772 if ( this.overlay ) { 38773 var overlays = this.document.data( "ui-dialog-overlays" ) - 1; 38774 38775 if ( !overlays ) { 38776 this.document 38777 .unbind( "focusin" ) 38778 .removeData( "ui-dialog-overlays" ); 38779 } else { 38780 this.document.data( "ui-dialog-overlays", overlays ); 38781 } 38782 38783 this.overlay.remove(); 38784 this.overlay = null; 38785 } 38786 } 38787}); 38788 38789})); 38790 38791}, 38792'jquery-ui/ui/core':function(){ 38793/*! 38794 * jQuery UI Core 1.11.2 38795 * http://jqueryui.com 38796 * 38797 * Copyright 2014 jQuery Foundation and other contributors 38798 * Released under the MIT license. 38799 * http://jquery.org/license 38800 * 38801 * http://api.jqueryui.com/category/ui-core/ 38802 */ 38803(function( factory ) { 38804 if ( typeof define === "function" && define.amd ) { 38805 38806 // AMD. Register as an anonymous module. 38807 define( [ "jquery" ], factory ); 38808 } else { 38809 38810 // Browser globals 38811 factory( jQuery ); 38812 } 38813}(function( $ ) { 38814 38815// $.ui might exist from components with no dependencies, e.g., $.ui.position 38816$.ui = $.ui || {}; 38817 38818$.extend( $.ui, { 38819 version: "1.11.2", 38820 38821 keyCode: { 38822 BACKSPACE: 8, 38823 COMMA: 188, 38824 DELETE: 46, 38825 DOWN: 40, 38826 END: 35, 38827 ENTER: 13, 38828 ESCAPE: 27, 38829 HOME: 36, 38830 LEFT: 37, 38831 PAGE_DOWN: 34, 38832 PAGE_UP: 33, 38833 PERIOD: 190, 38834 RIGHT: 39, 38835 SPACE: 32, 38836 TAB: 9, 38837 UP: 38 38838 } 38839}); 38840 38841// plugins 38842$.fn.extend({ 38843 scrollParent: function( includeHidden ) { 38844 var position = this.css( "position" ), 38845 excludeStaticParent = position === "absolute", 38846 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 38847 scrollParent = this.parents().filter( function() { 38848 var parent = $( this ); 38849 if ( excludeStaticParent && parent.css( "position" ) === "static" ) { 38850 return false; 38851 } 38852 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) ); 38853 }).eq( 0 ); 38854 38855 return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent; 38856 }, 38857 38858 uniqueId: (function() { 38859 var uuid = 0; 38860 38861 return function() { 38862 return this.each(function() { 38863 if ( !this.id ) { 38864 this.id = "ui-id-" + ( ++uuid ); 38865 } 38866 }); 38867 }; 38868 })(), 38869 38870 removeUniqueId: function() { 38871 return this.each(function() { 38872 if ( /^ui-id-\d+$/.test( this.id ) ) { 38873 $( this ).removeAttr( "id" ); 38874 } 38875 }); 38876 } 38877}); 38878 38879// selectors 38880function focusable( element, isTabIndexNotNaN ) { 38881 var map, mapName, img, 38882 nodeName = element.nodeName.toLowerCase(); 38883 if ( "area" === nodeName ) { 38884 map = element.parentNode; 38885 mapName = map.name; 38886 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 38887 return false; 38888 } 38889 img = $( "img[usemap='#" + mapName + "']" )[ 0 ]; 38890 return !!img && visible( img ); 38891 }
38892 return ( /input|select|textarea|button|object/.test( nodeName ) ? 38893 !element.disabled : 38894 "a" === nodeName ? 38895 element.href || isTabIndexNotNaN : 38896 isTabIndexNotNaN) && 38897 // the element and all of its ancestors must be visible 38898 visible( element ); 38899} 38900 38901function visible( element ) { 38902 return $.expr.filters.visible( element ) && 38903 !$( element ).parents().addBack().filter(function() { 38904 return $.css( this, "visibility" ) === "hidden"; 38905 }).length; 38906} 38907 38908$.extend( $.expr[ ":" ], { 38909 data: $.expr.createPseudo ? 38910 $.expr.createPseudo(function( dataName ) { 38911 return function( elem ) { 38912 return !!$.data( elem, dataName ); 38913 }; 38914 }) : 38915 // support: jQuery <1.8 38916 function( elem, i, match ) { 38917 return !!$.data( elem, match[ 3 ] ); 38918 }, 38919 38920 focusable: function( element ) { 38921 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 38922 }, 38923 38924 tabbable: function( element ) { 38925 var tabIndex = $.attr( element, "tabindex" ), 38926 isTabIndexNaN = isNaN( tabIndex ); 38927 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 38928 } 38929}); 38930 38931// support: jQuery <1.8 38932if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 38933 $.each( [ "Width", "Height" ], function( i, name ) { 38934 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 38935 type = name.toLowerCase(), 38936 orig = { 38937 innerWidth: $.fn.innerWidth, 38938 innerHeight: $.fn.innerHeight, 38939 outerWidth: $.fn.outerWidth, 38940 outerHeight: $.fn.outerHeight 38941 }; 38942 38943 function reduce( elem, size, border, margin ) { 38944 $.each( side, function() { 38945 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 38946 if ( border ) { 38947 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 38948 } 38949 if ( margin ) { 38950 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 38951 } 38952 }); 38953 return size; 38954 } 38955 38956 $.fn[ "inner" + name ] = function( size ) { 38957 if ( size === undefined ) { 38958 return orig[ "inner" + name ].call( this ); 38959 } 38960 38961 return this.each(function() { 38962 $( this ).css( type, reduce( this, size ) + "px" ); 38963 }); 38964 }; 38965 38966 $.fn[ "outer" + name] = function( size, margin ) { 38967 if ( typeof size !== "number" ) { 38968 return orig[ "outer" + name ].call( this, size ); 38969 } 38970 38971 return this.each(function() { 38972 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 38973 }); 38974 }; 38975 }); 38976} 38977 38978// support: jQuery <1.8 38979if ( !$.fn.addBack ) { 38980 $.fn.addBack = function( selector ) { 38981 return this.add( selector == null ? 38982 this.prevObject : this.prevObject.filter( selector ) 38983 ); 38984 }; 38985} 38986 38987// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) 38988if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { 38989 $.fn.removeData = (function( removeData ) { 38990 return function( key ) { 38991 if ( arguments.length ) { 38992 return removeData.call( this, $.camelCase( key ) ); 38993 } else { 38994 return removeData.call( this ); 38995 } 38996 }; 38997 })( $.fn.removeData ); 38998} 38999 39000// deprecated 39001$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 39002 39003$.fn.extend({ 39004 focus: (function( orig ) { 39005 return function( delay, fn ) { 39006 return typeof delay === "number" ? 39007 this.each(function() { 39008 var elem = this; 39009 setTimeout(function() { 39010 $( elem ).focus(); 39011 if ( fn ) { 39012 fn.call( elem ); 39013 } 39014 }, delay ); 39015 }) : 39016 orig.apply( this, arguments ); 39017 }; 39018 })( $.fn.focus ), 39019 39020 disableSelection: (function() { 39021 var eventType = "onselectstart" in document.createElement( "div" ) ? 39022 "selectstart" : 39023 "mousedown"; 39024 39025 return function() { 39026 return this.bind( eventType + ".ui-disableSelection", function( event ) { 39027 event.preventDefault(); 39028 }); 39029 }; 39030 })(), 39031 39032 enableSelection: function() { 39033 return this.unbind( ".ui-disableSelection" ); 39034 }, 39035 39036 zIndex: function( zIndex ) { 39037 if ( zIndex !== undefined ) { 39038 return this.css( "zIndex", zIndex ); 39039 } 39040 39041 if ( this.length ) { 39042 var elem = $( this[ 0 ] ), position, value; 39043 while ( elem.length && elem[ 0 ] !== document ) { 39044 // Ignore z-index if position is set to a value where z-index is ignored by the browser 39045 // This makes behavior of this function consistent across browsers 39046 // WebKit always returns auto if the element is positioned 39047 position = elem.css( "position" ); 39048 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 39049 // IE returns 0 when zIndex is not specified 39050 // other browsers return a string 39051 // we ignore the case of nested elements with an explicit value of 0 39052 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 39053 value = parseInt( elem.css( "zIndex" ), 10 ); 39054 if ( !isNaN( value ) && value !== 0 ) { 39055 return value; 39056 } 39057 } 39058 elem = elem.parent(); 39059 } 39060 } 39061 39062 return 0; 39063 } 39064}); 39065 39066// $.ui.plugin is deprecated. Use $.widget() extensions instead. 39067$.ui.plugin = { 39068 add: function( module, option, set ) { 39069 var i, 39070 proto = $.ui[ module ].prototype; 39071 for ( i in set ) { 39072 proto.plugins[ i ] = proto.plugins[ i ] || []; 39073 proto.plugins[ i ].push( [ option, set[ i ] ] ); 39074 } 39075 }, 39076 call: function( instance, name, args, allowDisconnected ) { 39077 var i, 39078 set = instance.plugins[ name ]; 39079 39080 if ( !set ) { 39081 return; 39082 } 39083 39084 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 39085 return; 39086 } 39087 39088 for ( i = 0; i < set.length; i++ ) { 39089 if ( instance.options[ set[ i ][ 0 ] ] ) { 39090 set[ i ][ 1 ].apply( instance.element, args ); 39091 } 39092 } 39093 } 39094}; 39095 39096})); 39097 39098},
39099'jquery-ui/ui/widget':function(){ 39100/*! 39101 * jQuery UI Widget 1.11.2 39102 * http://jqueryui.com 39103 * 39104 * Copyright 2014 jQuery Foundation and other contributors 39105 * Released under the MIT license. 39106 * http://jquery.org/license 39107 * 39108 * http://api.jqueryui.com/jQuery.widget/ 39109 */ 39110(function( factory ) { 39111 if ( typeof define === "function" && define.amd ) { 39112 39113 // AMD. Register as an anonymous module. 39114 define( [ "jquery" ], factory ); 39115 } else { 39116 39117 // Browser globals 39118 factory( jQuery ); 39119 } 39120}(function( $ ) { 39121 39122var widget_uuid = 0, 39123 widget_slice = Array.prototype.slice; 39124 39125$.cleanData = (function( orig ) { 39126 return function( elems ) { 39127 var events, elem, i; 39128 for ( i = 0; (elem = elems[i]) != null; i++ ) { 39129 try { 39130 39131 // Only trigger remove when necessary to save time 39132 events = $._data( elem, "events" ); 39133 if ( events && events.remove ) { 39134 $( elem ).triggerHandler( "remove" ); 39135 } 39136 39137 // http://bugs.jquery.com/ticket/8235 39138 } catch ( e ) {} 39139 } 39140 orig( elems ); 39141 }; 39142})( $.cleanData ); 39143 39144$.widget = function( name, base, prototype ) { 39145 var fullName, existingConstructor, constructor, basePrototype, 39146 // proxiedPrototype allows the provided prototype to remain unmodified 39147 // so that it can be used as a mixin for multiple widgets (#8876) 39148 proxiedPrototype = {}, 39149 namespace = name.split( "." )[ 0 ]; 39150 39151 name = name.split( "." )[ 1 ]; 39152 fullName = namespace + "-" + name; 39153 39154 if ( !prototype ) { 39155 prototype = base; 39156 base = $.Widget; 39157 } 39158 39159 // create selector for plugin 39160 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 39161 return !!$.data( elem, fullName ); 39162 }; 39163 39164 $[ namespace ] = $[ namespace ] || {}; 39165 existingConstructor = $[ namespace ][ name ]; 39166 constructor = $[ namespace ][ name ] = function( options, element ) { 39167 // allow instantiation without "new" keyword 39168 if ( !this._createWidget ) { 39169 return new constructor( options, element ); 39170 } 39171 39172 // allow instantiation without initializing for simple inheritance 39173 // must use "new" keyword (the code above always passes args) 39174 if ( arguments.length ) { 39175 this._createWidget( options, element ); 39176 } 39177 }; 39178 // extend with the existing constructor to carry over any static properties 39179 $.extend( constructor, existingConstructor, { 39180 version: prototype.version, 39181 // copy the object used to create the prototype in case we need to 39182 // redefine the widget later 39183 _proto: $.extend( {}, prototype ), 39184 // track widgets that inherit from this widget in case this widget is 39185 // redefined after a widget inherits from it 39186 _childConstructors: [] 39187 }); 39188 39189 basePrototype = new base(); 39190 // we need to make the options hash a property directly on the new instance 39191 // otherwise we'll modify the options hash on the prototype that we're 39192 // inheriting from 39193 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 39194 $.each( prototype, function( prop, value ) { 39195 if ( !$.isFunction( value ) ) { 39196 proxiedPrototype[ prop ] = value; 39197 return; 39198 } 39199 proxiedPrototype[ prop ] = (function() { 39200 var _super = function() { 39201 return base.prototype[ prop ].apply( this, arguments ); 39202 }, 39203 _superApply = function( args ) { 39204 return base.prototype[ prop ].apply( this, args ); 39205 }; 39206 return function() { 39207 var __super = this._super, 39208 __superApply = this._superApply, 39209 returnValue; 39210 39211 this._super = _super; 39212 this._superApply = _superApply; 39213 39214 returnValue = value.apply( this, arguments ); 39215 39216 this._super = __super; 39217 this._superApply = __superApply; 39218 39219 return returnValue; 39220 }; 39221 })(); 39222 }); 39223 constructor.prototype = $.widget.extend( basePrototype, { 39224 // TODO: remove support for widgetEventPrefix 39225 // always use the name + a colon as the prefix, e.g., draggable:start 39226 // don't prefix for widgets that aren't DOM-based 39227 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name 39228 }, proxiedPrototype, { 39229 constructor: constructor, 39230 namespace: namespace, 39231 widgetName: name, 39232 widgetFullName: fullName 39233 }); 39234 39235 // If this widget is being redefined then we need to find all widgets that 39236 // are inheriting from it and redefine all of them so that they inherit from 39237 // the new version of this widget. We're essentially trying to replace one 39238 // level in the prototype chain. 39239 if ( existingConstructor ) { 39240 $.each( existingConstructor._childConstructors, function( i, child ) { 39241 var childPrototype = child.prototype; 39242 39243 // redefine the child widget using the same prototype that was 39244 // originally used, but inherit from the new version of the base 39245 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); 39246 }); 39247 // remove the list of existing child constructors from the old constructor 39248 // so the old child constructors can be garbage collected 39249 delete existingConstructor._childConstructors; 39250 } else { 39251 base._childConstructors.push( constructor ); 39252 } 39253 39254 $.widget.bridge( name, constructor ); 39255 39256 return constructor; 39257}; 39258 39259$.widget.extend = function( target ) { 39260 var input = widget_slice.call( arguments, 1 ), 39261 inputIndex = 0, 39262 inputLength = input.length, 39263 key, 39264 value; 39265 for ( ; inputIndex < inputLength; inputIndex++ ) { 39266 for ( key in input[ inputIndex ] ) { 39267 value = input[ inputIndex ][ key ]; 39268 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 39269 // Clone objects 39270 if ( $.isPlainObject( value ) ) { 39271 target[ key ] = $.isPlainObject( target[ key ] ) ? 39272 $.widget.extend( {}, target[ key ], value ) : 39273 // Don't extend strings, arrays, etc. with objects 39274 $.widget.extend( {}, value ); 39275 // Copy everything else by reference 39276 } else { 39277 target[ key ] = value; 39278 } 39279 } 39280 } 39281 } 39282 return target; 39283}; 39284 39285$.widget.bridge = function( name, object ) { 39286 var fullName = object.prototype.widgetFullName || name; 39287 $.fn[ name ] = function( options ) { 39288 var isMethodCall = typeof options === "string", 39289 args = widget_slice.call( arguments, 1 ), 39290 returnValue = this; 39291 39292 // allow multiple hashes to be passed on init 39293 options = !isMethodCall && args.length ? 39294 $.widget.extend.apply( null, [ options ].concat(args) ) : 39295 options; 39296 39297 if ( isMethodCall ) { 39298 this.each(function() { 39299 var methodValue, 39300 instance = $.data( this, fullName ); 39301 if ( options === "instance" ) { 39302 returnValue = instance; 39303 return false; 39304 } 39305 if ( !instance ) { 39306 return $.error( "cannot call methods on " + name + " prior to initialization; " + 39307 "attempted to call method '" + options + "'" ); 39308 } 39309 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { 39310 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); 39311 } 39312 methodValue = instance[ options ].apply( instance, args ); 39313 if ( methodValue !== instance && methodValue !== undefined ) { 39314 returnValue = methodValue && methodValue.jquery ? 39315 returnValue.pushStack( methodValue.get() ) : 39316 methodValue; 39317 return false; 39318 } 39319 }); 39320 } else { 39321 this.each(function() { 39322 var instance = $.data( this, fullName ); 39323 if ( instance ) { 39324 instance.option( options || {} ); 39325 if ( instance._init ) { 39326 instance._init(); 39327 } 39328 } else { 39329 $.data( this, fullName, new object( options, this ) ); 39330 } 39331 }); 39332 } 39333 39334 return returnValue; 39335 }; 39336}; 39337 39338$.Widget = function( /* options, element */ ) {}; 39339$.Widget._childConstructors = []; 39340 39341$.Widget.prototype = { 39342 widgetName: "widget", 39343 widgetEventPrefix: "", 39344 defaultElement: "<div>", 39345 options: { 39346 disabled: false, 39347 39348 // callbacks 39349 create: null 39350 }, 39351 _createWidget: function( options, element ) { 39352 element = $( element || this.defaultElement || this )[ 0 ]; 39353 this.element = $( element ); 39354 this.uuid = widget_uuid++; 39355 this.eventNamespace = "." + this.widgetName + this.uuid; 39356 39357 this.bindings = $(); 39358 this.hoverable = $(); 39359 this.focusable = $(); 39360 39361 if ( element !== this ) { 39362 $.data( element, this.widgetFullName, this ); 39363 this._on( true, this.element, { 39364 remove: function( event ) { 39365 if ( event.target === element ) { 39366 this.destroy(); 39367 } 39368 } 39369 }); 39370 this.document = $( element.style ? 39371 // element within the document 39372 element.ownerDocument :
vendor: 7,772 bytes, lines 39373-39640
39373 // element is window or document 39374 element.document || element ); 39375 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); 39376 } 39377 39378 this.options = $.widget.extend( {}, 39379 this.options, 39380 this._getCreateOptions(), 39381 options ); 39382 39383 this._create(); 39384 this._trigger( "create", null, this._getCreateEventData() ); 39385 this._init(); 39386 }, 39387 _getCreateOptions: $.noop, 39388 _getCreateEventData: $.noop, 39389 _create: $.noop, 39390 _init: $.noop, 39391 39392 destroy: function() { 39393 this._destroy(); 39394 // we can probably remove the unbind calls in 2.0 39395 // all event bindings should go through this._on() 39396 this.element 39397 .unbind( this.eventNamespace ) 39398 .removeData( this.widgetFullName ) 39399 // support: jquery <1.6.3 39400 // http://bugs.jquery.com/ticket/9413 39401 .removeData( $.camelCase( this.widgetFullName ) ); 39402 this.widget() 39403 .unbind( this.eventNamespace ) 39404 .removeAttr( "aria-disabled" ) 39405 .removeClass( 39406 this.widgetFullName + "-disabled " + 39407 "ui-state-disabled" ); 39408 39409 // clean up events and states 39410 this.bindings.unbind( this.eventNamespace ); 39411 this.hoverable.removeClass( "ui-state-hover" ); 39412 this.focusable.removeClass( "ui-state-focus" ); 39413 }, 39414 _destroy: $.noop, 39415 39416 widget: function() { 39417 return this.element; 39418 }, 39419 39420 option: function( key, value ) { 39421 var options = key, 39422 parts, 39423 curOption, 39424 i; 39425 39426 if ( arguments.length === 0 ) { 39427 // don't return a reference to the internal hash 39428 return $.widget.extend( {}, this.options ); 39429 } 39430 39431 if ( typeof key === "string" ) { 39432 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 39433 options = {}; 39434 parts = key.split( "." ); 39435 key = parts.shift(); 39436 if ( parts.length ) { 39437 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 39438 for ( i = 0; i < parts.length - 1; i++ ) { 39439 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 39440 curOption = curOption[ parts[ i ] ]; 39441 } 39442 key = parts.pop(); 39443 if ( arguments.length === 1 ) { 39444 return curOption[ key ] === undefined ? null : curOption[ key ]; 39445 } 39446 curOption[ key ] = value; 39447 } else { 39448 if ( arguments.length === 1 ) { 39449 return this.options[ key ] === undefined ? null : this.options[ key ]; 39450 } 39451 options[ key ] = value; 39452 } 39453 } 39454 39455 this._setOptions( options ); 39456 39457 return this; 39458 }, 39459 _setOptions: function( options ) { 39460 var key; 39461 39462 for ( key in options ) { 39463 this._setOption( key, options[ key ] ); 39464 } 39465 39466 return this; 39467 }, 39468 _setOption: function( key, value ) { 39469 this.options[ key ] = value; 39470 39471 if ( key === "disabled" ) { 39472 this.widget() 39473 .toggleClass( this.widgetFullName + "-disabled", !!value ); 39474 39475 // If the widget is becoming disabled, then nothing is interactive 39476 if ( value ) { 39477 this.hoverable.removeClass( "ui-state-hover" ); 39478 this.focusable.removeClass( "ui-state-focus" ); 39479 } 39480 } 39481 39482 return this; 39483 }, 39484 39485 enable: function() { 39486 return this._setOptions({ disabled: false }); 39487 }, 39488 disable: function() { 39489 return this._setOptions({ disabled: true }); 39490 }, 39491 39492 _on: function( suppressDisabledCheck, element, handlers ) { 39493 var delegateElement, 39494 instance = this; 39495 39496 // no suppressDisabledCheck flag, shuffle arguments 39497 if ( typeof suppressDisabledCheck !== "boolean" ) { 39498 handlers = element; 39499 element = suppressDisabledCheck; 39500 suppressDisabledCheck = false; 39501 } 39502 39503 // no element argument, shuffle and use this.element 39504 if ( !handlers ) { 39505 handlers = element; 39506 element = this.element; 39507 delegateElement = this.widget(); 39508 } else { 39509 element = delegateElement = $( element ); 39510 this.bindings = this.bindings.add( element ); 39511 } 39512 39513 $.each( handlers, function( event, handler ) { 39514 function handlerProxy() { 39515 // allow widgets to customize the disabled handling 39516 // - disabled as an array instead of boolean 39517 // - disabled class as method for disabling individual parts 39518 if ( !suppressDisabledCheck && 39519 ( instance.options.disabled === true || 39520 $( this ).hasClass( "ui-state-disabled" ) ) ) { 39521 return; 39522 } 39523 return ( typeof handler === "string" ? instance[ handler ] : handler ) 39524 .apply( instance, arguments ); 39525 } 39526 39527 // copy the guid so direct unbinding works 39528 if ( typeof handler !== "string" ) { 39529 handlerProxy.guid = handler.guid = 39530 handler.guid || handlerProxy.guid || $.guid++; 39531 } 39532 39533 var match = event.match( /^([\w:-]*)\s*(.*)$/ ), 39534 eventName = match[1] + instance.eventNamespace, 39535 selector = match[2]; 39536 if ( selector ) { 39537 delegateElement.delegate( selector, eventName, handlerProxy ); 39538 } else { 39539 element.bind( eventName, handlerProxy ); 39540 } 39541 }); 39542 }, 39543 39544 _off: function( element, eventName ) { 39545 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + 39546 this.eventNamespace; 39547 element.unbind( eventName ).undelegate( eventName ); 39548 39549 // Clear the stack to avoid memory leaks (#10056) 39550 this.bindings = $( this.bindings.not( element ).get() ); 39551 this.focusable = $( this.focusable.not( element ).get() ); 39552 this.hoverable = $( this.hoverable.not( element ).get() ); 39553 }, 39554 39555 _delay: function( handler, delay ) { 39556 function handlerProxy() { 39557 return ( typeof handler === "string" ? instance[ handler ] : handler ) 39558 .apply( instance, arguments ); 39559 } 39560 var instance = this; 39561 return setTimeout( handlerProxy, delay || 0 ); 39562 }, 39563 39564 _hoverable: function( element ) { 39565 this.hoverable = this.hoverable.add( element ); 39566 this._on( element, { 39567 mouseenter: function( event ) { 39568 $( event.currentTarget ).addClass( "ui-state-hover" ); 39569 }, 39570 mouseleave: function( event ) { 39571 $( event.currentTarget ).removeClass( "ui-state-hover" ); 39572 } 39573 }); 39574 }, 39575 39576 _focusable: function( element ) { 39577 this.focusable = this.focusable.add( element ); 39578 this._on( element, { 39579 focusin: function( event ) { 39580 $( event.currentTarget ).addClass( "ui-state-focus" ); 39581 }, 39582 focusout: function( event ) { 39583 $( event.currentTarget ).removeClass( "ui-state-focus" ); 39584 } 39585 }); 39586 }, 39587 39588 _trigger: function( type, event, data ) { 39589 var prop, orig, 39590 callback = this.options[ type ]; 39591 39592 data = data || {}; 39593 event = $.Event( event ); 39594 event.type = ( type === this.widgetEventPrefix ? 39595 type : 39596 this.widgetEventPrefix + type ).toLowerCase(); 39597 // the original event may come from any element 39598 // so we need to reset the target on the new event 39599 event.target = this.element[ 0 ]; 39600 39601 // copy original event properties over to the new event 39602 orig = event.originalEvent; 39603 if ( orig ) { 39604 for ( prop in orig ) { 39605 if ( !( prop in event ) ) { 39606 event[ prop ] = orig[ prop ]; 39607 } 39608 } 39609 } 39610 39611 this.element.trigger( event, data ); 39612 return !( $.isFunction( callback ) && 39613 callback.apply( this.element[0], [ event ].concat( data ) ) === false || 39614 event.isDefaultPrevented() ); 39615 } 39616}; 39617 39618$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 39619 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 39620 if ( typeof options === "string" ) { 39621 options = { effect: options }; 39622 } 39623 var hasOptions, 39624 effectName = !options ? 39625 method : 39626 options === true || typeof options === "number" ? 39627 defaultEffect : 39628 options.effect || defaultEffect; 39629 options = options || {}; 39630 if ( typeof options === "number" ) { 39631 options = { duration: options }; 39632 } 39633 hasOptions = !$.isEmptyObject( options ); 39634 options.complete = callback; 39635 if ( options.delay ) { 39636 element.delay( options.delay ); 39637 } 39638 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 39639 element[ method ]( options ); 39640 } else if ( effectName !== method && element[ effectName ] ) {
39641 element[ effectName ]( options.duration, options.easing, callback ); 39642 } else { 39643 element.queue(function( next ) { 39644 $( this )[ method ](); 39645 if ( callback ) { 39646 callback.call( element[ 0 ] ); 39647 } 39648 next(); 39649 }); 39650 } 39651 }; 39652}); 39653 39654return $.widget; 39655 39656})); 39657 39658}, 39659'jquery-ui/ui/button':function(){ 39660/*! 39661 * jQuery UI Button 1.11.2 39662 * http://jqueryui.com 39663 * 39664 * Copyright 2014 jQuery Foundation and other contributors 39665 * Released under the MIT license. 39666 * http://jquery.org/license 39667 * 39668 * http://api.jqueryui.com/button/ 39669 */ 39670(function( factory ) { 39671 if ( typeof define === "function" && define.amd ) { 39672 39673 // AMD. Register as an anonymous module. 39674 define([ 39675 "jquery", 39676 "./core", 39677 "./widget" 39678 ], factory ); 39679 } else { 39680 39681 // Browser globals 39682 factory( jQuery ); 39683 } 39684}(function( $ ) { 39685 39686var lastActive, 39687 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 39688 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", 39689 formResetHandler = function() { 39690 var form = $( this ); 39691 setTimeout(function() { 39692 form.find( ":ui-button" ).button( "refresh" ); 39693 }, 1 ); 39694 }, 39695 radioGroup = function( radio ) { 39696 var name = radio.name, 39697 form = radio.form, 39698 radios = $( [] ); 39699 if ( name ) { 39700 name = name.replace( /'/g, "\\'" ); 39701 if ( form ) { 39702 radios = $( form ).find( "[name='" + name + "'][type=radio]" ); 39703 } else { 39704 radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument ) 39705 .filter(function() { 39706 return !this.form; 39707 }); 39708 } 39709 } 39710 return radios; 39711 }; 39712 39713$.widget( "ui.button", { 39714 version: "1.11.2", 39715 defaultElement: "<button>", 39716 options: { 39717 disabled: null, 39718 text: true, 39719 label: null, 39720 icons: { 39721 primary: null, 39722 secondary: null 39723 } 39724 }, 39725 _create: function() { 39726 this.element.closest( "form" ) 39727 .unbind( "reset" + this.eventNamespace ) 39728 .bind( "reset" + this.eventNamespace, formResetHandler ); 39729 39730 if ( typeof this.options.disabled !== "boolean" ) { 39731 this.options.disabled = !!this.element.prop( "disabled" ); 39732 } else { 39733 this.element.prop( "disabled", this.options.disabled ); 39734 } 39735 39736 this._determineButtonType(); 39737 this.hasTitle = !!this.buttonElement.attr( "title" ); 39738 39739 var that = this, 39740 options = this.options, 39741 toggleButton = this.type === "checkbox" || this.type === "radio", 39742 activeClass = !toggleButton ? "ui-state-active" : ""; 39743 39744 if ( options.label === null ) { 39745 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); 39746 } 39747 39748 this._hoverable( this.buttonElement ); 39749 39750 this.buttonElement 39751 .addClass( baseClasses ) 39752 .attr( "role", "button" ) 39753 .bind( "mouseenter" + this.eventNamespace, function() { 39754 if ( options.disabled ) { 39755 return; 39756 } 39757 if ( this === lastActive ) { 39758 $( this ).addClass( "ui-state-active" ); 39759 } 39760 }) 39761 .bind( "mouseleave" + this.eventNamespace, function() { 39762 if ( options.disabled ) { 39763 return; 39764 } 39765 $( this ).removeClass( activeClass ); 39766 }) 39767 .bind( "click" + this.eventNamespace, function( event ) { 39768 if ( options.disabled ) { 39769 event.preventDefault(); 39770 event.stopImmediatePropagation(); 39771 } 39772 }); 39773 39774 // Can't use _focusable() because the element that receives focus 39775 // and the element that gets the ui-state-focus class are different 39776 this._on({ 39777 focus: function() { 39778 this.buttonElement.addClass( "ui-state-focus" ); 39779 }, 39780 blur: function() { 39781 this.buttonElement.removeClass( "ui-state-focus" ); 39782 } 39783 }); 39784 39785 if ( toggleButton ) { 39786 this.element.bind( "change" + this.eventNamespace, function() { 39787 that.refresh(); 39788 }); 39789 } 39790 39791 if ( this.type === "checkbox" ) { 39792 this.buttonElement.bind( "click" + this.eventNamespace, function() { 39793 if ( options.disabled ) { 39794 return false; 39795 } 39796 }); 39797 } else if ( this.type === "radio" ) { 39798 this.buttonElement.bind( "click" + this.eventNamespace, function() { 39799 if ( options.disabled ) { 39800 return false; 39801 } 39802 $( this ).addClass( "ui-state-active" ); 39803 that.buttonElement.attr( "aria-pressed", "true" ); 39804 39805 var radio = that.element[ 0 ]; 39806 radioGroup( radio ) 39807 .not( radio ) 39808 .map(function() { 39809 return $( this ).button( "widget" )[ 0 ]; 39810 }) 39811 .removeClass( "ui-state-active" ) 39812 .attr( "aria-pressed", "false" ); 39813 }); 39814 } else { 39815 this.buttonElement 39816 .bind( "mousedown" + this.eventNamespace, function() { 39817 if ( options.disabled ) { 39818 return false; 39819 } 39820 $( this ).addClass( "ui-state-active" ); 39821 lastActive = this; 39822 that.document.one( "mouseup", function() { 39823 lastActive = null; 39824 });
39825 }) 39826 .bind( "mouseup" + this.eventNamespace, function() { 39827 if ( options.disabled ) { 39828 return false; 39829 } 39830 $( this ).removeClass( "ui-state-active" ); 39831 }) 39832 .bind( "keydown" + this.eventNamespace, function(event) { 39833 if ( options.disabled ) { 39834 return false; 39835 } 39836 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { 39837 $( this ).addClass( "ui-state-active" ); 39838 } 39839 }) 39840 // see #8559, we bind to blur here in case the button element loses 39841 // focus between keydown and keyup, it would be left in an "active" state 39842 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { 39843 $( this ).removeClass( "ui-state-active" ); 39844 }); 39845 39846 if ( this.buttonElement.is("a") ) { 39847 this.buttonElement.keyup(function(event) { 39848 if ( event.keyCode === $.ui.keyCode.SPACE ) { 39849 // TODO pass through original event correctly (just as 2nd argument doesn't work) 39850 $( this ).click(); 39851 } 39852 }); 39853 } 39854 } 39855 39856 this._setOption( "disabled", options.disabled ); 39857 this._resetButton(); 39858 }, 39859 39860 _determineButtonType: function() { 39861 var ancestor, labelSelector, checked; 39862 39863 if ( this.element.is("[type=checkbox]") ) { 39864 this.type = "checkbox"; 39865 } else if ( this.element.is("[type=radio]") ) { 39866 this.type = "radio"; 39867 } else if ( this.element.is("input") ) { 39868 this.type = "input"; 39869 } else { 39870 this.type = "button"; 39871 } 39872 39873 if ( this.type === "checkbox" || this.type === "radio" ) { 39874 // we don't search against the document in case the element 39875 // is disconnected from the DOM 39876 ancestor = this.element.parents().last(); 39877 labelSelector = "label[for='" + this.element.attr("id") + "']"; 39878 this.buttonElement = ancestor.find( labelSelector ); 39879 if ( !this.buttonElement.length ) { 39880 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 39881 this.buttonElement = ancestor.filter( labelSelector ); 39882 if ( !this.buttonElement.length ) { 39883 this.buttonElement = ancestor.find( labelSelector ); 39884 } 39885 } 39886 this.element.addClass( "ui-helper-hidden-accessible" ); 39887 39888 checked = this.element.is( ":checked" ); 39889 if ( checked ) { 39890 this.buttonElement.addClass( "ui-state-active" ); 39891 } 39892 this.buttonElement.prop( "aria-pressed", checked ); 39893 } else { 39894 this.buttonElement = this.element; 39895 } 39896 }, 39897 39898 widget: function() { 39899 return this.buttonElement; 39900 }, 39901 39902 _destroy: function() { 39903 this.element 39904 .removeClass( "ui-helper-hidden-accessible" ); 39905 this.buttonElement 39906 .removeClass( baseClasses + " ui-state-active " + typeClasses ) 39907 .removeAttr( "role" ) 39908 .removeAttr( "aria-pressed" ) 39909 .html( this.buttonElement.find(".ui-button-text").html() ); 39910 39911 if ( !this.hasTitle ) { 39912 this.buttonElement.removeAttr( "title" ); 39913 } 39914 }, 39915 39916 _setOption: function( key, value ) { 39917 this._super( key, value ); 39918 if ( key === "disabled" ) { 39919 this.widget().toggleClass( "ui-state-disabled", !!value ); 39920 this.element.prop( "disabled", !!value ); 39921 if ( value ) { 39922 if ( this.type === "checkbox" || this.type === "radio" ) { 39923 this.buttonElement.removeClass( "ui-state-focus" ); 39924 } else { 39925 this.buttonElement.removeClass( "ui-state-focus ui-state-active" ); 39926 } 39927 } 39928 return; 39929 } 39930 this._resetButton(); 39931 }, 39932 39933 refresh: function() { 39934 //See #8237 & #8828 39935 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); 39936 39937 if ( isDisabled !== this.options.disabled ) { 39938 this._setOption( "disabled", isDisabled ); 39939 } 39940 if ( this.type === "radio" ) { 39941 radioGroup( this.element[0] ).each(function() { 39942 if ( $( this ).is( ":checked" ) ) { 39943 $( this ).button( "widget" ) 39944 .addClass( "ui-state-active" ) 39945 .attr( "aria-pressed", "true" ); 39946 } else { 39947 $( this ).button( "widget" ) 39948 .removeClass( "ui-state-active" ) 39949 .attr( "aria-pressed", "false" ); 39950 } 39951 }); 39952 } else if ( this.type === "checkbox" ) { 39953 if ( this.element.is( ":checked" ) ) { 39954 this.buttonElement 39955 .addClass( "ui-state-active" ) 39956 .attr( "aria-pressed", "true" ); 39957 } else { 39958 this.buttonElement 39959 .removeClass( "ui-state-active" ) 39960 .attr( "aria-pressed", "false" ); 39961 } 39962 } 39963 }, 39964 39965 _resetButton: function() { 39966 if ( this.type === "input" ) { 39967 if ( this.options.label ) { 39968 this.element.val( this.options.label ); 39969 } 39970 return; 39971 } 39972 var buttonElement = this.buttonElement.removeClass( typeClasses ), 39973 buttonText = $( "<span></span>", this.document[0] ) 39974 .addClass( "ui-button-text" ) 39975 .html( this.options.label ) 39976 .appendTo( buttonElement.empty() ) 39977 .text(), 39978 icons = this.options.icons, 39979 multipleIcons = icons.primary && icons.secondary,
39980 buttonClasses = []; 39981 39982 if ( icons.primary || icons.secondary ) { 39983 if ( this.options.text ) { 39984 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 39985 } 39986 39987 if ( icons.primary ) { 39988 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 39989 } 39990 39991 if ( icons.secondary ) { 39992 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 39993 } 39994 39995 if ( !this.options.text ) { 39996 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 39997 39998 if ( !this.hasTitle ) { 39999 buttonElement.attr( "title", $.trim( buttonText ) ); 40000 } 40001 } 40002 } else { 40003 buttonClasses.push( "ui-button-text-only" ); 40004 } 40005 buttonElement.addClass( buttonClasses.join( " " ) ); 40006 } 40007}); 40008 40009$.widget( "ui.buttonset", { 40010 version: "1.11.2", 40011 options: { 40012 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" 40013 }, 40014 40015 _create: function() { 40016 this.element.addClass( "ui-buttonset" ); 40017 }, 40018 40019 _init: function() { 40020 this.refresh(); 40021 }, 40022 40023 _setOption: function( key, value ) { 40024 if ( key === "disabled" ) { 40025 this.buttons.button( "option", key, value ); 40026 } 40027 40028 this._super( key, value ); 40029 }, 40030 40031 refresh: function() { 40032 var rtl = this.element.css( "direction" ) === "rtl", 40033 allButtons = this.element.find( this.options.items ), 40034 existingButtons = allButtons.filter( ":ui-button" ); 40035 40036 // Initialize new buttons 40037 allButtons.not( ":ui-button" ).button(); 40038 40039 // Refresh existing buttons 40040 existingButtons.button( "refresh" ); 40041 40042 this.buttons = allButtons 40043 .map(function() { 40044 return $( this ).button( "widget" )[ 0 ]; 40045 }) 40046 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 40047 .filter( ":first" ) 40048 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 40049 .end() 40050 .filter( ":last" ) 40051 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 40052 .end() 40053 .end(); 40054 }, 40055 40056 _destroy: function() { 40057 this.element.removeClass( "ui-buttonset" ); 40058 this.buttons 40059 .map(function() { 40060 return $( this ).button( "widget" )[ 0 ]; 40061 }) 40062 .removeClass( "ui-corner-left ui-corner-right" ) 40063 .end() 40064 .button( "destroy" ); 40065 } 40066}); 40067 40068return $.ui.button; 40069 40070})); 40071 40072}, 40073'jquery-ui/ui/draggable':function(){ 40074/*! 40075 * jQuery UI Draggable 1.11.2 40076 * http://jqueryui.com 40077 * 40078 * Copyright 2014 jQuery Foundation and other contributors 40079 * Released under the MIT license. 40080 * http://jquery.org/license 40081 * 40082 * http://api.jqueryui.com/draggable/ 40083 */ 40084(function( factory ) { 40085 if ( typeof define === "function" && define.amd ) { 40086 40087 // AMD. Register as an anonymous module. 40088 define([ 40089 "jquery", 40090 "./core", 40091 "./mouse", 40092 "./widget" 40093 ], factory ); 40094 } else { 40095 40096 // Browser globals 40097 factory( jQuery ); 40098 } 40099}(function( $ ) { 40100 40101$.widget("ui.draggable", $.ui.mouse, { 40102 version: "1.11.2", 40103 widgetEventPrefix: "drag", 40104 options: { 40105 addClasses: true, 40106 appendTo: "parent", 40107 axis: false, 40108 connectToSortable: false, 40109 containment: false, 40110 cursor: "auto", 40111 cursorAt: false, 40112 grid: false, 40113 handle: false, 40114 helper: "original", 40115 iframeFix: false, 40116 opacity: false, 40117 refreshPositions: false, 40118 revert: false, 40119 revertDuration: 500, 40120 scope: "default", 40121 scroll: true, 40122 scrollSensitivity: 20, 40123 scrollSpeed: 20, 40124 snap: false, 40125 snapMode: "both", 40126 snapTolerance: 20, 40127 stack: false, 40128 zIndex: false, 40129 40130 // callbacks 40131 drag: null, 40132 start: null, 40133 stop: null 40134 }, 40135 _create: function() { 40136 40137 if ( this.options.helper === "original" ) { 40138 this._setPositionRelative(); 40139 } 40140 if (this.options.addClasses){ 40141 this.element.addClass("ui-draggable"); 40142 } 40143 if (this.options.disabled){ 40144 this.element.addClass("ui-draggable-disabled"); 40145 } 40146 this._setHandleClassName(); 40147 40148 this._mouseInit(); 40149 }, 40150 40151 _setOption: function( key, value ) { 40152 this._super( key, value ); 40153 if ( key === "handle" ) { 40154 this._removeHandleClassName(); 40155 this._setHandleClassName(); 40156 } 40157 }, 40158 40159 _destroy: function() { 40160 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { 40161 this.destroyOnClear = true; 40162 return; 40163 } 40164 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); 40165 this._removeHandleClassName(); 40166 this._mouseDestroy(); 40167 }, 40168 40169 _mouseCapture: function(event) { 40170 var o = this.options; 40171 40172 this._blurActiveElement( event ); 40173 40174 // among others, prevent a drag on a resizable-handle 40175 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { 40176 return false; 40177 } 40178 40179 //Quit if we're not on a valid handle 40180 this.handle = this._getHandle(event); 40181 if (!this.handle) { 40182 return false; 40183 } 40184 40185 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); 40186 40187 return true; 40188 40189 }, 40190 40191 _blockFrames: function( selector ) { 40192 this.iframeBlocks = this.document.find( selector ).map(function() { 40193 var iframe = $( this ); 40194 40195 return $( "<div>" ) 40196 .css( "position", "absolute" ) 40197 .appendTo( iframe.parent() ) 40198 .outerWidth( iframe.outerWidth() ) 40199 .outerHeight( iframe.outerHeight() ) 40200 .offset( iframe.offset() )[ 0 ]; 40201 }); 40202 }, 40203 40204 _unblockFrames: function() { 40205 if ( this.iframeBlocks ) { 40206 this.iframeBlocks.remove(); 40207 delete this.iframeBlocks; 40208 } 40209 }, 40210 40211 _blurActiveElement: function( event ) { 40212 var document = this.document[ 0 ]; 40213 40214 // Only need to blur if the event occurred on the draggable itself, see #10527 40215 if ( !this.handleElement.is( event.target ) ) { 40216 return; 40217 } 40218 40219 // support: IE9 40220 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 40221 try { 40222
vendor: 32,647 bytes, lines 40223-41207
40223 // Support: IE9, IE10 40224 // If the <body> is blurred, IE will switch windows, see #9520 40225 if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) { 40226 40227 // Blur any element that currently has focus, see #4261 40228 $( document.activeElement ).blur(); 40229 } 40230 } catch ( error ) {} 40231 }, 40232 40233 _mouseStart: function(event) { 40234 40235 var o = this.options; 40236 40237 //Create and append the visible helper 40238 this.helper = this._createHelper(event); 40239 40240 this.helper.addClass("ui-draggable-dragging"); 40241 40242 //Cache the helper size 40243 this._cacheHelperProportions(); 40244 40245 //If ddmanager is used for droppables, set the global draggable 40246 if ($.ui.ddmanager) { 40247 $.ui.ddmanager.current = this; 40248 } 40249 40250 /* 40251 * - Position generation - 40252 * This block generates everything position related - it's the core of draggables. 40253 */ 40254 40255 //Cache the margins of the original element 40256 this._cacheMargins(); 40257 40258 //Store the helper's css position 40259 this.cssPosition = this.helper.css( "position" ); 40260 this.scrollParent = this.helper.scrollParent( true ); 40261 this.offsetParent = this.helper.offsetParent(); 40262 this.hasFixedAncestor = this.helper.parents().filter(function() { 40263 return $( this ).css( "position" ) === "fixed"; 40264 }).length > 0; 40265 40266 //The element's absolute position on the page minus margins 40267 this.positionAbs = this.element.offset(); 40268 this._refreshOffsets( event ); 40269 40270 //Generate the original position 40271 this.originalPosition = this.position = this._generatePosition( event, false ); 40272 this.originalPageX = event.pageX; 40273 this.originalPageY = event.pageY; 40274 40275 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 40276 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 40277 40278 //Set a containment if given in the options 40279 this._setContainment(); 40280 40281 //Trigger event + callbacks 40282 if (this._trigger("start", event) === false) { 40283 this._clear(); 40284 return false; 40285 } 40286 40287 //Recache the helper size 40288 this._cacheHelperProportions(); 40289 40290 //Prepare the droppable offsets 40291 if ($.ui.ddmanager && !o.dropBehaviour) { 40292 $.ui.ddmanager.prepareOffsets(this, event); 40293 } 40294 40295 // Reset helper's right/bottom css if they're set and set explicit width/height instead 40296 // as this prevents resizing of elements with right/bottom set (see #7772) 40297 this._normalizeRightBottom(); 40298 40299 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 40300 40301 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 40302 if ( $.ui.ddmanager ) { 40303 $.ui.ddmanager.dragStart(this, event); 40304 } 40305 40306 return true; 40307 }, 40308 40309 _refreshOffsets: function( event ) { 40310 this.offset = { 40311 top: this.positionAbs.top - this.margins.top, 40312 left: this.positionAbs.left - this.margins.left, 40313 scroll: false, 40314 parent: this._getParentOffset(), 40315 relative: this._getRelativeOffset() 40316 }; 40317 40318 this.offset.click = { 40319 left: event.pageX - this.offset.left, 40320 top: event.pageY - this.offset.top 40321 }; 40322 }, 40323 40324 _mouseDrag: function(event, noPropagation) { 40325 // reset any necessary cached properties (see #5009) 40326 if ( this.hasFixedAncestor ) { 40327 this.offset.parent = this._getParentOffset(); 40328 } 40329 40330 //Compute the helpers position 40331 this.position = this._generatePosition( event, true ); 40332 this.positionAbs = this._convertPositionTo("absolute"); 40333 40334 //Call plugins and callbacks and use the resulting position if something is returned 40335 if (!noPropagation) { 40336 var ui = this._uiHash(); 40337 if (this._trigger("drag", event, ui) === false) { 40338 this._mouseUp({}); 40339 return false; 40340 } 40341 this.position = ui.position; 40342 } 40343 40344 this.helper[ 0 ].style.left = this.position.left + "px"; 40345 this.helper[ 0 ].style.top = this.position.top + "px"; 40346 40347 if ($.ui.ddmanager) { 40348 $.ui.ddmanager.drag(this, event); 40349 } 40350 40351 return false; 40352 }, 40353 40354 _mouseStop: function(event) { 40355 40356 //If we are using droppables, inform the manager about the drop 40357 var that = this, 40358 dropped = false; 40359 if ($.ui.ddmanager && !this.options.dropBehaviour) { 40360 dropped = $.ui.ddmanager.drop(this, event); 40361 } 40362 40363 //if a drop comes from outside (a sortable) 40364 if (this.dropped) { 40365 dropped = this.dropped; 40366 this.dropped = false; 40367 } 40368 40369 if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { 40370 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 40371 if (that._trigger("stop", event) !== false) { 40372 that._clear(); 40373 } 40374 }); 40375 } else { 40376 if (this._trigger("stop", event) !== false) { 40377 this._clear(); 40378 } 40379 } 40380 40381 return false; 40382 }, 40383 40384 _mouseUp: function( event ) { 40385 this._unblockFrames(); 40386 40387 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 40388 if ( $.ui.ddmanager ) { 40389 $.ui.ddmanager.dragStop(this, event); 40390 } 40391 40392 // Only need to focus if the event occurred on the draggable itself, see #10527 40393 if ( this.handleElement.is( event.target ) ) { 40394 // The interaction is over; whether or not the click resulted in a drag, focus the element 40395 this.element.focus(); 40396 } 40397 40398 return $.ui.mouse.prototype._mouseUp.call(this, event); 40399 }, 40400 40401 cancel: function() { 40402 40403 if (this.helper.is(".ui-draggable-dragging")) { 40404 this._mouseUp({}); 40405 } else { 40406 this._clear(); 40407 } 40408 40409 return this; 40410 40411 }, 40412 40413 _getHandle: function(event) { 40414 return this.options.handle ? 40415 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 40416 true; 40417 }, 40418 40419 _setHandleClassName: function() { 40420 this.handleElement = this.options.handle ? 40421 this.element.find( this.options.handle ) : this.element; 40422 this.handleElement.addClass( "ui-draggable-handle" ); 40423 }, 40424 40425 _removeHandleClassName: function() { 40426 this.handleElement.removeClass( "ui-draggable-handle" ); 40427 }, 40428 40429 _createHelper: function(event) { 40430 40431 var o = this.options, 40432 helperIsFunction = $.isFunction( o.helper ), 40433 helper = helperIsFunction ? 40434 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : 40435 ( o.helper === "clone" ? 40436 this.element.clone().removeAttr( "id" ) : 40437 this.element ); 40438 40439 if (!helper.parents("body").length) { 40440 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); 40441 } 40442 40443 // http://bugs.jqueryui.com/ticket/9446 40444 // a helper function can return the original element 40445 // which wouldn't have been set to relative in _create 40446 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { 40447 this._setPositionRelative(); 40448 } 40449 40450 if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { 40451 helper.css("position", "absolute"); 40452 } 40453 40454 return helper; 40455 40456 }, 40457 40458 _setPositionRelative: function() { 40459 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { 40460 this.element[ 0 ].style.position = "relative"; 40461 } 40462 }, 40463 40464 _adjustOffsetFromHelper: function(obj) { 40465 if (typeof obj === "string") { 40466 obj = obj.split(" "); 40467 } 40468 if ($.isArray(obj)) { 40469 obj = { left: +obj[0], top: +obj[1] || 0 }; 40470 } 40471 if ("left" in obj) { 40472 this.offset.click.left = obj.left + this.margins.left; 40473 } 40474 if ("right" in obj) { 40475 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 40476 } 40477 if ("top" in obj) { 40478 this.offset.click.top = obj.top + this.margins.top; 40479 } 40480 if ("bottom" in obj) { 40481 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 40482 } 40483 }, 40484 40485 _isRootNode: function( element ) { 40486 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; 40487 }, 40488 40489 _getParentOffset: function() { 40490 40491 //Get the offsetParent and cache its position 40492 var po = this.offsetParent.offset(), 40493 document = this.document[ 0 ]; 40494 40495 // This is a special case where we need to modify a offset calculated on start, since the following happened: 40496 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 40497 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 40498 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 40499 if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 40500 po.left += this.scrollParent.scrollLeft(); 40501 po.top += this.scrollParent.scrollTop(); 40502 } 40503 40504 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { 40505 po = { top: 0, left: 0 }; 40506 } 40507 40508 return { 40509 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), 40510 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) 40511 }; 40512 40513 }, 40514 40515 _getRelativeOffset: function() { 40516 if ( this.cssPosition !== "relative" ) { 40517 return { top: 0, left: 0 }; 40518 } 40519 40520 var p = this.element.position(), 40521 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 40522 40523 return { 40524 top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), 40525 left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) 40526 }; 40527 40528 }, 40529 40530 _cacheMargins: function() { 40531 this.margins = { 40532 left: (parseInt(this.element.css("marginLeft"), 10) || 0), 40533 top: (parseInt(this.element.css("marginTop"), 10) || 0), 40534 right: (parseInt(this.element.css("marginRight"), 10) || 0), 40535 bottom: (parseInt(this.element.css("marginBottom"), 10) || 0) 40536 }; 40537 }, 40538 40539 _cacheHelperProportions: function() { 40540 this.helperProportions = { 40541 width: this.helper.outerWidth(), 40542 height: this.helper.outerHeight() 40543 }; 40544 }, 40545 40546 _setContainment: function() { 40547 40548 var isUserScrollable, c, ce, 40549 o = this.options, 40550 document = this.document[ 0 ]; 40551 40552 this.relativeContainer = null; 40553 40554 if ( !o.containment ) { 40555 this.containment = null; 40556 return; 40557 } 40558 40559 if ( o.containment === "window" ) { 40560 this.containment = [ 40561 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 40562 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 40563 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, 40564 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 40565 ]; 40566 return; 40567 } 40568 40569 if ( o.containment === "document") { 40570 this.containment = [ 40571 0, 40572 0, 40573 $( document ).width() - this.helperProportions.width - this.margins.left, 40574 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 40575 ]; 40576 return; 40577 } 40578 40579 if ( o.containment.constructor === Array ) { 40580 this.containment = o.containment; 40581 return; 40582 } 40583 40584 if ( o.containment === "parent" ) { 40585 o.containment = this.helper[ 0 ].parentNode; 40586 } 40587 40588 c = $( o.containment ); 40589 ce = c[ 0 ]; 40590 40591 if ( !ce ) { 40592 return; 40593 } 40594 40595 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); 40596 40597 this.containment = [ 40598 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 40599 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), 40600 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 40601 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - 40602 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - 40603 this.helperProportions.width - 40604 this.margins.left - 40605 this.margins.right, 40606 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 40607 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - 40608 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - 40609 this.helperProportions.height - 40610 this.margins.top - 40611 this.margins.bottom 40612 ]; 40613 this.relativeContainer = c; 40614 }, 40615 40616 _convertPositionTo: function(d, pos) { 40617 40618 if (!pos) { 40619 pos = this.position; 40620 } 40621 40622 var mod = d === "absolute" ? 1 : -1, 40623 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 40624 40625 return { 40626 top: ( 40627 pos.top + // The absolute mouse position 40628 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 40629 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 40630 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod) 40631 ), 40632 left: ( 40633 pos.left + // The absolute mouse position 40634 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 40635 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 40636 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod) 40637 ) 40638 }; 40639 40640 }, 40641 40642 _generatePosition: function( event, constrainPosition ) { 40643 40644 var containment, co, top, left, 40645 o = this.options, 40646 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), 40647 pageX = event.pageX, 40648 pageY = event.pageY; 40649 40650 // Cache the scroll 40651 if ( !scrollIsRootNode || !this.offset.scroll ) { 40652 this.offset.scroll = { 40653 top: this.scrollParent.scrollTop(), 40654 left: this.scrollParent.scrollLeft() 40655 }; 40656 } 40657 40658 /* 40659 * - Position constraining - 40660 * Constrain the position to a mix of grid, containment. 40661 */ 40662 40663 // If we are not dragging yet, we won't check for options 40664 if ( constrainPosition ) { 40665 if ( this.containment ) { 40666 if ( this.relativeContainer ){ 40667 co = this.relativeContainer.offset(); 40668 containment = [ 40669 this.containment[ 0 ] + co.left, 40670 this.containment[ 1 ] + co.top, 40671 this.containment[ 2 ] + co.left, 40672 this.containment[ 3 ] + co.top 40673 ]; 40674 } else { 40675 containment = this.containment; 40676 } 40677 40678 if (event.pageX - this.offset.click.left < containment[0]) { 40679 pageX = containment[0] + this.offset.click.left; 40680 } 40681 if (event.pageY - this.offset.click.top < containment[1]) { 40682 pageY = containment[1] + this.offset.click.top; 40683 } 40684 if (event.pageX - this.offset.click.left > containment[2]) { 40685 pageX = containment[2] + this.offset.click.left; 40686 } 40687 if (event.pageY - this.offset.click.top > containment[3]) { 40688 pageY = containment[3] + this.offset.click.top; 40689 } 40690 } 40691 40692 if (o.grid) { 40693 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 40694 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 40695 pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; 40696 40697 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 40698 pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; 40699 } 40700 40701 if ( o.axis === "y" ) { 40702 pageX = this.originalPageX; 40703 } 40704 40705 if ( o.axis === "x" ) { 40706 pageY = this.originalPageY; 40707 } 40708 } 40709 40710 return { 40711 top: ( 40712 pageY - // The absolute mouse position 40713 this.offset.click.top - // Click offset (relative to the element) 40714 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 40715 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 40716 ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) 40717 ), 40718 left: ( 40719 pageX - // The absolute mouse position 40720 this.offset.click.left - // Click offset (relative to the element) 40721 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 40722 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 40723 ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) 40724 ) 40725 }; 40726 40727 }, 40728 40729 _clear: function() { 40730 this.helper.removeClass("ui-draggable-dragging"); 40731 if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { 40732 this.helper.remove(); 40733 } 40734 this.helper = null; 40735 this.cancelHelperRemoval = false; 40736 if ( this.destroyOnClear ) { 40737 this.destroy(); 40738 } 40739 }, 40740 40741 _normalizeRightBottom: function() { 40742 if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) { 40743 this.helper.width( this.helper.width() ); 40744 this.helper.css( "right", "auto" ); 40745 } 40746 if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) { 40747 this.helper.height( this.helper.height() ); 40748 this.helper.css( "bottom", "auto" ); 40749 } 40750 }, 40751 40752 // From now on bulk stuff - mainly helpers 40753 40754 _trigger: function( type, event, ui ) { 40755 ui = ui || this._uiHash(); 40756 $.ui.plugin.call( this, type, [ event, ui, this ], true ); 40757 40758 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 40759 if ( /^(drag|start|stop)/.test( type ) ) { 40760 this.positionAbs = this._convertPositionTo( "absolute" ); 40761 ui.offset = this.positionAbs; 40762 } 40763 return $.Widget.prototype._trigger.call( this, type, event, ui ); 40764 }, 40765 40766 plugins: {}, 40767 40768 _uiHash: function() { 40769 return { 40770 helper: this.helper, 40771 position: this.position, 40772 originalPosition: this.originalPosition, 40773 offset: this.positionAbs 40774 }; 40775 } 40776 40777}); 40778 40779$.ui.plugin.add( "draggable", "connectToSortable", { 40780 start: function( event, ui, draggable ) { 40781 var uiSortable = $.extend( {}, ui, { 40782 item: draggable.element 40783 }); 40784 40785 draggable.sortables = []; 40786 $( draggable.options.connectToSortable ).each(function() { 40787 var sortable = $( this ).sortable( "instance" ); 40788 40789 if ( sortable && !sortable.options.disabled ) { 40790 draggable.sortables.push( sortable ); 40791 40792 // refreshPositions is called at drag start to refresh the containerCache 40793 // which is used in drag. This ensures it's initialized and synchronized 40794 // with any changes that might have happened on the page since initialization. 40795 sortable.refreshPositions(); 40796 sortable._trigger("activate", event, uiSortable); 40797 } 40798 }); 40799 }, 40800 stop: function( event, ui, draggable ) { 40801 var uiSortable = $.extend( {}, ui, { 40802 item: draggable.element 40803 }); 40804 40805 draggable.cancelHelperRemoval = false; 40806 40807 $.each( draggable.sortables, function() { 40808 var sortable = this; 40809 40810 if ( sortable.isOver ) { 40811 sortable.isOver = 0; 40812 40813 // Allow this sortable to handle removing the helper 40814 draggable.cancelHelperRemoval = true; 40815 sortable.cancelHelperRemoval = false; 40816 40817 // Use _storedCSS To restore properties in the sortable, 40818 // as this also handles revert (#9675) since the draggable 40819 // may have modified them in unexpected ways (#8809) 40820 sortable._storedCSS = { 40821 position: sortable.placeholder.css( "position" ), 40822 top: sortable.placeholder.css( "top" ), 40823 left: sortable.placeholder.css( "left" ) 40824 }; 40825 40826 sortable._mouseStop(event); 40827 40828 // Once drag has ended, the sortable should return to using 40829 // its original helper, not the shared helper from draggable 40830 sortable.options.helper = sortable.options._helper; 40831 } else { 40832 // Prevent this Sortable from removing the helper. 40833 // However, don't set the draggable to remove the helper 40834 // either as another connected Sortable may yet handle the removal. 40835 sortable.cancelHelperRemoval = true; 40836 40837 sortable._trigger( "deactivate", event, uiSortable ); 40838 } 40839 }); 40840 }, 40841 drag: function( event, ui, draggable ) { 40842 $.each( draggable.sortables, function() { 40843 var innermostIntersecting = false, 40844 sortable = this; 40845 40846 // Copy over variables that sortable's _intersectsWith uses 40847 sortable.positionAbs = draggable.positionAbs; 40848 sortable.helperProportions = draggable.helperProportions; 40849 sortable.offset.click = draggable.offset.click; 40850 40851 if ( sortable._intersectsWith( sortable.containerCache ) ) { 40852 innermostIntersecting = true; 40853 40854 $.each( draggable.sortables, function() { 40855 // Copy over variables that sortable's _intersectsWith uses 40856 this.positionAbs = draggable.positionAbs; 40857 this.helperProportions = draggable.helperProportions; 40858 this.offset.click = draggable.offset.click; 40859 40860 if ( this !== sortable && 40861 this._intersectsWith( this.containerCache ) && 40862 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { 40863 innermostIntersecting = false; 40864 } 40865 40866 return innermostIntersecting; 40867 }); 40868 } 40869 40870 if ( innermostIntersecting ) { 40871 // If it intersects, we use a little isOver variable and set it once, 40872 // so that the move-in stuff gets fired only once. 40873 if ( !sortable.isOver ) { 40874 sortable.isOver = 1; 40875 40876 sortable.currentItem = ui.helper 40877 .appendTo( sortable.element ) 40878 .data( "ui-sortable-item", true ); 40879 40880 // Store helper option to later restore it 40881 sortable.options._helper = sortable.options.helper; 40882 40883 sortable.options.helper = function() { 40884 return ui.helper[ 0 ]; 40885 }; 40886 40887 // Fire the start events of the sortable with our passed browser event, 40888 // and our own helper (so it doesn't create a new one) 40889 event.target = sortable.currentItem[ 0 ]; 40890 sortable._mouseCapture( event, true ); 40891 sortable._mouseStart( event, true, true ); 40892 40893 // Because the browser event is way off the new appended portlet, 40894 // modify necessary variables to reflect the changes 40895 sortable.offset.click.top = draggable.offset.click.top; 40896 sortable.offset.click.left = draggable.offset.click.left; 40897 sortable.offset.parent.left -= draggable.offset.parent.left - 40898 sortable.offset.parent.left; 40899 sortable.offset.parent.top -= draggable.offset.parent.top - 40900 sortable.offset.parent.top; 40901 40902 draggable._trigger( "toSortable", event ); 40903 40904 // Inform draggable that the helper is in a valid drop zone, 40905 // used solely in the revert option to handle "valid/invalid". 40906 draggable.dropped = sortable.element; 40907 40908 // Need to refreshPositions of all sortables in the case that 40909 // adding to one sortable changes the location of the other sortables (#9675) 40910 $.each( draggable.sortables, function() { 40911 this.refreshPositions(); 40912 }); 40913 40914 // hack so receive/update callbacks work (mostly) 40915 draggable.currentItem = draggable.element; 40916 sortable.fromOutside = draggable; 40917 } 40918 40919 if ( sortable.currentItem ) { 40920 sortable._mouseDrag( event ); 40921 // Copy the sortable's position because the draggable's can potentially reflect 40922 // a relative position, while sortable is always absolute, which the dragged 40923 // element has now become. (#8809) 40924 ui.position = sortable.position; 40925 } 40926 } else { 40927 // If it doesn't intersect with the sortable, and it intersected before, 40928 // we fake the drag stop of the sortable, but make sure it doesn't remove 40929 // the helper by using cancelHelperRemoval. 40930 if ( sortable.isOver ) { 40931 40932 sortable.isOver = 0; 40933 sortable.cancelHelperRemoval = true; 40934 40935 // Calling sortable's mouseStop would trigger a revert, 40936 // so revert must be temporarily false until after mouseStop is called. 40937 sortable.options._revert = sortable.options.revert; 40938 sortable.options.revert = false; 40939 40940 sortable._trigger( "out", event, sortable._uiHash( sortable ) ); 40941 sortable._mouseStop( event, true ); 40942 40943 // restore sortable behaviors that were modfied 40944 // when the draggable entered the sortable area (#9481) 40945 sortable.options.revert = sortable.options._revert; 40946 sortable.options.helper = sortable.options._helper; 40947 40948 if ( sortable.placeholder ) { 40949 sortable.placeholder.remove(); 40950 } 40951 40952 // Recalculate the draggable's offset considering the sortable 40953 // may have modified them in unexpected ways (#8809) 40954 draggable._refreshOffsets( event ); 40955 ui.position = draggable._generatePosition( event, true ); 40956 40957 draggable._trigger( "fromSortable", event ); 40958 40959 // Inform draggable that the helper is no longer in a valid drop zone 40960 draggable.dropped = false; 40961 40962 // Need to refreshPositions of all sortables just in case removing 40963 // from one sortable changes the location of other sortables (#9675) 40964 $.each( draggable.sortables, function() { 40965 this.refreshPositions(); 40966 }); 40967 } 40968 } 40969 }); 40970 } 40971}); 40972 40973$.ui.plugin.add("draggable", "cursor", { 40974 start: function( event, ui, instance ) { 40975 var t = $( "body" ), 40976 o = instance.options; 40977 40978 if (t.css("cursor")) { 40979 o._cursor = t.css("cursor"); 40980 } 40981 t.css("cursor", o.cursor); 40982 }, 40983 stop: function( event, ui, instance ) { 40984 var o = instance.options; 40985 if (o._cursor) { 40986 $("body").css("cursor", o._cursor); 40987 } 40988 } 40989}); 40990 40991$.ui.plugin.add("draggable", "opacity", { 40992 start: function( event, ui, instance ) { 40993 var t = $( ui.helper ), 40994 o = instance.options; 40995 if (t.css("opacity")) { 40996 o._opacity = t.css("opacity"); 40997 } 40998 t.css("opacity", o.opacity); 40999 }, 41000 stop: function( event, ui, instance ) { 41001 var o = instance.options; 41002 if (o._opacity) { 41003 $(ui.helper).css("opacity", o._opacity); 41004 } 41005 } 41006}); 41007 41008$.ui.plugin.add("draggable", "scroll", { 41009 start: function( event, ui, i ) { 41010 if ( !i.scrollParentNotHidden ) { 41011 i.scrollParentNotHidden = i.helper.scrollParent( false ); 41012 } 41013 41014 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { 41015 i.overflowOffset = i.scrollParentNotHidden.offset(); 41016 } 41017 }, 41018 drag: function( event, ui, i ) { 41019 41020 var o = i.options, 41021 scrolled = false, 41022 scrollParent = i.scrollParentNotHidden[ 0 ], 41023 document = i.document[ 0 ]; 41024 41025 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { 41026 if ( !o.axis || o.axis !== "x" ) { 41027 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) { 41028 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 41029 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { 41030 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 41031 } 41032 } 41033 41034 if ( !o.axis || o.axis !== "y" ) { 41035 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) { 41036 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 41037 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { 41038 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 41039 } 41040 } 41041 41042 } else { 41043 41044 if (!o.axis || o.axis !== "x") { 41045 if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 41046 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 41047 } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 41048 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 41049 } 41050 } 41051 41052 if (!o.axis || o.axis !== "y") { 41053 if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 41054 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 41055 } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 41056 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 41057 } 41058 } 41059 41060 } 41061 41062 if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 41063 $.ui.ddmanager.prepareOffsets(i, event); 41064 } 41065 41066 } 41067}); 41068 41069$.ui.plugin.add("draggable", "snap", { 41070 start: function( event, ui, i ) { 41071 41072 var o = i.options; 41073 41074 i.snapElements = []; 41075 41076 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { 41077 var $t = $(this), 41078 $o = $t.offset(); 41079 if (this !== i.element[0]) { 41080 i.snapElements.push({ 41081 item: this, 41082 width: $t.outerWidth(), height: $t.outerHeight(), 41083 top: $o.top, left: $o.left 41084 }); 41085 } 41086 }); 41087 41088 }, 41089 drag: function( event, ui, inst ) { 41090 41091 var ts, bs, ls, rs, l, r, t, b, i, first, 41092 o = inst.options, 41093 d = o.snapTolerance, 41094 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 41095 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 41096 41097 for (i = inst.snapElements.length - 1; i >= 0; i--){ 41098 41099 l = inst.snapElements[i].left - inst.margins.left; 41100 r = l + inst.snapElements[i].width; 41101 t = inst.snapElements[i].top - inst.margins.top; 41102 b = t + inst.snapElements[i].height; 41103 41104 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { 41105 if (inst.snapElements[i].snapping) { 41106 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 41107 } 41108 inst.snapElements[i].snapping = false; 41109 continue; 41110 } 41111 41112 if (o.snapMode !== "inner") { 41113 ts = Math.abs(t - y2) <= d; 41114 bs = Math.abs(b - y1) <= d; 41115 ls = Math.abs(l - x2) <= d; 41116 rs = Math.abs(r - x1) <= d; 41117 if (ts) { 41118 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top; 41119 } 41120 if (bs) { 41121 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top; 41122 } 41123 if (ls) { 41124 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left; 41125 } 41126 if (rs) { 41127 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left; 41128 } 41129 } 41130 41131 first = (ts || bs || ls || rs); 41132 41133 if (o.snapMode !== "outer") { 41134 ts = Math.abs(t - y1) <= d; 41135 bs = Math.abs(b - y2) <= d; 41136 ls = Math.abs(l - x1) <= d; 41137 rs = Math.abs(r - x2) <= d; 41138 if (ts) { 41139 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top; 41140 } 41141 if (bs) { 41142 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top; 41143 } 41144 if (ls) { 41145 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left; 41146 } 41147 if (rs) { 41148 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left; 41149 } 41150 } 41151 41152 if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { 41153 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 41154 } 41155 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 41156 41157 } 41158 41159 } 41160}); 41161 41162$.ui.plugin.add("draggable", "stack", { 41163 start: function( event, ui, instance ) { 41164 var min, 41165 o = instance.options, 41166 group = $.makeArray($(o.stack)).sort(function(a, b) { 41167 return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0); 41168 }); 41169 41170 if (!group.length) { return; } 41171 41172 min = parseInt($(group[0]).css("zIndex"), 10) || 0; 41173 $(group).each(function(i) { 41174 $(this).css("zIndex", min + i); 41175 }); 41176 this.css("zIndex", (min + group.length)); 41177 } 41178}); 41179 41180$.ui.plugin.add("draggable", "zIndex", { 41181 start: function( event, ui, instance ) { 41182 var t = $( ui.helper ), 41183 o = instance.options; 41184 41185 if (t.css("zIndex")) { 41186 o._zIndex = t.css("zIndex"); 41187 } 41188 t.css("zIndex", o.zIndex); 41189 }, 41190 stop: function( event, ui, instance ) { 41191 var o = instance.options; 41192 41193 if (o._zIndex) { 41194 $(ui.helper).css("zIndex", o._zIndex); 41195 } 41196 } 41197}); 41198 41199return $.ui.draggable; 41200 41201})); 41202 41203}, 41204'jquery-ui/ui/mouse':function(){ 41205/*! 41206 * jQuery UI Mouse 1.11.2 41207 * http://jqueryui.com
vendor: 3,606 bytes, lines 41208-41334
41208 * 41209 * Copyright 2014 jQuery Foundation and other contributors 41210 * Released under the MIT license. 41211 * http://jquery.org/license 41212 * 41213 * http://api.jqueryui.com/mouse/ 41214 */ 41215(function( factory ) { 41216 if ( typeof define === "function" && define.amd ) { 41217 41218 // AMD. Register as an anonymous module. 41219 define([ 41220 "jquery", 41221 "./widget" 41222 ], factory ); 41223 } else { 41224 41225 // Browser globals 41226 factory( jQuery ); 41227 } 41228}(function( $ ) { 41229 41230var mouseHandled = false; 41231$( document ).mouseup( function() { 41232 mouseHandled = false; 41233}); 41234 41235return $.widget("ui.mouse", { 41236 version: "1.11.2", 41237 options: { 41238 cancel: "input,textarea,button,select,option", 41239 distance: 1, 41240 delay: 0 41241 }, 41242 _mouseInit: function() { 41243 var that = this; 41244 41245 this.element 41246 .bind("mousedown." + this.widgetName, function(event) { 41247 return that._mouseDown(event); 41248 }) 41249 .bind("click." + this.widgetName, function(event) { 41250 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { 41251 $.removeData(event.target, that.widgetName + ".preventClickEvent"); 41252 event.stopImmediatePropagation(); 41253 return false; 41254 } 41255 }); 41256 41257 this.started = false; 41258 }, 41259 41260 // TODO: make sure destroying one instance of mouse doesn't mess with 41261 // other instances of mouse 41262 _mouseDestroy: function() { 41263 this.element.unbind("." + this.widgetName); 41264 if ( this._mouseMoveDelegate ) { 41265 this.document 41266 .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate) 41267 .unbind("mouseup." + this.widgetName, this._mouseUpDelegate); 41268 } 41269 }, 41270 41271 _mouseDown: function(event) { 41272 // don't let more than one widget handle mouseStart 41273 if ( mouseHandled ) { 41274 return; 41275 } 41276 41277 this._mouseMoved = false; 41278 41279 // we may have missed mouseup (out of window) 41280 (this._mouseStarted && this._mouseUp(event)); 41281 41282 this._mouseDownEvent = event; 41283 41284 var that = this, 41285 btnIsLeft = (event.which === 1), 41286 // event.target.nodeName works around a bug in IE 8 with 41287 // disabled inputs (#7620) 41288 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 41289 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 41290 return true; 41291 } 41292 41293 this.mouseDelayMet = !this.options.delay; 41294 if (!this.mouseDelayMet) { 41295 this._mouseDelayTimer = setTimeout(function() { 41296 that.mouseDelayMet = true; 41297 }, this.options.delay); 41298 } 41299 41300 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 41301 this._mouseStarted = (this._mouseStart(event) !== false); 41302 if (!this._mouseStarted) { 41303 event.preventDefault(); 41304 return true; 41305 } 41306 } 41307 41308 // Click event may never have fired (Gecko & Opera) 41309 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { 41310 $.removeData(event.target, this.widgetName + ".preventClickEvent"); 41311 } 41312 41313 // these delegates are required to keep context 41314 this._mouseMoveDelegate = function(event) { 41315 return that._mouseMove(event); 41316 }; 41317 this._mouseUpDelegate = function(event) { 41318 return that._mouseUp(event); 41319 }; 41320 41321 this.document 41322 .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 41323 .bind( "mouseup." + this.widgetName, this._mouseUpDelegate ); 41324 41325 event.preventDefault(); 41326 41327 mouseHandled = true; 41328 return true; 41329 }, 41330 41331 _mouseMove: function(event) { 41332 // Only check for mouseups outside the document if you've moved inside the document 41333 // at least once. This prevents the firing of mouseup in the case of IE<9, which will 41334 // fire a mousemove event if content is placed under the cursor. See #7778
41335 // Support: IE <9 41336 if ( this._mouseMoved ) { 41337 // IE mouseup check - mouseup happened when mouse was out of window 41338 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { 41339 return this._mouseUp(event); 41340 41341 // Iframe mouseup check - mouseup occurred in another document 41342 } else if ( !event.which ) { 41343 return this._mouseUp( event ); 41344 } 41345 } 41346 41347 if ( event.which || event.button ) { 41348 this._mouseMoved = true; 41349 } 41350 41351 if (this._mouseStarted) { 41352 this._mouseDrag(event); 41353 return event.preventDefault(); 41354 } 41355 41356 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 41357 this._mouseStarted = 41358 (this._mouseStart(this._mouseDownEvent, event) !== false); 41359 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 41360 } 41361 41362 return !this._mouseStarted; 41363 }, 41364 41365 _mouseUp: function(event) { 41366 this.document 41367 .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 41368 .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate ); 41369 41370 if (this._mouseStarted) { 41371 this._mouseStarted = false; 41372 41373 if (event.target === this._mouseDownEvent.target) { 41374 $.data(event.target, this.widgetName + ".preventClickEvent", true); 41375 } 41376 41377 this._mouseStop(event); 41378 } 41379 41380 mouseHandled = false; 41381 return false; 41382 }, 41383 41384 _mouseDistanceMet: function(event) { 41385 return (Math.max( 41386 Math.abs(this._mouseDownEvent.pageX - event.pageX), 41387 Math.abs(this._mouseDownEvent.pageY - event.pageY) 41388 ) >= this.options.distance 41389 ); 41390 }, 41391 41392 _mouseDelayMet: function(/* event */) { 41393 return this.mouseDelayMet; 41394 }, 41395 41396 // These are placeholder methods, to be overriden by extending plugin 41397 _mouseStart: function(/* event */) {}, 41398 _mouseDrag: function(/* event */) {}, 41399 _mouseStop: function(/* event */) {}, 41400 _mouseCapture: function(/* event */) { return true; } 41401}); 41402 41403})); 41404 41405}, 41406'jquery-ui/ui/position':function(){ 41407/*! 41408 * jQuery UI Position 1.11.2 41409 * http://jqueryui.com 41410 * 41411 * Copyright 2014 jQuery Foundation and other contributors 41412 * Released under the MIT license. 41413 * http://jquery.org/license 41414 * 41415 * http://api.jqueryui.com/position/ 41416 */ 41417(function( factory ) { 41418 if ( typeof define === "function" && define.amd ) { 41419 41420 // AMD. Register as an anonymous module. 41421 define( [ "jquery" ], factory ); 41422 } else { 41423 41424 // Browser globals 41425 factory( jQuery ); 41426 } 41427}(function( $ ) { 41428(function() { 41429 41430$.ui = $.ui || {}; 41431 41432var cachedScrollbarWidth, supportsOffsetFractions, 41433 max = Math.max, 41434 abs = Math.abs, 41435 round = Math.round, 41436 rhorizontal = /left|center|right/, 41437 rvertical = /top|center|bottom/, 41438 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 41439 rposition = /^\w+/, 41440 rpercent = /%$/, 41441 _position = $.fn.position; 41442 41443function getOffsets( offsets, width, height ) { 41444 return [ 41445 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 41446 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 41447 ]; 41448} 41449 41450function parseCss( element, property ) { 41451 return parseInt( $.css( element, property ), 10 ) || 0; 41452} 41453 41454function getDimensions( elem ) { 41455 var raw = elem[0]; 41456 if ( raw.nodeType === 9 ) { 41457 return { 41458 width: elem.width(), 41459 height: elem.height(), 41460 offset: { top: 0, left: 0 } 41461 }; 41462 } 41463 if ( $.isWindow( raw ) ) { 41464 return { 41465 width: elem.width(), 41466 height: elem.height(), 41467 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 41468 }; 41469 } 41470 if ( raw.preventDefault ) { 41471 return { 41472 width: 0, 41473 height: 0, 41474 offset: { top: raw.pageY, left: raw.pageX } 41475 }; 41476 } 41477 return { 41478 width: elem.outerWidth(), 41479 height: elem.outerHeight(), 41480 offset: elem.offset() 41481 }; 41482} 41483 41484$.position = { 41485 scrollbarWidth: function() { 41486 if ( cachedScrollbarWidth !== undefined ) { 41487 return cachedScrollbarWidth; 41488 } 41489 var w1, w2, 41490 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), 41491 innerDiv = div.children()[0]; 41492 41493 $( "body" ).append( div ); 41494 w1 = innerDiv.offsetWidth; 41495 div.css( "overflow", "scroll" ); 41496 41497 w2 = innerDiv.offsetWidth; 41498 41499 if ( w1 === w2 ) { 41500 w2 = div[0].clientWidth; 41501 } 41502 41503 div.remove(); 41504 41505 return (cachedScrollbarWidth = w1 - w2); 41506 }, 41507 getScrollInfo: function( within ) { 41508 var overflowX = within.isWindow || within.isDocument ? "" : 41509 within.element.css( "overflow-x" ), 41510 overflowY = within.isWindow || within.isDocument ? "" : 41511 within.element.css( "overflow-y" ), 41512 hasOverflowX = overflowX === "scroll" || 41513 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), 41514 hasOverflowY = overflowY === "scroll" || 41515 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); 41516 return { 41517 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 41518 height: hasOverflowX ? $.position.scrollbarWidth() : 0 41519 }; 41520 }, 41521 getWithinInfo: function( element ) { 41522 var withinElement = $( element || window ), 41523 isWindow = $.isWindow( withinElement[0] ), 41524 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; 41525 return { 41526 element: withinElement, 41527 isWindow: isWindow, 41528 isDocument: isDocument,
vendor: 6,607 bytes, lines 41529-41731
41529 offset: withinElement.offset() || { left: 0, top: 0 }, 41530 scrollLeft: withinElement.scrollLeft(), 41531 scrollTop: withinElement.scrollTop(), 41532 41533 // support: jQuery 1.6.x 41534 // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows 41535 width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(), 41536 height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight() 41537 }; 41538 } 41539}; 41540 41541$.fn.position = function( options ) { 41542 if ( !options || !options.of ) { 41543 return _position.apply( this, arguments ); 41544 } 41545 41546 // make a copy, we don't want to modify arguments 41547 options = $.extend( {}, options ); 41548 41549 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 41550 target = $( options.of ), 41551 within = $.position.getWithinInfo( options.within ), 41552 scrollInfo = $.position.getScrollInfo( within ), 41553 collision = ( options.collision || "flip" ).split( " " ), 41554 offsets = {}; 41555 41556 dimensions = getDimensions( target ); 41557 if ( target[0].preventDefault ) { 41558 // force left top to allow flipping 41559 options.at = "left top"; 41560 } 41561 targetWidth = dimensions.width; 41562 targetHeight = dimensions.height; 41563 targetOffset = dimensions.offset; 41564 // clone to reuse original targetOffset later 41565 basePosition = $.extend( {}, targetOffset ); 41566 41567 // force my and at to have valid horizontal and vertical positions 41568 // if a value is missing or invalid, it will be converted to center 41569 $.each( [ "my", "at" ], function() { 41570 var pos = ( options[ this ] || "" ).split( " " ), 41571 horizontalOffset, 41572 verticalOffset; 41573 41574 if ( pos.length === 1) { 41575 pos = rhorizontal.test( pos[ 0 ] ) ? 41576 pos.concat( [ "center" ] ) : 41577 rvertical.test( pos[ 0 ] ) ? 41578 [ "center" ].concat( pos ) : 41579 [ "center", "center" ]; 41580 } 41581 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 41582 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 41583 41584 // calculate offsets 41585 horizontalOffset = roffset.exec( pos[ 0 ] ); 41586 verticalOffset = roffset.exec( pos[ 1 ] ); 41587 offsets[ this ] = [ 41588 horizontalOffset ? horizontalOffset[ 0 ] : 0, 41589 verticalOffset ? verticalOffset[ 0 ] : 0 41590 ]; 41591 41592 // reduce to just the positions without the offsets 41593 options[ this ] = [ 41594 rposition.exec( pos[ 0 ] )[ 0 ], 41595 rposition.exec( pos[ 1 ] )[ 0 ] 41596 ]; 41597 }); 41598 41599 // normalize collision option 41600 if ( collision.length === 1 ) { 41601 collision[ 1 ] = collision[ 0 ]; 41602 } 41603 41604 if ( options.at[ 0 ] === "right" ) { 41605 basePosition.left += targetWidth; 41606 } else if ( options.at[ 0 ] === "center" ) { 41607 basePosition.left += targetWidth / 2; 41608 } 41609 41610 if ( options.at[ 1 ] === "bottom" ) { 41611 basePosition.top += targetHeight; 41612 } else if ( options.at[ 1 ] === "center" ) { 41613 basePosition.top += targetHeight / 2; 41614 } 41615 41616 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 41617 basePosition.left += atOffset[ 0 ]; 41618 basePosition.top += atOffset[ 1 ]; 41619 41620 return this.each(function() { 41621 var collisionPosition, using, 41622 elem = $( this ), 41623 elemWidth = elem.outerWidth(), 41624 elemHeight = elem.outerHeight(), 41625 marginLeft = parseCss( this, "marginLeft" ), 41626 marginTop = parseCss( this, "marginTop" ), 41627 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, 41628 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, 41629 position = $.extend( {}, basePosition ), 41630 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 41631 41632 if ( options.my[ 0 ] === "right" ) { 41633 position.left -= elemWidth; 41634 } else if ( options.my[ 0 ] === "center" ) { 41635 position.left -= elemWidth / 2; 41636 } 41637 41638 if ( options.my[ 1 ] === "bottom" ) { 41639 position.top -= elemHeight; 41640 } else if ( options.my[ 1 ] === "center" ) { 41641 position.top -= elemHeight / 2; 41642 } 41643 41644 position.left += myOffset[ 0 ]; 41645 position.top += myOffset[ 1 ]; 41646 41647 // if the browser doesn't support fractions, then round for consistent results 41648 if ( !supportsOffsetFractions ) { 41649 position.left = round( position.left ); 41650 position.top = round( position.top ); 41651 } 41652 41653 collisionPosition = { 41654 marginLeft: marginLeft, 41655 marginTop: marginTop 41656 }; 41657 41658 $.each( [ "left", "top" ], function( i, dir ) { 41659 if ( $.ui.position[ collision[ i ] ] ) { 41660 $.ui.position[ collision[ i ] ][ dir ]( position, { 41661 targetWidth: targetWidth, 41662 targetHeight: targetHeight, 41663 elemWidth: elemWidth, 41664 elemHeight: elemHeight, 41665 collisionPosition: collisionPosition, 41666 collisionWidth: collisionWidth, 41667 collisionHeight: collisionHeight, 41668 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 41669 my: options.my, 41670 at: options.at, 41671 within: within, 41672 elem: elem 41673 }); 41674 } 41675 }); 41676 41677 if ( options.using ) { 41678 // adds feedback as second argument to using callback, if present 41679 using = function( props ) { 41680 var left = targetOffset.left - position.left, 41681 right = left + targetWidth - elemWidth, 41682 top = targetOffset.top - position.top, 41683 bottom = top + targetHeight - elemHeight, 41684 feedback = { 41685 target: { 41686 element: target, 41687 left: targetOffset.left, 41688 top: targetOffset.top, 41689 width: targetWidth, 41690 height: targetHeight 41691 }, 41692 element: { 41693 element: elem, 41694 left: position.left, 41695 top: position.top, 41696 width: elemWidth, 41697 height: elemHeight 41698 }, 41699 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 41700 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 41701 }; 41702 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 41703 feedback.horizontal = "center"; 41704 } 41705 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 41706 feedback.vertical = "middle"; 41707 } 41708 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 41709 feedback.important = "horizontal"; 41710 } else { 41711 feedback.important = "vertical"; 41712 } 41713 options.using.call( this, props, feedback ); 41714 }; 41715 } 41716 41717 elem.offset( $.extend( position, { using: using } ) ); 41718 }); 41719}; 41720 41721$.ui.position = { 41722 fit: { 41723 left: function( position, data ) { 41724 var within = data.within, 41725 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 41726 outerWidth = within.width, 41727 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 41728 overLeft = withinOffset - collisionPosLeft, 41729 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 41730 newOverRight; 41731
41732 // element is wider than within 41733 if ( data.collisionWidth > outerWidth ) { 41734 // element is initially over the left side of within 41735 if ( overLeft > 0 && overRight <= 0 ) { 41736 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; 41737 position.left += overLeft - newOverRight; 41738 // element is initially over right side of within 41739 } else if ( overRight > 0 && overLeft <= 0 ) { 41740 position.left = withinOffset; 41741 // element is initially over both left and right sides of within 41742 } else { 41743 if ( overLeft > overRight ) { 41744 position.left = withinOffset + outerWidth - data.collisionWidth; 41745 } else { 41746 position.left = withinOffset; 41747 } 41748 } 41749 // too far left -> align with left edge 41750 } else if ( overLeft > 0 ) { 41751 position.left += overLeft; 41752 // too far right -> align with right edge 41753 } else if ( overRight > 0 ) { 41754 position.left -= overRight; 41755 // adjust based on position and margin 41756 } else { 41757 position.left = max( position.left - collisionPosLeft, position.left ); 41758 } 41759 }, 41760 top: function( position, data ) { 41761 var within = data.within, 41762 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 41763 outerHeight = data.within.height, 41764 collisionPosTop = position.top - data.collisionPosition.marginTop, 41765 overTop = withinOffset - collisionPosTop, 41766 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 41767 newOverBottom; 41768 41769 // element is taller than within 41770 if ( data.collisionHeight > outerHeight ) { 41771 // element is initially over the top of within 41772 if ( overTop > 0 && overBottom <= 0 ) { 41773 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; 41774 position.top += overTop - newOverBottom; 41775 // element is initially over bottom of within 41776 } else if ( overBottom > 0 && overTop <= 0 ) { 41777 position.top = withinOffset; 41778 // element is initially over both top and bottom of within 41779 } else { 41780 if ( overTop > overBottom ) { 41781 position.top = withinOffset + outerHeight - data.collisionHeight; 41782 } else { 41783 position.top = withinOffset; 41784 } 41785 } 41786 // too far up -> align with top 41787 } else if ( overTop > 0 ) { 41788 position.top += overTop; 41789 // too far down -> align with bottom edge 41790 } else if ( overBottom > 0 ) { 41791 position.top -= overBottom; 41792 // adjust based on position and margin 41793 } else { 41794 position.top = max( position.top - collisionPosTop, position.top ); 41795 } 41796 } 41797 }, 41798 flip: { 41799 left: function( position, data ) { 41800 var within = data.within, 41801 withinOffset = within.offset.left + within.scrollLeft, 41802 outerWidth = within.width, 41803 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 41804 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 41805 overLeft = collisionPosLeft - offsetLeft, 41806 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 41807 myOffset = data.my[ 0 ] === "left" ? 41808 -data.elemWidth : 41809 data.my[ 0 ] === "right" ? 41810 data.elemWidth : 41811 0, 41812 atOffset = data.at[ 0 ] === "left" ? 41813 data.targetWidth : 41814 data.at[ 0 ] === "right" ? 41815 -data.targetWidth : 41816 0, 41817 offset = -2 * data.offset[ 0 ], 41818 newOverRight, 41819 newOverLeft; 41820 41821 if ( overLeft < 0 ) { 41822 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; 41823 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 41824 position.left += myOffset + atOffset + offset; 41825 } 41826 } else if ( overRight > 0 ) { 41827 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; 41828 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 41829 position.left += myOffset + atOffset + offset; 41830 } 41831 } 41832 }, 41833 top: function( position, data ) { 41834 var within = data.within, 41835 withinOffset = within.offset.top + within.scrollTop, 41836 outerHeight = within.height, 41837 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 41838 collisionPosTop = position.top - data.collisionPosition.marginTop, 41839 overTop = collisionPosTop - offsetTop, 41840 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 41841 top = data.my[ 1 ] === "top", 41842 myOffset = top ? 41843 -data.elemHeight : 41844 data.my[ 1 ] === "bottom" ? 41845 data.elemHeight : 41846 0, 41847 atOffset = data.at[ 1 ] === "top" ? 41848 data.targetHeight : 41849 data.at[ 1 ] === "bottom" ? 41850 -data.targetHeight : 41851 0, 41852 offset = -2 * data.offset[ 1 ], 41853 newOverTop, 41854 newOverBottom; 41855 if ( overTop < 0 ) { 41856 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; 41857 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { 41858 position.top += myOffset + atOffset + offset; 41859 } 41860 } else if ( overBottom > 0 ) { 41861 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; 41862 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { 41863 position.top += myOffset + atOffset + offset; 41864 } 41865 } 41866 } 41867 }, 41868 flipfit: { 41869 left: function() { 41870 $.ui.position.flip.left.apply( this, arguments ); 41871 $.ui.position.fit.left.apply( this, arguments ); 41872 }, 41873 top: function() { 41874 $.ui.position.flip.top.apply( this, arguments ); 41875 $.ui.position.fit.top.apply( this, arguments ); 41876 } 41877 } 41878}; 41879 41880// fraction support test 41881(function() { 41882 var testElement, testElementParent, testElementStyle, offsetLeft, i, 41883 body = document.getElementsByTagName( "body" )[ 0 ], 41884 div = document.createElement( "div" ); 41885 41886 //Create a "fake body" for testing based on method used in jQuery.support 41887 testElement = document.createElement( body ? "div" : "body" ); 41888 testElementStyle = { 41889 visibility: "hidden", 41890 width: 0, 41891 height: 0, 41892 border: 0, 41893 margin: 0, 41894 background: "none" 41895 }; 41896 if ( body ) { 41897 $.extend( testElementStyle, { 41898 position: "absolute",
41899 left: "-1000px", 41900 top: "-1000px" 41901 }); 41902 } 41903 for ( i in testElementStyle ) { 41904 testElement.style[ i ] = testElementStyle[ i ]; 41905 } 41906 testElement.appendChild( div ); 41907 testElementParent = body || document.documentElement; 41908 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 41909 41910 div.style.cssText = "position: absolute; left: 10.7432222px;"; 41911 41912 offsetLeft = $( div ).offset().left; 41913 supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11; 41914 41915 testElement.innerHTML = ""; 41916 testElementParent.removeChild( testElement ); 41917})(); 41918 41919})(); 41920 41921return $.ui.position; 41922 41923})); 41924 41925}, 41926'jquery-ui/ui/resizable':function(){ 41927/*! 41928 * jQuery UI Resizable 1.11.2 41929 * http://jqueryui.com 41930 * 41931 * Copyright 2014 jQuery Foundation and other contributors 41932 * Released under the MIT license. 41933 * http://jquery.org/license 41934 * 41935 * http://api.jqueryui.com/resizable/ 41936 */ 41937(function( factory ) { 41938 if ( typeof define === "function" && define.amd ) { 41939 41940 // AMD. Register as an anonymous module. 41941 define([ 41942 "jquery", 41943 "./core", 41944 "./mouse", 41945 "./widget" 41946 ], factory ); 41947 } else { 41948 41949 // Browser globals 41950 factory( jQuery ); 41951 } 41952}(function( $ ) { 41953 41954$.widget("ui.resizable", $.ui.mouse, { 41955 version: "1.11.2", 41956 widgetEventPrefix: "resize", 41957 options: { 41958 alsoResize: false, 41959 animate: false, 41960 animateDuration: "slow", 41961 animateEasing: "swing", 41962 aspectRatio: false, 41963 autoHide: false, 41964 containment: false, 41965 ghost: false, 41966 grid: false, 41967 handles: "e,s,se", 41968 helper: false, 41969 maxHeight: null, 41970 maxWidth: null, 41971 minHeight: 10, 41972 minWidth: 10, 41973 // See #7960 41974 zIndex: 90, 41975 41976 // callbacks 41977 resize: null, 41978 start: null, 41979 stop: null 41980 }, 41981 41982 _num: function( value ) { 41983 return parseInt( value, 10 ) || 0; 41984 }, 41985 41986 _isNumber: function( value ) { 41987 return !isNaN( parseInt( value, 10 ) ); 41988 }, 41989 41990 _hasScroll: function( el, a ) { 41991 41992 if ( $( el ).css( "overflow" ) === "hidden") { 41993 return false; 41994 } 41995 41996 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 41997 has = false; 41998 41999 if ( el[ scroll ] > 0 ) { 42000 return true; 42001 } 42002 42003 // TODO: determine which cases actually cause this to happen 42004 // if the element doesn't have the scroll set, see if it's possible to 42005 // set the scroll 42006 el[ scroll ] = 1; 42007 has = ( el[ scroll ] > 0 ); 42008 el[ scroll ] = 0; 42009 return has; 42010 }, 42011 42012 _create: function() { 42013 42014 var n, i, handle, axis, hname, 42015 that = this, 42016 o = this.options; 42017 this.element.addClass("ui-resizable"); 42018 42019 $.extend(this, { 42020 _aspectRatio: !!(o.aspectRatio), 42021 aspectRatio: o.aspectRatio, 42022 originalElement: this.element, 42023 _proportionallyResizeElements: [], 42024 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 42025 }); 42026 42027 // Wrap the element if it cannot hold child nodes 42028 if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 42029 42030 this.element.wrap( 42031 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ 42032 position: this.element.css("position"), 42033 width: this.element.outerWidth(), 42034 height: this.element.outerHeight(), 42035 top: this.element.css("top"), 42036 left: this.element.css("left") 42037 }) 42038 ); 42039 42040 this.element = this.element.parent().data( 42041 "ui-resizable", this.element.resizable( "instance" ) 42042 ); 42043 42044 this.elementIsWrapper = true; 42045 42046 this.element.css({ 42047 marginLeft: this.originalElement.css("marginLeft"), 42048 marginTop: this.originalElement.css("marginTop"), 42049 marginRight: this.originalElement.css("marginRight"), 42050 marginBottom: this.originalElement.css("marginBottom") 42051 }); 42052 this.originalElement.css({ 42053 marginLeft: 0, 42054 marginTop: 0, 42055 marginRight: 0, 42056 marginBottom: 0 42057 }); 42058 // support: Safari 42059 // Prevent Safari textarea resize 42060 this.originalResizeStyle = this.originalElement.css("resize"); 42061 this.originalElement.css("resize", "none"); 42062 42063 this._proportionallyResizeElements.push( this.originalElement.css({ 42064 position: "static", 42065 zoom: 1, 42066 display: "block" 42067 }) ); 42068 42069 // support: IE9 42070 // avoid IE jump (hard set the margin) 42071 this.originalElement.css({ margin: this.originalElement.css("margin") }); 42072 42073 this._proportionallyResize(); 42074 } 42075 42076 this.handles = o.handles || 42077 ( !$(".ui-resizable-handle", this.element).length ? 42078 "e,s,se" : { 42079 n: ".ui-resizable-n", 42080 e: ".ui-resizable-e", 42081 s: ".ui-resizable-s", 42082 w: ".ui-resizable-w", 42083 se: ".ui-resizable-se", 42084 sw: ".ui-resizable-sw", 42085 ne: ".ui-resizable-ne", 42086 nw: ".ui-resizable-nw" 42087 } ); 42088 42089 if (this.handles.constructor === String) { 42090 42091 if ( this.handles === "all") { 42092 this.handles = "n,e,s,w,se,sw,ne,nw"; 42093 } 42094 42095 n = this.handles.split(","); 42096 this.handles = {}; 42097 42098 for (i = 0; i < n.length; i++) { 42099 42100 handle = $.trim(n[i]); 42101 hname = "ui-resizable-" + handle; 42102 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); 42103 42104 axis.css({ zIndex: o.zIndex }); 42105 42106 // TODO : What's going on here? 42107 if ("se" === handle) { 42108 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); 42109 } 42110 42111 this.handles[handle] = ".ui-resizable-" + handle; 42112 this.element.append(axis); 42113 } 42114 42115 } 42116 42117 this._renderAxis = function(target) { 42118 42119 var i, axis, padPos, padWrapper; 42120 42121 target = target || this.element; 42122 42123 for (i in this.handles) { 42124 42125 if (this.handles[i].constructor === String) { 42126 this.handles[i] = this.element.children( this.handles[ i ] ).first().show(); 42127 } 42128 42129 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 42130 42131 axis = $(this.handles[i], this.element); 42132 42133 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 42134 42135 padPos = [ "padding",
vendor: 11,791 bytes, lines 42136-42611
42136 /ne|nw|n/.test(i) ? "Top" : 42137 /se|sw|s/.test(i) ? "Bottom" : 42138 /^e$/.test(i) ? "Right" : "Left" ].join(""); 42139 42140 target.css(padPos, padWrapper); 42141 42142 this._proportionallyResize(); 42143 42144 } 42145 42146 // TODO: What's that good for? There's not anything to be executed left 42147 if (!$(this.handles[i]).length) { 42148 continue; 42149 } 42150 } 42151 }; 42152 42153 // TODO: make renderAxis a prototype function 42154 this._renderAxis(this.element); 42155 42156 this._handles = $(".ui-resizable-handle", this.element) 42157 .disableSelection(); 42158 42159 this._handles.mouseover(function() { 42160 if (!that.resizing) { 42161 if (this.className) { 42162 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 42163 } 42164 that.axis = axis && axis[1] ? axis[1] : "se"; 42165 } 42166 }); 42167 42168 if (o.autoHide) { 42169 this._handles.hide(); 42170 $(this.element) 42171 .addClass("ui-resizable-autohide") 42172 .mouseenter(function() { 42173 if (o.disabled) { 42174 return; 42175 } 42176 $(this).removeClass("ui-resizable-autohide"); 42177 that._handles.show(); 42178 }) 42179 .mouseleave(function() { 42180 if (o.disabled) { 42181 return; 42182 } 42183 if (!that.resizing) { 42184 $(this).addClass("ui-resizable-autohide"); 42185 that._handles.hide(); 42186 } 42187 }); 42188 } 42189 42190 this._mouseInit(); 42191 42192 }, 42193 42194 _destroy: function() { 42195 42196 this._mouseDestroy(); 42197 42198 var wrapper, 42199 _destroy = function(exp) { 42200 $(exp) 42201 .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 42202 .removeData("resizable") 42203 .removeData("ui-resizable") 42204 .unbind(".resizable") 42205 .find(".ui-resizable-handle") 42206 .remove(); 42207 }; 42208 42209 // TODO: Unwrap at same DOM position 42210 if (this.elementIsWrapper) { 42211 _destroy(this.element); 42212 wrapper = this.element; 42213 this.originalElement.css({ 42214 position: wrapper.css("position"), 42215 width: wrapper.outerWidth(), 42216 height: wrapper.outerHeight(), 42217 top: wrapper.css("top"), 42218 left: wrapper.css("left") 42219 }).insertAfter( wrapper ); 42220 wrapper.remove(); 42221 } 42222 42223 this.originalElement.css("resize", this.originalResizeStyle); 42224 _destroy(this.originalElement); 42225 42226 return this; 42227 }, 42228 42229 _mouseCapture: function(event) { 42230 var i, handle, 42231 capture = false; 42232 42233 for (i in this.handles) { 42234 handle = $(this.handles[i])[0]; 42235 if (handle === event.target || $.contains(handle, event.target)) { 42236 capture = true; 42237 } 42238 } 42239 42240 return !this.options.disabled && capture; 42241 }, 42242 42243 _mouseStart: function(event) { 42244 42245 var curleft, curtop, cursor, 42246 o = this.options, 42247 el = this.element; 42248 42249 this.resizing = true; 42250 42251 this._renderProxy(); 42252 42253 curleft = this._num(this.helper.css("left")); 42254 curtop = this._num(this.helper.css("top")); 42255 42256 if (o.containment) { 42257 curleft += $(o.containment).scrollLeft() || 0; 42258 curtop += $(o.containment).scrollTop() || 0; 42259 } 42260 42261 this.offset = this.helper.offset(); 42262 this.position = { left: curleft, top: curtop }; 42263 42264 this.size = this._helper ? { 42265 width: this.helper.width(), 42266 height: this.helper.height() 42267 } : { 42268 width: el.width(), 42269 height: el.height() 42270 }; 42271 42272 this.originalSize = this._helper ? { 42273 width: el.outerWidth(), 42274 height: el.outerHeight() 42275 } : { 42276 width: el.width(), 42277 height: el.height() 42278 }; 42279 42280 this.sizeDiff = { 42281 width: el.outerWidth() - el.width(), 42282 height: el.outerHeight() - el.height() 42283 }; 42284 42285 this.originalPosition = { left: curleft, top: curtop }; 42286 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 42287 42288 this.aspectRatio = (typeof o.aspectRatio === "number") ? 42289 o.aspectRatio : 42290 ((this.originalSize.width / this.originalSize.height) || 1); 42291 42292 cursor = $(".ui-resizable-" + this.axis).css("cursor"); 42293 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); 42294 42295 el.addClass("ui-resizable-resizing"); 42296 this._propagate("start", event); 42297 return true; 42298 }, 42299 42300 _mouseDrag: function(event) { 42301 42302 var data, props, 42303 smp = this.originalMousePosition, 42304 a = this.axis, 42305 dx = (event.pageX - smp.left) || 0, 42306 dy = (event.pageY - smp.top) || 0, 42307 trigger = this._change[a]; 42308 42309 this._updatePrevProperties(); 42310 42311 if (!trigger) { 42312 return false; 42313 } 42314 42315 data = trigger.apply(this, [ event, dx, dy ]); 42316 42317 this._updateVirtualBoundaries(event.shiftKey); 42318 if (this._aspectRatio || event.shiftKey) { 42319 data = this._updateRatio(data, event); 42320 } 42321 42322 data = this._respectSize(data, event); 42323 42324 this._updateCache(data); 42325 42326 this._propagate("resize", event); 42327 42328 props = this._applyChanges(); 42329 42330 if ( !this._helper && this._proportionallyResizeElements.length ) { 42331 this._proportionallyResize(); 42332 } 42333 42334 if ( !$.isEmptyObject( props ) ) { 42335 this._updatePrevProperties(); 42336 this._trigger( "resize", event, this.ui() ); 42337 this._applyChanges(); 42338 } 42339 42340 return false; 42341 }, 42342 42343 _mouseStop: function(event) { 42344 42345 this.resizing = false; 42346 var pr, ista, soffseth, soffsetw, s, left, top, 42347 o = this.options, that = this; 42348 42349 if (this._helper) { 42350 42351 pr = this._proportionallyResizeElements; 42352 ista = pr.length && (/textarea/i).test(pr[0].nodeName); 42353 soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height; 42354 soffsetw = ista ? 0 : that.sizeDiff.width; 42355 42356 s = { 42357 width: (that.helper.width() - soffsetw), 42358 height: (that.helper.height() - soffseth) 42359 }; 42360 left = (parseInt(that.element.css("left"), 10) + 42361 (that.position.left - that.originalPosition.left)) || null; 42362 top = (parseInt(that.element.css("top"), 10) + 42363 (that.position.top - that.originalPosition.top)) || null; 42364 42365 if (!o.animate) { 42366 this.element.css($.extend(s, { top: top, left: left })); 42367 } 42368 42369 that.helper.height(that.size.height); 42370 that.helper.width(that.size.width); 42371 42372 if (this._helper && !o.animate) { 42373 this._proportionallyResize(); 42374 } 42375 } 42376 42377 $("body").css("cursor", "auto"); 42378 42379 this.element.removeClass("ui-resizable-resizing"); 42380 42381 this._propagate("stop", event); 42382 42383 if (this._helper) { 42384 this.helper.remove(); 42385 } 42386 42387 return false; 42388 42389 }, 42390 42391 _updatePrevProperties: function() { 42392 this.prevPosition = { 42393 top: this.position.top, 42394 left: this.position.left 42395 }; 42396 this.prevSize = { 42397 width: this.size.width, 42398 height: this.size.height 42399 }; 42400 }, 42401 42402 _applyChanges: function() { 42403 var props = {}; 42404 42405 if ( this.position.top !== this.prevPosition.top ) { 42406 props.top = this.position.top + "px"; 42407 } 42408 if ( this.position.left !== this.prevPosition.left ) { 42409 props.left = this.position.left + "px"; 42410 } 42411 if ( this.size.width !== this.prevSize.width ) { 42412 props.width = this.size.width + "px"; 42413 } 42414 if ( this.size.height !== this.prevSize.height ) { 42415 props.height = this.size.height + "px"; 42416 } 42417 42418 this.helper.css( props ); 42419 42420 return props; 42421 }, 42422 42423 _updateVirtualBoundaries: function(forceAspectRatio) { 42424 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 42425 o = this.options; 42426 42427 b = { 42428 minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0, 42429 maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity, 42430 minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0, 42431 maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity 42432 }; 42433 42434 if (this._aspectRatio || forceAspectRatio) { 42435 pMinWidth = b.minHeight * this.aspectRatio; 42436 pMinHeight = b.minWidth / this.aspectRatio; 42437 pMaxWidth = b.maxHeight * this.aspectRatio; 42438 pMaxHeight = b.maxWidth / this.aspectRatio; 42439 42440 if (pMinWidth > b.minWidth) { 42441 b.minWidth = pMinWidth; 42442 } 42443 if (pMinHeight > b.minHeight) { 42444 b.minHeight = pMinHeight; 42445 } 42446 if (pMaxWidth < b.maxWidth) { 42447 b.maxWidth = pMaxWidth; 42448 } 42449 if (pMaxHeight < b.maxHeight) { 42450 b.maxHeight = pMaxHeight; 42451 } 42452 } 42453 this._vBoundaries = b; 42454 }, 42455 42456 _updateCache: function(data) { 42457 this.offset = this.helper.offset(); 42458 if (this._isNumber(data.left)) { 42459 this.position.left = data.left; 42460 } 42461 if (this._isNumber(data.top)) { 42462 this.position.top = data.top; 42463 } 42464 if (this._isNumber(data.height)) { 42465 this.size.height = data.height; 42466 } 42467 if (this._isNumber(data.width)) { 42468 this.size.width = data.width; 42469 } 42470 }, 42471 42472 _updateRatio: function( data ) { 42473 42474 var cpos = this.position, 42475 csize = this.size, 42476 a = this.axis; 42477 42478 if (this._isNumber(data.height)) { 42479 data.width = (data.height * this.aspectRatio); 42480 } else if (this._isNumber(data.width)) { 42481 data.height = (data.width / this.aspectRatio); 42482 } 42483 42484 if (a === "sw") { 42485 data.left = cpos.left + (csize.width - data.width); 42486 data.top = null; 42487 } 42488 if (a === "nw") { 42489 data.top = cpos.top + (csize.height - data.height); 42490 data.left = cpos.left + (csize.width - data.width); 42491 } 42492 42493 return data; 42494 }, 42495 42496 _respectSize: function( data ) { 42497 42498 var o = this._vBoundaries, 42499 a = this.axis, 42500 ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), 42501 ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 42502 isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width), 42503 isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height), 42504 dw = this.originalPosition.left + this.originalSize.width, 42505 dh = this.position.top + this.size.height, 42506 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 42507 if (isminw) { 42508 data.width = o.minWidth; 42509 } 42510 if (isminh) { 42511 data.height = o.minHeight; 42512 } 42513 if (ismaxw) { 42514 data.width = o.maxWidth; 42515 } 42516 if (ismaxh) { 42517 data.height = o.maxHeight; 42518 } 42519 42520 if (isminw && cw) { 42521 data.left = dw - o.minWidth; 42522 } 42523 if (ismaxw && cw) { 42524 data.left = dw - o.maxWidth; 42525 } 42526 if (isminh && ch) { 42527 data.top = dh - o.minHeight; 42528 } 42529 if (ismaxh && ch) { 42530 data.top = dh - o.maxHeight; 42531 } 42532 42533 // Fixing jump error on top/left - bug #2330 42534 if (!data.width && !data.height && !data.left && data.top) { 42535 data.top = null; 42536 } else if (!data.width && !data.height && !data.top && data.left) { 42537 data.left = null; 42538 } 42539 42540 return data; 42541 }, 42542 42543 _getPaddingPlusBorderDimensions: function( element ) { 42544 var i = 0, 42545 widths = [], 42546 borders = [ 42547 element.css( "borderTopWidth" ), 42548 element.css( "borderRightWidth" ), 42549 element.css( "borderBottomWidth" ), 42550 element.css( "borderLeftWidth" ) 42551 ], 42552 paddings = [ 42553 element.css( "paddingTop" ), 42554 element.css( "paddingRight" ), 42555 element.css( "paddingBottom" ), 42556 element.css( "paddingLeft" ) 42557 ]; 42558 42559 for ( ; i < 4; i++ ) { 42560 widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 ); 42561 widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 ); 42562 } 42563 42564 return { 42565 height: widths[ 0 ] + widths[ 2 ], 42566 width: widths[ 1 ] + widths[ 3 ] 42567 }; 42568 }, 42569 42570 _proportionallyResize: function() { 42571 42572 if (!this._proportionallyResizeElements.length) { 42573 return; 42574 } 42575 42576 var prel, 42577 i = 0, 42578 element = this.helper || this.element; 42579 42580 for ( ; i < this._proportionallyResizeElements.length; i++) { 42581 42582 prel = this._proportionallyResizeElements[i]; 42583 42584 // TODO: Seems like a bug to cache this.outerDimensions 42585 // considering that we are in a loop. 42586 if (!this.outerDimensions) { 42587 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); 42588 } 42589 42590 prel.css({ 42591 height: (element.height() - this.outerDimensions.height) || 0, 42592 width: (element.width() - this.outerDimensions.width) || 0 42593 }); 42594 42595 } 42596 42597 }, 42598 42599 _renderProxy: function() { 42600 42601 var el = this.element, o = this.options; 42602 this.elementOffset = el.offset(); 42603 42604 if (this._helper) { 42605 42606 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); 42607 42608 this.helper.addClass(this._helper).css({ 42609 width: this.element.outerWidth() - 1, 42610 height: this.element.outerHeight() - 1, 42611 position: "absolute",
vendor: 6,496 bytes, lines 42612-42845
42612 left: this.elementOffset.left + "px", 42613 top: this.elementOffset.top + "px", 42614 zIndex: ++o.zIndex //TODO: Don't modify option 42615 }); 42616 42617 this.helper 42618 .appendTo("body") 42619 .disableSelection(); 42620 42621 } else { 42622 this.helper = this.element; 42623 } 42624 42625 }, 42626 42627 _change: { 42628 e: function(event, dx) { 42629 return { width: this.originalSize.width + dx }; 42630 }, 42631 w: function(event, dx) { 42632 var cs = this.originalSize, sp = this.originalPosition; 42633 return { left: sp.left + dx, width: cs.width - dx }; 42634 }, 42635 n: function(event, dx, dy) { 42636 var cs = this.originalSize, sp = this.originalPosition; 42637 return { top: sp.top + dy, height: cs.height - dy }; 42638 }, 42639 s: function(event, dx, dy) { 42640 return { height: this.originalSize.height + dy }; 42641 }, 42642 se: function(event, dx, dy) { 42643 return $.extend(this._change.s.apply(this, arguments), 42644 this._change.e.apply(this, [ event, dx, dy ])); 42645 }, 42646 sw: function(event, dx, dy) { 42647 return $.extend(this._change.s.apply(this, arguments), 42648 this._change.w.apply(this, [ event, dx, dy ])); 42649 }, 42650 ne: function(event, dx, dy) { 42651 return $.extend(this._change.n.apply(this, arguments), 42652 this._change.e.apply(this, [ event, dx, dy ])); 42653 }, 42654 nw: function(event, dx, dy) { 42655 return $.extend(this._change.n.apply(this, arguments), 42656 this._change.w.apply(this, [ event, dx, dy ])); 42657 } 42658 }, 42659 42660 _propagate: function(n, event) { 42661 $.ui.plugin.call(this, n, [ event, this.ui() ]); 42662 (n !== "resize" && this._trigger(n, event, this.ui())); 42663 }, 42664 42665 plugins: {}, 42666 42667 ui: function() { 42668 return { 42669 originalElement: this.originalElement, 42670 element: this.element, 42671 helper: this.helper, 42672 position: this.position, 42673 size: this.size, 42674 originalSize: this.originalSize, 42675 originalPosition: this.originalPosition 42676 }; 42677 } 42678 42679}); 42680 42681/* 42682 * Resizable Extensions 42683 */ 42684 42685$.ui.plugin.add("resizable", "animate", { 42686 42687 stop: function( event ) { 42688 var that = $(this).resizable( "instance" ), 42689 o = that.options, 42690 pr = that._proportionallyResizeElements, 42691 ista = pr.length && (/textarea/i).test(pr[0].nodeName), 42692 soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height, 42693 soffsetw = ista ? 0 : that.sizeDiff.width, 42694 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, 42695 left = (parseInt(that.element.css("left"), 10) + 42696 (that.position.left - that.originalPosition.left)) || null, 42697 top = (parseInt(that.element.css("top"), 10) + 42698 (that.position.top - that.originalPosition.top)) || null; 42699 42700 that.element.animate( 42701 $.extend(style, top && left ? { top: top, left: left } : {}), { 42702 duration: o.animateDuration, 42703 easing: o.animateEasing, 42704 step: function() { 42705 42706 var data = { 42707 width: parseInt(that.element.css("width"), 10), 42708 height: parseInt(that.element.css("height"), 10), 42709 top: parseInt(that.element.css("top"), 10), 42710 left: parseInt(that.element.css("left"), 10) 42711 }; 42712 42713 if (pr && pr.length) { 42714 $(pr[0]).css({ width: data.width, height: data.height }); 42715 } 42716 42717 // propagating resize, and updating values for each animation step 42718 that._updateCache(data); 42719 that._propagate("resize", event); 42720 42721 } 42722 } 42723 ); 42724 } 42725 42726}); 42727 42728$.ui.plugin.add( "resizable", "containment", { 42729 42730 start: function() { 42731 var element, p, co, ch, cw, width, height, 42732 that = $( this ).resizable( "instance" ), 42733 o = that.options, 42734 el = that.element, 42735 oc = o.containment, 42736 ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; 42737 42738 if ( !ce ) { 42739 return; 42740 } 42741 42742 that.containerElement = $( ce ); 42743 42744 if ( /document/.test( oc ) || oc === document ) { 42745 that.containerOffset = { 42746 left: 0, 42747 top: 0 42748 }; 42749 that.containerPosition = { 42750 left: 0, 42751 top: 0 42752 }; 42753 42754 that.parentData = { 42755 element: $( document ), 42756 left: 0, 42757 top: 0, 42758 width: $( document ).width(), 42759 height: $( document ).height() || document.body.parentNode.scrollHeight 42760 }; 42761 } else { 42762 element = $( ce ); 42763 p = []; 42764 $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) { 42765 p[ i ] = that._num( element.css( "padding" + name ) ); 42766 }); 42767 42768 that.containerOffset = element.offset(); 42769 that.containerPosition = element.position(); 42770 that.containerSize = { 42771 height: ( element.innerHeight() - p[ 3 ] ), 42772 width: ( element.innerWidth() - p[ 1 ] ) 42773 }; 42774 42775 co = that.containerOffset; 42776 ch = that.containerSize.height; 42777 cw = that.containerSize.width; 42778 width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw ); 42779 height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ; 42780 42781 that.parentData = { 42782 element: ce, 42783 left: co.left, 42784 top: co.top, 42785 width: width, 42786 height: height 42787 }; 42788 } 42789 }, 42790 42791 resize: function( event ) { 42792 var woset, hoset, isParent, isOffsetRelative, 42793 that = $( this ).resizable( "instance" ), 42794 o = that.options, 42795 co = that.containerOffset, 42796 cp = that.position, 42797 pRatio = that._aspectRatio || event.shiftKey, 42798 cop = { 42799 top: 0, 42800 left: 0 42801 }, 42802 ce = that.containerElement, 42803 continueResize = true; 42804 42805 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { 42806 cop = co; 42807 } 42808 42809 if ( cp.left < ( that._helper ? co.left : 0 ) ) { 42810 that.size.width = that.size.width + 42811 ( that._helper ? 42812 ( that.position.left - co.left ) : 42813 ( that.position.left - cop.left ) ); 42814 42815 if ( pRatio ) { 42816 that.size.height = that.size.width / that.aspectRatio; 42817 continueResize = false; 42818 } 42819 that.position.left = o.helper ? co.left : 0; 42820 } 42821 42822 if ( cp.top < ( that._helper ? co.top : 0 ) ) { 42823 that.size.height = that.size.height + 42824 ( that._helper ? 42825 ( that.position.top - co.top ) : 42826 that.position.top ); 42827 42828 if ( pRatio ) { 42829 that.size.width = that.size.height * that.aspectRatio; 42830 continueResize = false; 42831 } 42832 that.position.top = that._helper ? co.top : 0; 42833 } 42834 42835 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); 42836 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); 42837 42838 if ( isParent && isOffsetRelative ) { 42839 that.offset.left = that.parentData.left + that.position.left; 42840 that.offset.top = that.parentData.top + that.position.top; 42841 } else { 42842 that.offset.left = that.element.offset().left; 42843 that.offset.top = that.element.offset().top; 42844 } 42845
42846 woset = Math.abs( that.sizeDiff.width + 42847 (that._helper ? 42848 that.offset.left - cop.left : 42849 (that.offset.left - co.left)) ); 42850 42851 hoset = Math.abs( that.sizeDiff.height + 42852 (that._helper ? 42853 that.offset.top - cop.top : 42854 (that.offset.top - co.top)) ); 42855 42856 if ( woset + that.size.width >= that.parentData.width ) { 42857 that.size.width = that.parentData.width - woset; 42858 if ( pRatio ) { 42859 that.size.height = that.size.width / that.aspectRatio; 42860 continueResize = false; 42861 } 42862 } 42863 42864 if ( hoset + that.size.height >= that.parentData.height ) { 42865 that.size.height = that.parentData.height - hoset; 42866 if ( pRatio ) { 42867 that.size.width = that.size.height * that.aspectRatio; 42868 continueResize = false; 42869 } 42870 } 42871 42872 if ( !continueResize ){ 42873 that.position.left = that.prevPosition.left; 42874 that.position.top = that.prevPosition.top; 42875 that.size.width = that.prevSize.width; 42876 that.size.height = that.prevSize.height; 42877 } 42878 }, 42879 42880 stop: function() { 42881 var that = $( this ).resizable( "instance" ), 42882 o = that.options, 42883 co = that.containerOffset, 42884 cop = that.containerPosition, 42885 ce = that.containerElement, 42886 helper = $( that.helper ), 42887 ho = helper.offset(), 42888 w = helper.outerWidth() - that.sizeDiff.width, 42889 h = helper.outerHeight() - that.sizeDiff.height; 42890 42891 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { 42892 $( this ).css({ 42893 left: ho.left - cop.left - co.left, 42894 width: w, 42895 height: h 42896 }); 42897 } 42898 42899 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { 42900 $( this ).css({ 42901 left: ho.left - cop.left - co.left, 42902 width: w, 42903 height: h 42904 }); 42905 } 42906 } 42907}); 42908 42909$.ui.plugin.add("resizable", "alsoResize", { 42910 42911 start: function() { 42912 var that = $(this).resizable( "instance" ), 42913 o = that.options, 42914 _store = function(exp) { 42915 $(exp).each(function() { 42916 var el = $(this); 42917 el.data("ui-resizable-alsoresize", { 42918 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 42919 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) 42920 }); 42921 }); 42922 }; 42923 42924 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { 42925 if (o.alsoResize.length) { 42926 o.alsoResize = o.alsoResize[0]; 42927 _store(o.alsoResize); 42928 } else { 42929 $.each(o.alsoResize, function(exp) { 42930 _store(exp); 42931 }); 42932 } 42933 } else { 42934 _store(o.alsoResize); 42935 } 42936 }, 42937 42938 resize: function(event, ui) { 42939 var that = $(this).resizable( "instance" ), 42940 o = that.options, 42941 os = that.originalSize, 42942 op = that.originalPosition, 42943 delta = { 42944 height: (that.size.height - os.height) || 0, 42945 width: (that.size.width - os.width) || 0, 42946 top: (that.position.top - op.top) || 0, 42947 left: (that.position.left - op.left) || 0 42948 }, 42949 42950 _alsoResize = function(exp, c) { 42951 $(exp).each(function() { 42952 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, 42953 css = c && c.length ? 42954 c : 42955 el.parents(ui.originalElement[0]).length ? 42956 [ "width", "height" ] : 42957 [ "width", "height", "top", "left" ]; 42958 42959 $.each(css, function(i, prop) { 42960 var sum = (start[prop] || 0) + (delta[prop] || 0); 42961 if (sum && sum >= 0) { 42962 style[prop] = sum || null; 42963 } 42964 }); 42965 42966 el.css(style); 42967 }); 42968 }; 42969 42970 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { 42971 $.each(o.alsoResize, function(exp, c) { 42972 _alsoResize(exp, c); 42973 }); 42974 } else { 42975 _alsoResize(o.alsoResize); 42976 } 42977 }, 42978 42979 stop: function() { 42980 $(this).removeData("resizable-alsoresize"); 42981 } 42982}); 42983 42984$.ui.plugin.add("resizable", "ghost", { 42985 42986 start: function() { 42987 42988 var that = $(this).resizable( "instance" ), o = that.options, cs = that.size; 42989 42990 that.ghost = that.originalElement.clone(); 42991 that.ghost 42992 .css({ 42993 opacity: 0.25, 42994 display: "block", 42995 position: "relative", 42996 height: cs.height, 42997 width: cs.width, 42998 margin: 0, 42999 left: 0, 43000 top: 0 43001 }) 43002 .addClass("ui-resizable-ghost") 43003 .addClass(typeof o.ghost === "string" ? o.ghost : ""); 43004 43005 that.ghost.appendTo(that.helper); 43006 43007 }, 43008 43009 resize: function() { 43010 var that = $(this).resizable( "instance" ); 43011 if (that.ghost) { 43012 that.ghost.css({ 43013 position: "relative", 43014 height: that.size.height,
43015 width: that.size.width 43016 }); 43017 } 43018 }, 43019 43020 stop: function() { 43021 var that = $(this).resizable( "instance" ); 43022 if (that.ghost && that.helper) { 43023 that.helper.get(0).removeChild(that.ghost.get(0)); 43024 } 43025 } 43026 43027}); 43028 43029$.ui.plugin.add("resizable", "grid", { 43030 43031 resize: function() { 43032 var outerDimensions, 43033 that = $(this).resizable( "instance" ), 43034 o = that.options, 43035 cs = that.size, 43036 os = that.originalSize, 43037 op = that.originalPosition, 43038 a = that.axis, 43039 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, 43040 gridX = (grid[0] || 1), 43041 gridY = (grid[1] || 1), 43042 ox = Math.round((cs.width - os.width) / gridX) * gridX, 43043 oy = Math.round((cs.height - os.height) / gridY) * gridY, 43044 newWidth = os.width + ox, 43045 newHeight = os.height + oy, 43046 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), 43047 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), 43048 isMinWidth = o.minWidth && (o.minWidth > newWidth), 43049 isMinHeight = o.minHeight && (o.minHeight > newHeight); 43050 43051 o.grid = grid; 43052 43053 if (isMinWidth) { 43054 newWidth += gridX; 43055 } 43056 if (isMinHeight) { 43057 newHeight += gridY; 43058 } 43059 if (isMaxWidth) { 43060 newWidth -= gridX; 43061 } 43062 if (isMaxHeight) { 43063 newHeight -= gridY; 43064 } 43065 43066 if (/^(se|s|e)$/.test(a)) { 43067 that.size.width = newWidth; 43068 that.size.height = newHeight; 43069 } else if (/^(ne)$/.test(a)) { 43070 that.size.width = newWidth; 43071 that.size.height = newHeight; 43072 that.position.top = op.top - oy; 43073 } else if (/^(sw)$/.test(a)) { 43074 that.size.width = newWidth; 43075 that.size.height = newHeight; 43076 that.position.left = op.left - ox; 43077 } else { 43078 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) { 43079 outerDimensions = that._getPaddingPlusBorderDimensions( this ); 43080 } 43081 43082 if ( newHeight - gridY > 0 ) { 43083 that.size.height = newHeight; 43084 that.position.top = op.top - oy; 43085 } else { 43086 newHeight = gridY - outerDimensions.height; 43087 that.size.height = newHeight; 43088 that.position.top = op.top + os.height - newHeight; 43089 } 43090 if ( newWidth - gridX > 0 ) { 43091 that.size.width = newWidth; 43092 that.position.left = op.left - ox; 43093 } else { 43094 newWidth = gridY - outerDimensions.height; 43095 that.size.width = newWidth; 43096 that.position.left = op.left + os.width - newWidth; 43097 } 43098 } 43099 } 43100 43101}); 43102 43103return $.ui.resizable; 43104 43105})); 43106 43107}, 43108'dpage/widgets/Page':function(){ 43109define([ 43110 "dojo/_base/declare" 43111 , "dojo/on" 43112 , "dojo/_base/event" 43113 , "dojo/json" 43114 43115 , "dpage/widgets/Container" 43116 , "dojox/widget/Standby" 43117], 43118 function (declare, on, event, json) { 43119 /** 43120 * @namespace dpage 43121 */ 43122 /** 43123 * @namespace widgets 43124 * @memberOf dpage 43125 */ 43126 /** 43127 * Every page in your application inherits from this module. Main DPage app container. Has other benifits such as catching the back-button keystroke event 43128 * which causes the browser to go back one page. Meant to augment the window.document. 43129 * This class is intended to be used as a Singleton. You will get an error if you try to instantiate more than one Page object per browser page. 43130 * @class Page 43131 * @param {Object} [options] Optional options for the widget. 43132 * @param {Object} [options.model] Data destined for Container child controls. 43133 * @param {bool} [options.modelTransform] Default false. If true, parse the model as if it contains meta-data. If false, don't bother parsing. Use it as-is. 43134 * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady. 43135 * @param {function} [options.widgetsParsedCallback] callback function for when widgets in this container are parsed. 43136 * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided 43137 * markup. As with all containers, the markup can contain widgets that can be accessed through 43138 * getWidget() or getWidgets(). 43139 * @param {dpage.widgets.Container} [options.container] The container of the widget. 43140 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 43141 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 43142 * is created. 43143 * @param {Object} [containerNode] Optional container node to tie the widget to. 43144 * @memberOf dpage.widgets 43145 * @extends {dpage.widgets.Container} 43146 */ 43147 var theClass = declare("dpage.widgets.Page", [dpage.widgets.Container], /** @lends dpage.widgets.Page.prototype */ { 43148 _overlay: null, 43149 43150 constructor: function (options, containerNode) { 43151 var self = this; 43152 43153 if (dpage.widgets.Page.getInstance() != null) 43154 throw new Error("A dpage.widgets.Page already exists. This class is intended to be used as a Singleton. You can obtain a reference to the existing class using the dpage.widgets.Page.getInstance() method."); 43155 43156 //store a reference to this object. 43157 dpage.widgets.Page._pageObj = this; 43158 43159 if (options != null) { 43160 43161 } 43162 43163 on(document.body, "keydown", function () { return self.docKeyDown(arguments); }); 43164 this._containerNode = document.body; 43165 }, 43166 _doNextCSSResource : function() 43167 { 43168 var self = this; 43169 var notReady = false; 43170 43171 for (var k in dpage.widgets.Page._cssLoading) 43172 { 43173 if(dpage.widgets.Page._cssLoading.hasOwnProperty(k)) 43174 { 43175 if (!dpage.widgets.Page._cssLoading[k]) { 43176 notReady = true; 43177 break; 43178 } 43179 } 43180 } 43181 43182 //wait until ready. 43183 if (notReady) { 43184 setTimeout(function () { self._doNextCSSResource(); }, 0); 43185 return; 43186 } 43187 43188 var nextResource = dpage.widgets.Page._postParseCSS.shift(); 43189 if(nextResource != null){ 43190 require(["xstyle/css!"+nextResource], function () { self._doNextCSSResource(); }); 43191 } 43192 }, 43193 widgetsParsed : function() 43194 { 43195 var self = this; 43196 setTimeout(function () { self._doNextCSSResource(); }, 0); 43197 43198 return this.inherited(arguments); 43199 }, 43200 templateString: "<div></div>", 43201 buildRendering: function () 43202 { 43203 return this.inherited(arguments); 43204 }, 43205 docKeyDown: function (e) { 43206 e = e[0];
43207 43208 if (e.keyCode == 8) { 43209 if (e.target == document.body) 43210 event.stop(e); 43211 } 43212 }, 43213 /** 43214 * Will disable the page so that a user cannot interact with it. 43215 * @returns {void} 43216 */ 43217 disablePage: function () { 43218 this.blockUI(true); 43219 }, 43220 /** 43221 * Enables the page so that the user can interact with it. 43222 * @returns {void} 43223 */ 43224 enablePage: function () { 43225 this.blockUI(false); 43226 } 43227 }); 43228 43229 theClass._postParseCSS = [], 43230 theClass._pageObj = null; 43231 43232 /** 43233 * Get the Page singleton obj. 43234 * @memberof dpage.widgets.Page 43235 * @name getInstance 43236 * @function 43237 * @returns {dpage.widgets.Page} 43238 */ 43239 theClass.getInstance = function () { 43240 return theClass._pageObj; 43241 }; 43242 43243 theClass._cssLoading = {}; 43244 43245 /** 43246 * A class (module) can call this method to inform the page that it has CSS resources pending. This is used by the Page class to control when to load the postParseCSS 43247 * if specified by a user calling the setPostParseCSS function. 43248 * @memberof dpage.widgets.Page 43249 * @name setClassCSSLoading 43250 * @function 43251 * @param {String} className The name of the class that has CSS pending or not. 43252 * @param {bool} doneLoading A caller will set this to true to indicate that all css for a class is done loading, false, when it begins to load a css resource, but it has 43253 * not come back yet. 43254 * @returns {dpage.widgets.Page} 43255 */ 43256 theClass.setClassCSSLoading = function (className, doneLoading) { 43257 theClass._cssLoading[className] = doneLoading; 43258 }; 43259 43260 /** 43261 * Set a list of css resources to bring in after the page is done parsing. Each string points to a CSS resource to bring in synchronously. 43262 * Use this option to control the style a bit more. Can be used to override default widget style with css that is auto-required in by them. 43263 * Any css resources specified are required in after the page is done instantiating declarative widgets. If the resources are not coming in, 43264 * see if you are overriding the widgetsParsed() method. If so, make sure that you are calling the base class method this.inherited(arguments) 43265 * which is where the resources are pulled in. 43266 * @memberof dpage.widgets.Page 43267 * @name setPostParseCSS 43268 * @function 43269 * @param {Array.String} resources List of css resource paths (can use package locations too). 43270 * @returns {void} 43271 */ 43272 theClass.setPostParseCSS = function (resources) { 43273 theClass._postParseCSS = resources; 43274 }; 43275 43276 return theClass; 43277 } 43278); 43279}, 43280'dpage/widgets/DomWrapper':function(){ 43281define([ 43282 "dojo/_base/event" 43283 , "dojo/on" 43284 , "dojo/dom-attr" 43285 , "dojo/dom-class" 43286 , "dojo/mouse" 43287 , "dojo/dom-geometry" 43288 , "dojo/dom-style" 43289 , "dojo/json" 43290 43291 , "dojo/request/xhr" 43292 , "dojox/html/entities" 43293 , "dojo/_base/declare" 43294 , "dpage/widgets/BaseWidget"], 43295function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 43296 /** 43297 * @namespace dpage 43298 */ 43299 /** 43300 * @namespace widgets 43301 * @memberOf dpage 43302 */ 43303 /** 43304 * Widget to serve as a wrapper around any dom node. This is so that we can provide access to the dom node without having to set an 43305 * id on the dom node. 43306 * @class DomWrapper 43307 * @param {Object} [options] Optional options for the widget. 43308 * @param {Function} options.onClick Click Handler for the dom node. 43309 * @param {dpage.widgets.Container} [options.container] The container of the widget. 43310 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 43311 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 43312 * is created. 43313 * @param {Object} [containerNode] Optional container node to tie the widget to. 43314 * @memberOf dpage.widgets 43315 * @extends {dpage.widgets.BaseWidget} 43316 */ 43317 return dojo.declare("dpage.widgets.DomWrapper", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.DomWrapper.prototype */ { 43318 _containerNode: null, 43319 constructor: function (options, srcNodeRef) { 43320 var self = this; 43321 this._containerNode = srcNodeRef; 43322 43323 if (options != null) { 43324 if (options.onClick != null) 43325 this.on("click", options.onClick); 43326 } 43327 43328 }, 43329 templateString: "<div></div>", 43330 buildRendering: function () { 43331 return this._containerNode; 43332 }, 43333 postCreate: function () { 43334 return this.inherited(arguments); 43335 }, 43336 /** 43337 * Set an event handler for the node. Events are dom and browser specific. 43338 * @param {String} eventName The symbolic name of the event. 43339 * @param {Function} functionRef the callback function to call. 43340 * @returns {void} 43341 */ 43342 on: function (eventName, functionRef) { 43343 on(this._containerNode, eventName, functionRef); 43344 }, 43345 /** 43346 * @returns {void} 43347 */ 43348 getDomNode: function () 43349 { 43350 return this._containerNode; 43351 } 43352 });
43353}); 43354 43355}, 43356'dpage/widgets/ExpandCollapse':function(){ 43357define([ 43358 "dojo/_base/event" 43359 , "dojo/on" 43360 , "dojo/dom-attr" 43361 , "dojo/dom-class" 43362 , "dojo/mouse" 43363 , "dojo/dom-geometry" 43364 , "dojo/dom-style" 43365 , "dojo/json" 43366 43367 , "dojo/request/xhr" 43368 , "dojox/html/entities" 43369 , "dojo/_base/declare" 43370 , "dpage/widgets/BaseWidget"], 43371function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 43372 /** 43373 * @namespace dpage 43374 */ 43375 /** 43376 * @namespace widgets 43377 * @memberOf dpage 43378 */ 43379 /** 43380 * A Widget to either show or hide content. Attach to a dom node and any children will be shown or hidden. 43381 * @class ExpandCollapse 43382 * @param {Object} [options] Optional options for the widget. 43383 * @param {dpage.widgets.Container} [options.container] The container of the widget. 43384 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 43385 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 43386 * is created. 43387 * @param {Object} [containerNode] Optional container node to tie the widget to. 43388 * @memberOf dpage.widgets 43389 * @extends {dpage.widgets.BaseWidget} 43390 */ 43391 return dojo.declare("dpage.widgets.ExpandCollapse", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.ExpandCollapse.prototype */ { 43392 _containerNode: null, 43393 _hideStyle: 'none', 43394 _showStyle: 'block', 43395 _hidden: true, 43396 constructor: function (options, srcNodeRef) { 43397 var self = this; 43398 this._containerNode = srcNodeRef; 43399 43400 if (style.get(this._containerNode, "display").toUpperCase() == "NONE") 43401 this._hidden = true; 43402 else 43403 this._hidden = false; 43404 43405 }, 43406 templateString: "<div></div>", 43407 buildRendering: function () { 43408 return this._containerNode; 43409 }, 43410 postCreate: function () { 43411 return this.inherited(arguments); 43412 }, 43413 /** 43414 * @returns {Object} The dom node reference this widget encapsulates. 43415 */ 43416 getDomNode: function () 43417 { 43418 return this._containerNode; 43419 }, 43420 /** 43421 * Either shows or hides the content. 43422 * @returns {void} 43423 */ 43424 toggle: function () 43425 { 43426 if (this._hidden) { 43427 this._hidden = false; 43428 style.set(this._containerNode, { display: this._showStyle }); 43429 } 43430 else { 43431 this._hidden = true; 43432 style.set(this._containerNode, { display: this._hideStyle }); 43433 } 43434 }, 43435 /** 43436 * Is the content shown or hidden 43437 * @returns {bool} 43438 */ 43439 isHidden: function () 43440 { 43441 return this._hidden; 43442 }, 43443 /** 43444 * Show the content 43445 * @returns {void} 43446 */ 43447 expand: function () 43448 { 43449 if (this._hidden) 43450 this.toggle(); 43451 }, 43452 /** 43453 * Hide the content 43454 * @returns {void} 43455 */ 43456 collapse: function () 43457 { 43458 if (!this._hidden) 43459 this.toggle(); 43460 } 43461 }); 43462}); 43463 43464}, 43465'dpage/widgets/InlineValidationMessage':function(){ 43466define([ 43467 "dojo/_base/event" 43468 ,"dojo/on" 43469 ,"dojo/dom-attr" 43470 ,"dojo/dom-class" 43471 ,"dojo/mouse" 43472 ,"dojo/dom-geometry" 43473 , "dojo/dom-style" 43474 , "dojo/json" 43475 43476 , "xstyle/css!dpage/widgets/InlineValidationMessage.css" 43477 , "dojo/request/xhr" 43478 ,"dojox/html/entities" 43479 ,"dojo/_base/declare" 43480 , "dpage/widgets/ValidationMessage"], 43481function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 43482 /** 43483 * @namespace dpage 43484 */ 43485 /** 43486 * @namespace widgets 43487 * @memberOf dpage 43488 */ 43489 /** 43490 * Implementation of a ValidationMessage that shows messages in-line with the content of the container. 43491 * @class InlineValidationMessage 43492 * @param {Object} [options] Optional options for the widget. 43493 * @param {String} [options.dataField] The field (column name) this widget is bound to. 43494 43495 * @param {dpage.modules.TabularModel} [options.model] The model to use. 43496 * @param {dpage.widgets.Container} [options.container] The container of the widget. 43497 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 43498 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 43499 * is created. 43500 * @param {Object} [containerNode] Optional container node to tie the widget to. 43501 * @memberOf dpage.widgets 43502 * @extends {dpage.widgets.ValidationMessage} 43503 */ 43504 return dojo.declare("dpage.widgets.InlineValidationMessage", [dpage.widgets.ValidationMessage], /** @lends dpage.widgets.InlineValidationMessage.prototype */ { 43505 _containerNode: null, 43506 _errors: null, 43507 constructor: function (options, srcNodeRef) 43508 { 43509 this._errors = []; 43510 var self = this; 43511 this._containerNode = srcNodeRef; 43512 }, 43513 _updateView : function() 43514 { 43515 //set up the data. 43516 this.inherited(arguments); 43517 43518 domClass.remove(this._containerNode, "validation-message"); 43519 this._containerNode.innerHTML = ""; 43520 43521 if (this._errors.length > 0) { 43522 domClass.add(this._containerNode, "validation-message"); 43523 ul = document.createElement("UL"); 43524 this._containerNode.appendChild(ul); 43525 } 43526 43527 for (var idx = 0; idx < this._errors.length ; idx++) { 43528 var obj = this._errors[idx]; 43529 43530 var li = document.createElement("LI"); 43531 43532 li.innerHTML = dojox.html.entities.encode(obj.message); 43533 43534 ul.appendChild(li); 43535 } 43536 } 43537 }); 43538}); 43539 43540}, 43541'dpage/widgets/Label':function(){ 43542define([ 43543 "dojo/_base/event" 43544 ,"dojo/on" 43545 ,"dojo/dom-attr" 43546 ,"dojo/dom-class" 43547 ,"dojo/mouse" 43548 ,"dojo/dom-geometry" 43549 , "dojo/dom-style" 43550 , "dojo/json" 43551 43552 , "dpage/modules/Date" 43553 , "dpage/modules/TabularModel" 43554 , "dojo/request/xhr"
43555 ,"dojox/html/entities" 43556 ,"dojo/_base/declare" 43557 , "dpage/widgets/SingleValueWidget"], 43558function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 43559 /** 43560 * @namespace dpage 43561 */ 43562 /** 43563 * @namespace widgets 43564 * @memberOf dpage 43565 */ 43566 /** 43567 * Class to encapulate blocks of text on a page. The label can be bound to data which is where it makes the most sense. 43568 * If the datatype of the model is DATE, the default date formatter is used to display it (dpage.modules.Date.formatDate()) 43569 * @class Label 43570 * @param {Object} [options] Optional options for the widget. 43571 * @param {bool} [options.noHTMLEncode] Dont' html encode the display data if set to true (not recommended). 43572 * @param {bool} [options.encodeSpace] Default false. If true AND noHTMLEncode==false, encode space characters as &nbsp; so that a user can see the whitespace. 43573 * @param {Function} [options.formatter] Function that will be used to format the data. The raw value is passed as a single param. Return the value 43574 * to display. 43575 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 43576 * @param {dpage.widgets.Container} [options.container] The container of the widget. 43577 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 43578 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 43579 * is created. 43580 * @param {Object} [containerNode] Optional container node to tie the widget to. 43581 * @memberOf dpage.widgets 43582 * @extends {dpage.widgets.SingleValueWidget} 43583 */ 43584 return dojo.declare("dpage.widgets.Label", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Label.prototype */ { 43585 _containerNode: null, 43586 _dataType: null, 43587 _formatter: null, 43588 _htmlEncode: true, 43589 _encodeSpace:false, 43590 43591 constructor: function (options, srcNodeRef) 43592 { 43593 var self = this; 43594 this._containerNode = srcNodeRef; 43595 43596 if (this._containerNode == null) { 43597 this._containerNode = document.createElement("SPAN"); 43598 } 43599 43600 if (this._containerNode.nodeName != "SPAN" && this._containerNode.nodeName != "DIV" && this._containerNode.nodeName != "LABEL") 43601 throw new Error("Source node for dpage.widgets.Label must be an SPAN or a DIV or a LABEL."); 43602 43603 if (options != null) 43604 { 43605 if (options.formatter != null) 43606 this._formatter = options.formatter; 43607 if (options.noHTMLEncode) 43608 this._htmlEncode = false; 43609 if (options.encodeSpace !== undefined) 43610 this._encodeSpace = options.encodeSpace; 43611 } 43612 }, 43613 /** HTML encode the model value or not. Default is to encode. Do not pass in a false value unless you know what you are doing. 43614 * @param {bool} trueOrFalse Encode or not. 43615 * @returns {void} 43616 */ 43617 setHTMLEncode : function(val){ 43618 this._htmlEncode = val; 43619 }, 43620 setModel : function(model) 43621 { 43622 this.inherited(arguments); 43623 43624 this._updateView(); 43625 }, 43626 _renderText : function(rawValue) 43627 { 43628 var dVal = this.renderText(rawValue); 43629 43630 if (dVal == null) 43631 dVal = ""; 43632 43633 if (this._htmlEncode) { 43634 dVal = dojox.html.entities.encode(dVal); 43635 43636 if (this._encodeSpace) { 43637 dVal = dVal.replace(/ /g, " "); 43638 } 43639 } 43640 43641 return dVal; 43642 }, 43643 /** Can be overridden by a subclass. formats the text that is displayed. 43644 * @param {String} rawValue the value to render. 43645 * @returns {String} value to display (will be html-encoded unless overridden) 43646 */ 43647 renderText : function(rawValue) 43648 { 43649 //if a formatter function is specified, use it to render the text. 43650 if (this._formatter != null) 43651 return this._formatter(rawValue); 43652 else if (this.getModel().getMetadata().DataType == "DATE") 43653 return dpage.modules.Date.formatDate(dpage.modules.Date.parseModelValue(rawValue)); 43654 else 43655 return rawValue; 43656 }, 43657 _updateView : function() 43658 { 43659 var vtd = this.getValue(); 43660 43661 if (vtd == null) 43662 vtd = ""; 43663 43664 this._containerNode.innerHTML = this._renderText(vtd.toString()); 43665 }, 43666 templateString: "<div></div>" 43667 }); 43668}); 43669 43670}, 43671'dpage/widgets/OKCancelDialog':function(){ 43672define([ 43673 "dojo/_base/declare" 43674 , "dojo/on" 43675 , "dojo/_base/event" 43676 , "jQueryPrivate"
43677 43678 , "dojox/html/entities" 43679 , "dpage/widgets/Dialog" 43680], 43681 function (declare, on, event, $) { 43682 /** 43683 * @namespace dpage 43684 */ 43685 /** 43686 * @namespace widgets 43687 * @memberOf dpage 43688 */ 43689 /** 43690 * An easy way of showing a simple dialog with an OK and Cancel button with some text. Text is html encoded so it is rendered as plain text. 43691 * @class OKCancelDialog 43692 * @param {Object} [options] Optional options for the widget 43693 * @param {String} [options.text] The text to display in the dialog. 43694 * @param {Function} [options.OKCallback] Callback for OK click. 43695 43696 * @param {String} [options.title] The title to display in the title bar of the dialog. 43697 * @param {bool} [options.noDefaultCSS] Default false. If true, no css will be required in for the widget. 43698 * @param {Number} [options.height] The height of the dialog. 43699 * @param {Number} [options.width] The width of the dialog. 43700 * @param {bool} [options.OKButton] Display an OK button or not that will close the dialog. Default is false for no button. 43701 * @param {Object} [options.model] Data destined for Container child controls. This is an object where each property value is a dpage.modules.TabularModel *or* 43702 * an object that conforms to the structure that can be used to pass to the dpage.modules.TabularModel constructor in the model property. 43703 * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady. 43704 * @param {function} [options.widgetsParsedCallback] callback function for when widgets in this container are parsed. 43705 * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided 43706 * markup. As with all containers, the markup can contain widgets that can be accessed through 43707 * getWidget() or getWidgets(). 43708 * @param {dpage.widgets.Container} [options.container] The container of the widget. 43709 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 43710 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 43711 * is created. 43712 * @param {Object} [containerNode] Optional container node to tie the widget to. 43713 * @memberOf dpage.widgets 43714 * @extends {dpage.widgets.Dialog} 43715 */ 43716 return declare("dpage.widgets.OKCancelDialog", [dpage.widgets.Dialog], /** @lends dpage.widgets.OKCancelDialog.prototype */ { 43717 _OKCallback : null 43718 , constructor: function (options) { 43719 var title = ""; 43720 if(options != null) 43721 { 43722 if (options.title != null) { 43723 title = dojox.html.entities.encode(options.title).replace("\"", """); 43724 } 43725 43726 if (options.text != null){ 43727 this.templateString="<DIV title=\"" + title + "\"><p style='text-align:center'>" + dojox.html.entities.encode(options.text.toString()) + "</p></DIV>"; 43728 } 43729 43730 if (options.OKCallback != null) 43731 this._OKCallback = options.OKCallback; 43732 } 43733 43734 } 43735 , templateString: "<div></div>" 43736 , buildRendering: function () { 43737 return this.inherited(arguments); 43738 } 43739 , postCreate : function() 43740 { 43741 var self = this; 43742 var options = { 43743 autoOpen: false, 43744 modal: true, 43745 buttons: { 43746 "OK": function () { self.close(); self.OKClicked(); } 43747 , "Cancel": function () { self.close(); } 43748 } 43749 }; 43750 43751 if (this._height) 43752 options.height = this._height; 43753 if (this._width) 43754 options.width = this._width; 43755 43756 this._dialog = $(this.domNode).dialog(options); 43757 } 43758 ,OKClicked : function() 43759 { 43760 if (this._OKCallback != null) 43761 this._OKCallback(); 43762 } 43763 }); 43764 } 43765); 43766}, 43767'dpage/widgets/Select':function(){ 43768define([ 43769 "dojo/_base/event" 43770 , "dojo/on" 43771 , "dojo/dom-attr" 43772 , "dojo/dom-class" 43773 , "dojo/mouse" 43774 , "dojo/dom-geometry" 43775 , "dojo/dom-style" 43776 , "dojo/json" 43777 43778 , "xstyle/css!dpage/widgets/Select.css" 43779 , "dpage/modules/LegacyPlaceholder" 43780 , "dpage/modules/TabularModel" 43781 , "dojo/request/xhr"
43782 , "dpage/modules/Encoding" 43783 , "dojo/_base/declare" 43784 , "dpage/widgets/SingleValueWidget"], 43785function (event, on, domAttr, domClass, mouse, domGeom, style, json ) { 43786 /** 43787 * @namespace dpage 43788 */ 43789 /** 43790 * @namespace widgets 43791 * @memberOf dpage 43792 */ 43793 /** 43794 * Widget to provide a drop down list control bound to data. 43795 * @class Select 43796 * @param {Object} [options] Optional options for the widget. 43797 * @param {dpage.modules.TabularModel} [options.optionsModel] Will create a list of <option>'s for the <select>. If passed, will overwrite the existing <options>. If not 43798 * passed, the existing <option>'s will be used. The options are <b>NOT</b> re-rendered based on model changes. In other words, 43799 * changes to the optionsModel will not be reflected in the select options. 43800 * @param {String} [options.optionsModelPropValue] Property to use for the value in the options. Valid only when using a options.optionsModel. <b>The property values in the model must be a unique list of values to work properly</b> 43801 * This is how the model data for the widget is linked to the optionsModel data for the options. 43802 * @param {String} [options.optionsModelPropText] Property to use for the display value in the options. Valid only when using a options.optionsModel 43803 * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input. This event will fires *after* the validation happens. You cannot cancel at this point. 43804 * The callback function definition is bool callback({event : eventObj , widget : widgetThatFiredEvent}) 43805 * @param {Function} [options.onPreChange] callback function for when widget value changes from user input. This event will fire before any validation. The widget (and backing model) will always contain the old value. You can return back a false value from your callback to cancel further processing of the event (including cancelling validation and value setting of the widget (and model)). 43806 * The callback function definition is bool callback({event : eventObj , widget : widgetThatFiredEvent , newValue : theNewValue}) 43807 * @param {String} [options.defaultValue] If provided, this will add an option to the top of the list of options with the supplied value. If defaultText is not provided, the display will 43808 * also show this value. 43809 * @param {String} [options.defaultText] Assumes defaultValue was also provided. If supplied, this will be the text of the default option. 43810 * @param {bool} [options.defaultSelectable] default true. Assumes defaultValue was provided. Controls whether the user can select the default option. 43811 43812 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 43813 * @param {dpage.widgets.Container} [options.container] The container of the widget. 43814 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 43815 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 43816 * is created. 43817 * @param {Object} [containerNode] Optional container node to tie the widget to. 43818 * @memberOf dpage.widgets 43819 * @extends {dpage.widgets.SingleValueWidget} 43820 */ 43821 var theClass = dojo.declare("dpage.widgets.Select", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Select.prototype */ { 43822 _containerNode: null, 43823 _optionsModel: null, 43824 _optionsModelPropValue: null, 43825 _optionsModelPropText: null, 43826 _onChange: null,//must be null here and set in the constructor otherwise it acts like a static var. 43827 _onPreChange: null, 43828 _addDefaultOption: false, 43829 _defaultValue: null, 43830 _defaultText: null, 43831 _defaultSelectable: true, 43832 43833 constructor: function (options, srcNodeRef) { 43834 var self = this; 43835 this._containerNode = srcNodeRef; 43836 43837 this._onChange = []; 43838 this._onPreChange = []; 43839 43840 if (this._containerNode == null) { 43841 this._containerNode = document.createElement("SELECT"); 43842 } 43843 43844 if (this._containerNode.nodeName != "SELECT") 43845 throw new Error("Source node for dpage.widgets.Select must be a SELECT."); 43846 43847 if (options != null) { 43848 if (options.optionsModel != null) { 43849 this._optionsModel = options.optionsModel; 43850 } 43851 if (options.optionsModelPropValue != null) 43852 this._optionsModelPropValue = options.optionsModelPropValue; 43853 if (options.optionsModelPropText != null) 43854 this._optionsModelPropText = options.optionsModelPropText; 43855 43856 if (options.onChange != null) { 43857 this._onChange.push(options.onChange); 43858 } 43859 43860 if (options.onPreChange != null) { 43861 this._onPreChange.push(options.onPreChange); 43862 } 43863 43864 if (options.defaultValue !== undefined){ 43865 this._defaultValue = options.defaultValue; 43866 this._addDefaultOption = true; 43867 } 43868 43869 if(options.defaultText !== undefined) 43870 { 43871 if (!this._addDefaultOption) 43872 throw new Error("WidgetId: " + this.getWidgetId() + ". To use the defaultText option you must pass the defaultValue option."); 43873 this._defaultText = options.defaultText; 43874 } 43875 else{ 43876 if(this._addDefaultOption) 43877 this._defaultText = this._defaultValue; 43878 } 43879 43880 if (options.defaultSelectable !== undefined) { 43881 if(!this._addDefaultOption) 43882 throw new Error("WidgetId: " + this.getWidgetId() + ". To use the defaultSelectable option you must pass the defaultValue option."); 43883 this._defaultSelectable = options.defaultSelectable; 43884 } 43885 } 43886 43887 if (this._optionsModel != null && this._optionsModelPropValue == null)
43888 throw new Error("Must pass in a optionsModelPropValue property to a dpage.widgets.Select.") 43889 43890 //set to the same as value if not passed in. 43891 if (this._optionsModelPropText == null) 43892 this._optionsModelPropText = this._optionsModelPropValue; 43893 43894 if (this._optionsModel != null) { 43895 if (this._optionsModel.isInstanceOf == null || !this._optionsModel.isInstanceOf(dpage.modules.TabularModel)) 43896 throw new Error("The optionsModel property must be of type dpage.modules.TabularModel"); 43897 } 43898 43899 on(this._containerNode, "blur", function (event) { self.select_OnBlur(event); }); 43900 on(this._containerNode, "focus", function (event) { self.select_OnFocus(event); }); 43901 on(this._containerNode, "change", function (event) { self.select_OnChange(event); }); 43902 on(this._containerNode, "keydown" , function (event) {return self.select_KeyDown(event);}); 43903 }, 43904 postCreate : function() 43905 { 43906 //BaseWidget calls _updateView() 43907 this.inherited(arguments); 43908 43909 //_updateView will not highlight the value if _optionsModel == null. 43910 if (this._optionsModel != null) 43911 { 43912 this._highlightValue(); 43913 } 43914 }, 43915 _highlightValue: function () { 43916 var modelVal; 43917 var foundVal = false; 43918 var newOption; 43919 var self = this; 43920 43921 modelVal = this.getValue(); 43922 43923 for (var x = 0; x < this._containerNode.options.length; x++) { 43924 if ( 43925 (modelVal != null && this._containerNode.options[x].value == modelVal 43926 && (modelVal != "" || this._containerNode.options[x].getAttribute('data-isnull') != 'true')) 43927 || 43928 (modelVal == null && this._containerNode.options[x].getAttribute('data-isnull') == 'true') 43929 ) { 43930 this._containerNode.selectedIndex = x; 43931 foundVal = true; 43932 } 43933 } 43934 43935 if (!foundVal) { 43936 var v = modelVal; 43937 43938 if (v == null) { 43939 newOption = new Option("", ""); 43940 newOption.setAttribute("data-isnull", "true"); 43941 } 43942 else 43943 newOption = new Option(v, v); 43944 43945 //on(newOption, "keydown", function (event) { return self.select_KeyDown(event); }); 43946 this._containerNode.options[this._containerNode.options.length] = newOption; 43947 this._containerNode.selectedIndex = this._containerNode.options.length - 1; 43948 } 43949 }, 43950 //Redraws the entire select, highlighting the current value. 43951 // Cross-browser way of redrawing the select FAST. 43952 _updateView : function() 43953 { 43954 var valFound; 43955 var self = this; 43956 var newOption; 43957 var optionArray = []; 43958 var val; 43959 var text; 43960 43961 //call the base class (BaseWidget). This clears the validation state common to all BaseWidget _updateView methods. 43962 this.inherited(arguments); 43963 43964 if (this._optionsModel == null) 43965 return; 43966 43967 //determine whether we have support for innerHTML to set options. If so, use it because it is a much faster 43968 // way of building the options. 43969 if (dpage.widgets.Select._innerHTMLWorks == null) 43970 { 43971 var select = document.createElement("SELECT"); 43972 select.innerHTML = "<option></option>"; 43973 if (select.options.length == 0) 43974 dpage.widgets.Select._innerHTMLWorks = false; 43975 else 43976 dpage.widgets.Select._innerHTMLWorks = true; 43977 } 43978 43979 if (dpage.widgets.Select._innerHTMLWorks) { 43980 43981 //add a default option if needed. 43982 if (this._addDefaultOption) { 43983 val = this._defaultValue; 43984 text = this._defaultText; 43985 43986 if (text == null) 43987 text = ""; 43988 43989 if (val == this.getValue()) { 43990 valFound = true; 43991 if (val == null) 43992 optionArray.push("<option value=\"\" " + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + " data-isnull='true' selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 43993 else 43994 optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\"" + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + " selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 43995 } 43996 else { 43997 if (val == null) 43998 optionArray.push("<option value=\"\"" + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + " data-isnull='true'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 43999 else 44000 optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\" " + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + ">" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 44001 } 44002 } 44003 44004 for (var x = 0; x < this._optionsModel.getRows().length ; x++) { 44005 val = this._optionsModel.getValue(x, this._optionsModelPropValue); 44006 text = this._optionsModel.getValue(x, this._optionsModelPropText); 44007 44008 if (text == null) 44009 text = ""; 44010 44011 if (val == this.getValue()) { 44012 valFound = true; 44013 if (val == null) 44014 optionArray.push("<option value=\"\" data-isnull='true' selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 44015 else 44016 optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\" selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 44017 } 44018 else { 44019 if (val == null) 44020 optionArray.push("<option value=\"\" data-isnull='true'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 44021 else 44022 optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\">" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>"); 44023 } 44024 } 44025 44026 this._containerNode.innerHTML = optionArray.join(""); 44027 } 44028 else 44029 { 44030 //add in the default option if we have one. 44031 if (this._addDefaultOption) { 44032 val = this._defaultValue; 44033 text = this._defaultText; 44034 var o; 44035 44036 if (text == null) 44037 text = ""; 44038 44039 if (val == this.getValue()) { 44040 valFound = true; 44041 if (val == null) { 44042 o = new Option(text, "", true, true); 44043 o.setAttribute('data-isnull', 'true'); 44044 } 44045 else { 44046 o = new Option(text, val, true, true); 44047 } 44048 } 44049 else { 44050 if (val == null) { 44051 o = new Option(text, val); 44052 o.setAttribute('data-isnull', 'true'); 44053 } 44054 else{ 44055 o =new Option(text, val); 44056 } 44057 } 44058 44059 this._containerNode.options[this._containerNode.options.length] = o; 44060 if (this._addDefaultOption && this._defaultSelectable == false) { 44061 o.setAttribute("disabled", true); 44062 o.setAttribute("hidden", true); 44063 } 44064 44065 } 44066 44067 //pretty much a custom solution for IE9. 44068 this._containerNode.options.length = 0; 44069 for (var x = 0; x < this._optionsModel.getRows().length ; x++) { 44070 var val = this._optionsModel.getValue(x, this._optionsModelPropValue); 44071 var text = this._optionsModel.getValue(x, this._optionsModelPropText); 44072 44073 if (text == null) 44074 text = ""; 44075 44076 if (val == this.getValue()) { 44077 valFound = true; 44078 if (val == null) { 44079 var o = new Option(text, "", true, true); 44080 o.setAttribute('data-isnull', 'true'); 44081 this._containerNode.options[this._containerNode.options.length] = o; 44082 } 44083 else 44084 this._containerNode.options[this._containerNode.options.length] = new Option(text, val, true, true); 44085 } 44086 else { 44087 if (val == null) { 44088 var o = new Option(text, val); 44089 o.setAttribute('data-isnull', 'true'); 44090 this._containerNode.options[this._containerNode.options.length] = o; 44091 } 44092 else 44093 this._containerNode.options[this._containerNode.options.length] = new Option(text, val); 44094 } 44095 } 44096 } 44097 44098 if (!valFound) { 44099 var v = this.getValue(); 44100 44101 if (v == null) { 44102 newOption = new Option("", ""); 44103 newOption.setAttribute("data-isnull", "true"); 44104 } 44105 else 44106 newOption = new Option(v, v); 44107 44108 //on(newOption, "keydown", function (event) { return self.select_KeyDown(event); }); 44109 this._containerNode.options[this._containerNode.options.length] = newOption; 44110 this._containerNode.selectedIndex = this._containerNode.options.length - 1; 44111 } 44112 }, 44113 /** 44114 * Set a TabularModel that contains all of the options for the MultiSelect. Will erase existing options and replace them with the ones in the optionsModel. 44115 * If a value in the model is not contained in the optionsModel, a option is added to the select but not to the optionsModel. The optionsModel is read-only. 44116 * @param {dpage.modules.TabularModel} model 44117 * @param {String} propValue The property name in the TabularModel to use for the value 44118 * @param {String} propText The property name in the TabularModel to use for the text (display) 44119 * @returns {void} 44120 */ 44121 setOptionsModel: function (model, propValue, propText) { 44122 this._optionsModel = model; 44123 44124 //TODO: Need to hook up to the optionsModel change events to redraw the select when rows added/removed/changed. 44125 44126 if (propValue != null) 44127 this._optionsModelPropValue = propValue; 44128 if (propText != null) 44129 this._optionsModelPropText = propText; 44130 44131 this._updateView(); 44132 }, 44133 //set a tabular model. 44134 setModel: function (model) { 44135 44136 this.inherited(arguments); 44137 44138 this._highlightValue(); 44139 }, 44140 select_OnFocus: function () { 44141 44142 }, 44143 select_OnBlur: function () { 44144 }, 44145 select_KeyDown: function (e) { 44146 //This event does not fire for some odd reason in Chrome, but works in IE and firefox. Only seems to affect a single select not the multi-select. 44147 if (e.keyCode == 8) { 44148 event.stop(e); 44149 } 44150 }, 44151 /** 44152 * Get the current selected value from the control. This method differs from getValue(). getValue() returns the model value. This method returns the selected value which 44153 * won't correspond to the model value if the selected value is not a valid value for the model property. For instance, the field may be required and the user may have 44154 * selected the null value. In this case, calling this method will return null, whereas calling getValue() will return you the last valid value. 44155 * @returns {Object} 44156 */ 44157 getSelectedValue : function() { 44158 return this.getDomNode().value; 44159 }, 44160 /** 44161 * Focus the control 44162 * @returns {void} 44163 */ 44164 focus: function () { 44165 this.getDomNode().focus(); 44166 }, 44167 select_OnChange: function (evt) { 44168 var self = this; 44169 var selectVal; 44170 44171 selectVal = this.getDomNode().value; 44172 44173 //check for a null value. 44174 if (selectVal == "" 44175 && 44176 this.getDomNode().options[this.getDomNode().selectedIndex].getAttribute('data-isnull') == 'true') { 44177 selectVal = null; 44178 } 44179 44180 //call callbacks in order. 44181 for (var i = 0; i < this._onPreChange.length; i++) { 44182 if (this._onPreChange[i]({ event: evt, widget: self, newValue: selectVal}) == false) { 44183 //prevent further action. 44184 evt.preventDefault(); 44185 //select the current (old) value. 44186 this._highlightValue(); 44187 return false; 44188 } 44189 } 44190 44191 if (this.validate() == null) { 44192 if (this.getContainer()) { 44193 if (this.getContainer().getValidationMessageWidget()) { 44194 this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId()); 44195 } 44196 } 44197 44198 this.setModelValue(selectVal); 44199 } 44200 44201 //call callbacks in order. 44202 for (var i = 0; i < this._onChange.length; i++) 44203 this._onChange[i]({ event: evt, widget: self }); 44204 }, 44205 //Override the default action to re-draw the entire widget. 44206 _modelChanged: function () { 44207 this._highlightValue(); 44208 }, 44209 templateString: "<div></div>", 44210 /** 44211 * Set an event handler. Refer to the constructor options for more information on event types. 44212 * @param {String} eventName The event to bind to. Only supported events are "change" and "prechange". 44213 * @param {function} functionRef The callback function to call. 44214 * @returns {void} 44215 */ 44216 on: function (eventName, functionRef) { 44217 var self = this; 44218 44219 if (eventName == "change") 44220 this._onChange.push(functionRef); 44221 else if (eventName == "prechange") 44222 this._onPreChange.push(functionRef); 44223 else 44224 throw new Error("Supported events are: 'change'."); 44225 }, 44226 validate: function () { 44227 var value = this._containerNode.value; 44228 var ret; 44229 44230 ret = dpage.widgets.BaseWidget.validate(value, this.getModel().getMetadata(), this.getModel().getDisplayName()); 44231 44232 this.setValidationMessage(ret); 44233 44234 return ret; 44235 }, 44236 setValidationMessage: function (message) { 44237 this.inherited(arguments); 44238 44239 domClass.remove(this._containerNode, "dpage-widgets-Select-input-invalid"); 44240 44241 if (message != null) 44242 domClass.add(this._cont
44242ainerNode, "dpage-widgets-Select-input-invalid"); 44243 } 44244 44245 }); 44246 44247 theClass._innerHTMLWorks = null; 44248 44249 return theClass; 44250}); 44251 44252}, 44253'dpage/modules/Encoding':function(){ 44254define(["dojo/_base/declare", 44255 44256 "dojox/html/entities" 44257], 44258 function (declare) { 44259 /** 44260 * @namespace dpage 44261 */ 44262 /** 44263 * @namespace modules 44264 * @memberOf dpage 44265 */ 44266 /** 44267 * Provides common encoding routines. 44268 * @class Encoding 44269 * @memberOf dpage.modules 44270 */ 44271 var theClass = declare("dpage.modules.Encoding", [], /** @lends dpage.modules.Encoding.prototype */ { 44272 44273 constructor: function (options) { 44274 var self = this; 44275 } 44276 }); 44277 44278 /** Encodes a string encoded for use in an html document, including inside html attributes. 44279 * @memberof dpage.modules.Encoding 44280 * @name htmlEncode 44281 * @function 44282 * @param {String} strIn The string to encode. 44283 * @returns {String} 44284 */ 44285 theClass.htmlEncode = function (strIn) { 44286 return dojox.html.entities.encode(strIn).replace(/'/g , "'").replace(/"/g , """); 44287 }; 44288 44289 return theClass; 44290 } 44291); 44292}, 44293'dpage/widgets/MultiSelect':function(){ 44294define([ 44295 "dojo/_base/event" 44296 , "dojo/on" 44297 , "dojo/dom-attr" 44298 , "dojo/dom-class" 44299 , "dojo/mouse" 44300 , "dojo/dom-geometry" 44301 , "dojo/dom-style" 44302 , "dojo/json" 44303 44304 , "xstyle/css!dpage/widgets/TextBox.css" 44305 , "dpage/modules/LegacyPlaceholder" 44306 , "dpage/modules/TabularModel" 44307 , "dojo/request/xhr" 44308 , "dojox/html/entities" 44309 , "dojo/_base/declare" 44310 , "dpage/widgets/MultiValueWidget"], 44311function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 44312 /** 44313 * @namespace dpage 44314 */ 44315 /** 44316 * @namespace widgets 44317 * @memberOf dpage 44318 */ 44319 /** 44320 * Widget to provide a multi-select list control bound to data. 44321 * @class MultiSelect 44322 * @param {Object} [options] Optional options for the widget. 44323 * @param {String} [options.dataField] The field (column name) this widget is bound to. 44324 * @param {dpage.modules.TabularModel} [options.optionsModel] Will create a list of <option>'s for the <select>. If passed, will overwrite the existing <options>. If not 44325 * passed, the existing <option>'s will be used. 44326 * @param {String} [options.optionsModelPropValue] Property to use for the value in the options. Valid only when using a options.optionsModel 44327 * @param {String} [options.optionsModelPropText] Property to use for the display value in the options. Valid only when using a options.optionsModel 44328 * @param {dpage.modules.TabularModel} [options.model] The model to use. 44329 * @param {dpage.widgets.Container} [options.container] The container of the widget. 44330 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 44331 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 44332 * is created. 44333 * @param {Object} [containerNode] Optional container node to tie the widget to. 44334 * @memberOf dpage.widgets 44335 * @extends {dpage.widgets.MultiValueWidget} 44336 */ 44337 return dojo.declare("dpage.widgets.MultiSelect", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.MultiSelect.prototype */ { 44338 _containerNode: null, 44339 _optionsModel: null, 44340 _optionsModelPropValue: null, 44341 _optionsModelPropText: null, 44342 _dataField: null, 44343 constructor: function (options, srcNodeRef) { 44344 var self = this; 44345 this._containerNode = srcNodeRef; 44346 44347 if (this._containerNode == null) { 44348 this._containerNode = document.createElement("SELECT"); 44349 this._containerNode.setAttribute("multiple" , "multiple"); 44350 } 44351 44352 if (this._containerNode.nodeName != "SELECT" || this._containerNode.getAttribute("multiple") == null || this._containerNode.getAttribute("multiple").toUpperCase() != "MULTIPLE") 44353 throw new Error("Source node for dpage.widgets.Select must be a SELECT multiple='multiple'"); 44354 44355 if (options != null) { 44356 if (options.placeholder != null) { 44357 this._placeholder = options.placeholder; 44358 } 44359 if (options.optionsModel != null) { 44360 if (options.optionsModel.isInstanceOf == null || !options.optionsModel.isInstanceOf(dpage.modules.TabularModel)) 44361 throw new Error("optionsModel must be an instance of dpage.modules.TabularModel."); 44362 this._optionsModel = options.optionsModel; 44363 } 44364 if (options.optionsModelPropValue != null) 44365 this._optionsModelPropValue = options.optionsModelPropValue; 44366 if (options.optionsModelPropText != null) 44367 this._optionsModelPropText = options.optionsModelPropText; 44368 if (options.dataField == null){ 44369 if (options.model == null) 44370 this._dataField = this.getModel().getColumns()[0].ColumnName; 44371 else
44372 throw new Error("Must pass the dataField property to dpage.widgets.MultiSelect. "); 44373 } 44374 else 44375 this._dataField = options.dataField; 44376 } 44377 44378 if (this._optionsModel != null && this._optionsModelPropValue == null) 44379 throw new Error("Must pass in a optionsModelPropValue property to a dpage.widgets.Select") 44380 44381 //set to the same as value if not passed in. 44382 if (this._optionsModelPropText == null) 44383 this._optionsModelPropText = this._optionsModelPropValue; 44384 44385 on(this._containerNode, "blur", function () { self.select_OnBlur(event); }); 44386 on(this._containerNode, "focus", function () { self.select_OnFocus(event); }); 44387 on(this._containerNode, "change", function () { self.select_OnChange(event); }); 44388 }, 44389 postCreate: function () { 44390 44391 this._updateView(); 44392 }, 44393 44394 _highlightValues: function () { 44395 var valLookup = {}; 44396 44397 //used for fast lookup for selection. 44398 for (var i = 0; i < this.getModel().getRows().length; i++) { 44399 valLookup[this.getModel().getValue(i, this._dataField)] = 1;//1 means we need to select an option. 2 means we have selected the option. 44400 } 44401 44402 for (var x = 0; x < this._containerNode.options.length; x++) { 44403 if (valLookup[this._containerNode.options[x].value]) { 44404 this._containerNode.options[x].selected = true; 44405 valLookup[this._containerNode.options[x].value] = 2; 44406 } 44407 else 44408 this._containerNode.options[x].selected = false; 44409 } 44410 44411 //add rows from the model that are not contained in the options model. 44412 for (var i = 0; i < this.getModel().getRows().length; i++) { 44413 if (valLookup[this.getModel().getValue(i, this._dataField)] != 2) { 44414 this._containerNode.options[this._containerNode.options.length] = new Option(this.getModel().getValue(i, this._dataField), this.getModel().getValue(i, this._dataField), false, true); 44415 } 44416 } 44417 }, 44418 44419 _updateView : function(){ 44420 var valLookup = {}; 44421 44422 if (this._optionsModel == null) 44423 return; 44424 44425 this._containerNode.innerHTML = ""; 44426 44427 //used for fast lookup for selection. 44428 for (var i = 0; i < this.getModel().getRows().length; i++) { 44429 valLookup[this.getModel().getValue(i, this._dataField)] = 1;//1 means we need to select an option. 2 means we have selected the option. 44430 } 44431 44432 if (this._optionsModel != null) { 44433 for (var x = 0; x < this._optionsModel.getRows().length ; x++) { 44434 var val = this._optionsModel.getValue(x, this._optionsModelPropValue); 44435 var text = this._optionsModel.getValue(x, this._optionsModelPropText); 44436 var node = document.createElement("OPTION"); 44437 var isSelected = false; 44438 44439 if (valLookup[val]) { 44440 isSelected = true; 44441 valLookup[val] = 2; //1 means we need to select an option. 2 means we have selected the option. 44442 } 44443 else 44444 isSelected = false; 44445 44446 this._containerNode.options[this._containerNode.length] = new Option(text, val, false, isSelected); 44447 } 44448 } 44449 44450 //add rows from the model that are not contained in the options model. 44451 for (var i = 0; i < this.getModel().getRows().length; i++) { 44452 if (valLookup[this.getModel().getValue(i, this._dataField)] != 2) { 44453 this._containerNode.options[this._containerNode.options.length] = new Option(this.getModel().getValue(i, this._dataField), this.getModel().getValue(i, this._dataField), false, true); 44454 } 44455 } 44456 }, 44457 44458 /** 44459 * Set a TabularModel that contains all of the options for the MultiSelect. Will erase existing options and replace them with the ones in the optionsModel. 44460 * If a value in the model is not contained in the optionsModel, a option is added to the select but not to the optionsModel. The optionsModel is read-only. 44461 * @param {dpage.modules.TabularModel} model 44462 * @param [String] propValue The property name in the TabularModel to use for the value 44463 * @param [String] propText The property name in the TabularModel to use for the text (display) 44464 * @returns {void} 44465 */ 44466 setOptionsModel : function(model , propValue, propText) 44467 { 44468 this._optionsModel = model; 44469 44470 if (model.isInstanceOf == null || !model.isInstanceOf(dpage.modules.TabularModel)) 44471 throw new Error("optionsModel must be a dpage.modules.TabularModel."); 44472 44473 if(propValue != null) 44474 this._optionsModelPropValue = propValue; 44475 44476 if(propText != null) 44477 this._optionsModelPropText = propText; 44478 44479 this._updateView(); 44480 }, 44481 /** 44482 * Sets a tabular model and optional dataField to bind the data values to. 44483 * @param {dpage.modules.TabularModel} model 44484 * @param [String] dataField If not passed in, defaults to the same as when constructed. 44485 * @returns {void} 44486 */ 44487 setModel: function (model, dataField) { 44488 44489 this.inherited(arguments); 44490 44491 if (dataField != null) 44492 this._dataField = dataField; 44493 44494 this._highlightValues();
44495 }, 44496 select_OnFocus: function () { 44497 44498 }, 44499 select_OnBlur: function () { 44500 }, 44501 /** 44502 * Focus the control 44503 * @returns {void} 44504 */ 44505 focus: function () { 44506 this.getDomNode().focus(); 44507 }, 44508 select_OnChange: function () { 44509 var valLookup = {}; 44510 var oldS = this.isSubscribedToModelChanges(); 44511 44512 this.setDataSubscriptions(false); 44513 44514 //used for fast lookup for selection. 44515 for (var i = 0; i < this.getModel().getRows().length; i++) { 44516 valLookup[this.getModel().getValue(i, this._dataField)] = 1;//1 means the value exists. 2 means we should NOT delete the value. 44517 } 44518 44519 for (var i = 0; i < this._containerNode.options.length; i++) 44520 { 44521 if(this._containerNode.options[i].selected) 44522 { 44523 if(!valLookup[this._containerNode.options[i].value]) 44524 { 44525 var row = {}; 44526 row[this._dataField] = this._containerNode.options[i].value; 44527 this.getModel().addRow(row); 44528 } 44529 valLookup[this._containerNode.options[i].value] = 2; 44530 } 44531 } 44532 44533 for (var i = this.getModel().getRows().length-1; i >=0; i--) { 44534 if (valLookup[this.getModel().getValue(i , this._dataField)] != 2) { 44535 this.getModel().deleteRow(i); 44536 } 44537 } 44538 44539 this.setDataSubscriptions(true); 44540 }, 44541 //overridden 44542 _modelChanged: function (changeType, rowObj, propName) { 44543 this._highlightValues(); 44544 }, 44545 validate: function () { 44546 44547 } 44548 }); 44549}); 44550 44551}, 44552'dpage/widgets/Submit':function(){ 44553define([ 44554 "dojo/_base/event" 44555 ,"dojo/on" 44556 ,"dojo/dom-attr" 44557 ,"dojo/dom-class" 44558 ,"dojo/mouse" 44559 ,"dojo/dom-geometry" 44560 , "dojo/dom-style" 44561 , "dojo/json" 44562 , "dojo/request" 44563 , "dojo/dom-form" 44564 44565 , "dpage/widgets/BaseWidget" 44566 , "dpage/widgets/Page" 44567 , "dpage/widgets/Button" 44568 ,"dojox/html/entities" 44569 ,"dojo/_base/declare" 44570 , "dpage/widgets/BaseWidget"], 44571function (event, on, domAttr, domClass, mouse, domGeom, style, json, request, domForm) { 44572 /** 44573 * @namespace dpage 44574 */ 44575 /** 44576 * @namespace widgets 44577 * @memberOf dpage 44578 */ 44579 /** 44580 * This widget is the basis for how a DPage application communcates with the server and coordinates the validation of 44581 * all of the Container's widgets. When a "submit" is triggered, this widget coordinates all of the validation. If successfull, 44582 * then submits the current model to the server automatically. If a value attribute is defined on the domNode of the Submit, the 44583 * model value of the Submit widget is bound to will be set to this value. 44584 * @class Submit 44585 * @param {Object} [options] Optional options for the widget. 44586 * @param {bool} [options.noValidate] Default false. Flag used to instruct the submit to either call val
44586idate or not. If true, data will be submitted 44587 * regardless of whether data in controls is valid (validation will not be attempted). Default behavior (false) is to call the 44588 * containers validateWidgets() method. 44589 * @param {String} [options.method] Default "POST". Supported values are "GET" or "POST". Usually "POST" is what you want. GET has request limits that are pretty low. 44590 * @param {bool} [options.doAsynchronous] Default false. Perform the callback either synchronous or asynchronous. Synchronous will submit the Container model to the server and refresh the entire page. 44591 * Asynchronous will submit the Container model to the server. Default behavior is to refresh the Container model with the new model from the server. 44592 * Page location will not change. If you pass in a asynchronousPostCallback the default behavior is overridden. 44593 * @param {Function} [options.asynchronousPostCallback] Callback to be called when the server method responds. Works with both GET and POST request methods. function(successOrError , serverResponse){} 44594 * @param {Number} [options.asynchronousTimeout] Default 120 seconds. Timeout in seconds. 44595 * @param {bool} [options.asyncModelTransform] Default true. Applies when using an asynchronousPostCallback method. If set to true, the Submit widget will transform the raw model from the 44596 * server and pass it into your callback function as the second parameter. If set to false, The raw server response will be passed 44597 * as the second parameter to your callback function. If you are not sure what to use here, use the default of true. 44598 * @param {bool} [options.doModelRefresh] Default true. Should the container model be refreshed automatically with the response data. Performs the following code: 44599 * <pre>this.getContainer().refreshModel(json.parse(serverResponse)); </pre> This only applies in the case 44600 * of an asynchronous call. Does not apply if a asynchronousPostCallback function is specified. 44601 * For this to work properly, the model must be serialized on the server and returned as a raw JSON response. 44602 * @param {String} [options.url] Server endpoint to send data to. 44603 * @param {bool} [options.disablePage] Default true. Flag used to instruct the widget to disable the page when the button is clicked. 44604 * @param {bool} [options.disableContainer] Default false. Disable the container while the submit is in progress. 44605 * @param {bool} [options.enableClickToSubmit] Default true. If false, clicking on the button will not cause a submit. Usefull, if you are hooking 44606 * up a click handler and you want to control the submit yourself. 44607 44608 * @param {Function} [options.onClick] callback for click. 44609 * @param {String} [options.text] The button text. 44610 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 44611 * @param {dpage.widgets.Container} [options.container] The container of the widget. 44612 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 44613 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 44614 * is created. 44615 * @param {Object} [containerNode] Optional container node to tie the widget to. 44616 * @memberOf dpage.widgets 44617 * @extends {dpage.widgets.Button} 44618 */ 44619 var theClass = dojo.declare("dpage.widgets.Submit", [dpage.widgets.Button], /** @lends dpage.widgets.Submit.prototype */ { 44620 _doAsynchronous: false, 44621 _method: 'POST', 44622 _asynchronousCallback: null, 44623 _url: null, 44624 _onSubmit: null, 44625 _noValidate: false, 44626 //this is so that you can set a value attribute like this <button value='....' .../> 44627 _nativeValue: null, 44628 _nativeValuePresent: false, 44629 _disablePage: true, 44630 _disableContainer: false, 44631 _enableClickToSubmit: true, 44632 _doModelRefresh: true, 44633 _asynchronousTimeout: 120, 44634 _asyncModelTransform: true, 44635 _tryRawXHRAndBlob : true, 44636 44637 constructor: function (options, srcNodeRef) 44638 { 44639 var self = this; 44640 44641 //The base class button will ensure that this._containerNode is set 44642 if (this._containerNode.nodeName == "INPUT" && domAttr.get(this._containerNode, "type").toUpperCase() == "SUBMIT") { 44643 on(this._containerNode, "click", function (event) { self._button_OnClick(); dojo.stopEvent(event); return false; }); 44644 } 44645 else if (this._containerNode.nodeName == "BUTTON") { 44646 on(this._containerNode, "click", function (event) { self._button_OnClick(); dojo.stopEvent(event); return false; }); 44647 } 44648 else if (this._containerNode.nodeName == "A") { 44649 on(this._containerNode, "click", function (event) { self._button_OnClick(); dojo.stopEvent(event); return false; }); 44650 } 44651 else 44652 throw new Error("Source node for widgets.Submit must be an INPUT[type=button], a BUTTON, or an A"); 44653 44654 if (this._containerNode.hasAttribute("value")) 44655 { 44656 this._nativeValue = domAttr.get(this._containerNode, "value"); 44657 this._nativeValuePresent = true; 44658 } 44659 44660 if (options == null || options.url == null) 44661 { 44662 throw new Error("A Submit widget needs the url property to function. Pass the url option in."); 44663 } 44664 44665 if(options != null) 44666 { 44667 if (options.disablePage != undefined && options.disablePage == false) 44668 this._disablePage = false; 44669 44670 if (options.disableContainer) 44671 this._disableContainer = true; 44672 44673 if (options.noValidate != null) 44674 this._noValidate = options.noValidate; 44675 44676 if (options.method != null) 44677 this._method = options.method; 44678 44679 if (options.asynchronousTimeout != null) 44680 this._asynchronousTimeout = options.asynchronousTimeout; 44681 44682 if (options.enableClickToSubmit != undefined && options.enableClickToSubmit == false) 44683 this._enableClickToSubmit = false; 44684 44685 if (options.asyncModelTransform != undefined && options.asyncModelTransform == false) 44686 this._asyncModelTransform = false; 44687 44688 if (options.doAsynchronous != null) 44689 { 44690 this._doAsynchronous = options.doAsynchronous; 44691 44692 this._asynchronousCallback = options.asynchronousPost
44692Callback; 44693 44694 if (options.doModelRefresh != undefined) 44695 this._doModelRefresh = options.doModelRefresh; 44696 } 44697 44698 if (options.url != null) 44699 this._url = options.url; 44700 44701 if (options.onSubmit != null) 44702 this._onSubmit = options.onSubmit; 44703 } 44704 }, 44705 templateString: "<div></div>", 44706 _button_OnClick: function () 44707 { 44708 if (this._enableClickToSubmit) 44709 this.submit(); 44710 }, 44711 validateContainerWidgets: function () 44712 { 44713 var pageObj = dpage.widgets.Page.getInstance(); 44714 44715 if (this._noValidate) { 44716 this._doSubmit(); 44717 } 44718 else { 44719 var valid = this.getContainer().validateWidgets(); 44720 if (!valid) { 44721 44722 if(pageObj != null && this._disablePage) 44723 pageObj.enablePage(); 44724 44725 if (this.getContainer() != null && this._disableContainer) 44726 this.getContainer().blockUI(false); 44727 44728 } 44729 else { 44730 this._doSubmit(); 44731 } 44732 } 44733 }, 44734 _defaultAsyncCallback : function(status , data) 44735 { 44736 if (dpage.widgets.Page.getInstance() != null && this._disablePage) 44737 dpage.widgets.Page.getInstance().enablePage(); 44738 44739 if (this.getContainer() != null && this._disableContainer) 44740 this.getContainer().blockUI(false); 44741 44742 try{ 44743 44744 if(this._asynchronousCallback != null) 44745 { 44746 //transform the data for the callback. 44747 if (this._asyncModelTransform) 44748 data = dpage.widgets.Container.parseServerModel(data); 44749 44750 this._asynchronousCallback(status , data); 44751 return; 44752 } 44753 44754 //otherwise. 44755 if (status == "SUCCESS") 44756 { 44757 if(this._doModelRefresh) 44758 { 44759 var model = json.parse(data); 44760 this.getContainer().refreshModel(model , true); 44761 } 44762 } 44763 else 44764 throw(new Error(data)); 44765 } 44766 catch(e) 44767 { 44768 var c = this.getContainer(); 44769 var vw; 44770 if(c != null ) 44771 { 44772 vw = c.getValidationMessageWidget(); 44773 } 44774 if (vw != null) 44775 vw.setError([{ message: e.message }]); 44776 else 44777 throw e; 44778 } 44779 44780 }, 44781 /*Asynchronous call using the XMLHttpRequest object.*/ 44782 _doXHRSubmitNoBlob: function (strModel) { 44783 var url = this._url; 44784 var self = this; 44785 44786 if (this._method == "GET") { 44787 44788 if (!/\?/.test(url)) 44789 url += "?"; 44790 44791 url += "model=" + encodeURIComponent(strModel); 44792 44793 request.get(url, { 44794 timeout: this._asynchronousTimeout * 1000 44795 }).then(function (res) { 44796 self._defaultAsyncCallback("SUCCESS", res); 44797 }, function (res) { 44798 self._defaultAsyncCallback("ERROR", res); 44799 }); 44800 } 44801 else if (this._method == "POST") { 44802 var theForm = document.createElement("FORM"); 44803 var theInput = document.createElement("INPUT"); 44804 domAttr.set(theInput, "type", "hidden"); 44805 domAttr.set(theInput, "name", "model"); 44806 domAttr.set(theInput, "value", strModel); 44807 44808 theForm.appendChild(theInput); 44809 44810 domAttr.set(theForm, "action", this._url); 44811 domAttr.set(theForm, "method", "POST"); 44812 44813 44814 request.post(this._url, { 44815 data: domForm.toObject(theForm), 44816 timeout: this._asynchronousTimeout * 1000 44817 }).then(function (res) { 44818 self.getContainer().result = res; 44819 dpage.widgets.Page.getInstance().enablePage(); 44820 //self._defaultAsyncCallback("SUCCESS", res); 44821 }, function (res) { 44822 self._defaultAsyncCallback("ERROR", res); 44823 }); 44824 } 44825 }, 44826 44827 _doXHRSubmit : function (strModel){ 44828 var req = this._createXMLHTTPObject(); 44829 var url = this._url; 44830 var method = this._method; 44831 var self = this; 44832 var postData = null; 44833 44834 if (!req) 44835 throw new Error("Unable to instantiate XMLHttpRequest."); 44836 44837 if (this._method == "GET") { 44838 if (!/\?/.test(url)) 44839 url += "?"; 44840 44841 url += "model=" + encodeURIComponent(strModel); 44842 } 44843 44844 req.open(method, url, true); 44845 44846 //timeout has to be *after* the open call in IE. 44847 req.timeout = this._asynchronousTimeout * 1000; 44848 44849 req.responseType = 'text'; 44850 44851 //common response handling. 44852 req.onreadystatechange = function () { 44853 44854 if (req.readyState != 4) 44855 return; 44856 if (req.status != 200 && req.status != 304) { 44857 var msg = "RequestError: Unable to load " + url + " status: " + req.status; 44858 self._defaultAsyncCallback("ERROR", msg); 44859 return; 44860 } 44861 44862 self._defaultAsyncCallback("SUCCESS", req.responseText); 44863 }; 44864 44865 if (this._method == "POST") { 44866 req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 44867 44868 var data = encodeURIComponent(strModel); 44869 44870 postData = "model=" + data; 44871 } 44872 44873 if (postData == null) 44874 req.send(); 44875 else 44876 req.send(postData); 44877 }, 44878 _getXmlHttpFactories : function(){ 44879 return [ 44880 function () {return new XMLHttpRequest()}, 44881 function () {return new ActiveXObject("Msxml2.XMLHTTP")}, 44882 function () {return new ActiveXObject("Msxml3.XMLHTTP")}, 44883 function () {return new ActiveXObject("Microsoft.XMLHTTP")} 44884 ]; 44885 }, 44886 44887 _createXMLHTTPObject : function() { 44888 var xmlhttp = false; 44889 var XMLHttpFactories = this._getXmlHttpFactories(); 44890 44891 for (var i=0;i<XMLHttpFactories.length;i++) { 44892 try { 44893 xmlhttp = XMLHttpFactories[i](); 44894 } 44895 catch (e) { 44896 continue; 44897 } 44898 break; 44899 } 44900 return xmlhttp; 44901 }, 44902 _doSubmit: function () 44903 { 44904 var self = this; 44905 var url = this._url; 44906 44907 //if you include a value attribute in the dom node, it will get bound to the model here... 44908 // Ex: <button value='hello!' data-dojo-type='dpage/widgets/Submit' data-dojo-props:'container: this , model : this.getModel.Files , dataField : "Prop1"' /> 44909 if (this._nativeValuePresent) 44910 this.setModelValue(this._nativeValue); 44911 44912 //get the page model. 44913 var strModel = this.getContainer().serializeModel(); 44914 44915 if (this._method != "POST" && this._method != "GET") 44916 throw new Error("Invalid _method of: " + this._method); 44917 44918 if (this._doAsynchronous) { 44919 44920 if (this._tryRawXHRAndBlob) 44921 this._doXHRSubmit(strModel); 44922 else 44923 this._doXHRSubmitNoBlob(strModel); 44924 } 44925 else { 44926 //post the page 44927 var theForm = document.createElement("FORM"); 44928 var theInput = document.createElement("INPUT"); 44929 domAttr.set(theInput, "type", "hidden"); 44930 domAttr.set(theInput, "name", "model"); 44931 domAttr.set(theInput, "value", strModel); 44932 44933 theForm.appendChild(theInput); 44934 44935 domAttr.set(theForm, "action", this._url); 44936 domAttr.set(theForm, "method", this._method); 44937 44938 document.body.appendChild(theForm); 44939 44940 theForm.submit(); 44941 } 44942 }, 44943 /** 44944 * Perform the submit action. The Container model (getModel()) is sent to the server seri
44944alized in the model parameter value. In other words, 44945 * to access the serialized model on the server, access the model parameter that was passed in. 44946 * @returns {void} 44947 */ 44948 submit : function () 44949 { 44950 var wid = this.getWidgetId(); 44951 var self = this; 44952 var pageObj = dpage.widgets.Page.getInstance(); 44953 44954 if (this.getContainer() == null) { 44955 throw new Error("A Submit widget needs a container property to function. Pass the container option in."); 44956 } 44957 44958 if (pageObj != null && this._disablePage) 44959 pageObj.disablePage(); 44960 44961 44962 if (this.getContainer() != null && this._disableContainer) 44963 this.getContainer().blockUI(true); 44964 44965 if (this._url == null) 44966 throw new Error("This widgets.Submit widget (id=" + wid + ") has a null url"); 44967 44968 //so page will be blocked immediately. 44969 setTimeout(function () { self.validateContainerWidgets(); }, 0); 44970 44971 } 44972 }); 44973 44974 return theClass; 44975}); 44976 44977}, 44978'dpage/widgets/Table':function(){ 44979define([ 44980 "dojo/_base/event" 44981 , "dojo/on" 44982 , "dojo/dom-attr" 44983 , "dojo/dom-class" 44984 , "dojo/mouse" 44985 , "dojo/dom-geometry" 44986 , "dojo/dom-style" 44987 , "dojo/json" 44988 , "dojo/query" 44989 , "jQueryPrivate" 44990 44991 , "dpage/modules/TabularToSingleValueModel" 44992 , "dpage/modules/Config" 44993 , "xstyle/css!dpage/widgets/Table.css" 44994 , "dpage/modules/TabularModel" 44995 , "dojox/html/entities" 44996 , "dojo/_base/declare" 44997 , "dpage/widgets/MultiValueWidget"], 44998function (event, on, domAttr, domClass, mouse, domGeom, style, json, query, $) { 44999 /** 45000 * @namespace dpage 45001 */ 45002 /** 45003 * @namespace widgets 45004 * @memberOf dpage 45005 */ 45006 /** 45007 * A usefull data-bound responsive-design enabled table. 45008 * @class Table 45009 * @param {Object} [options] Optional options for the widget. 45010 * @param {bool} [options.noDefaultCSS] If true, don't bring an any default styling. 45011 * @param {bool} [options.useExistingTable] If true, bind the model to the existing table markup. The number of rows in the table, 45012 * must match number of rows in the model. Default is false. If set to false, any existing 45013 * table will be overwritten with a table generated from the data in the model. 45014 * @param {bool} [options.paginate] Defaults false. If true, paging will be added. 45015 * @param {bool} [options.pageLinksOnBottom] Default true. Paging links will be added to the bottom of the table. Need to also set options.paginate to true. 45016 * @param {bool} [options.pageLinksOnTop] Default false. Paging links will be added to the bottom of the table. Need to also set options.paginate to true. 45017 * @param {Number} [options.pageSize] Default 10. The number of rows to display per page. If passed, implies options.paginate. 45018 * @param {Number} [options.maxPageLinks] Default 20. The maximum number of paging links to show at the bottom of the table. 45019 * @param {Number} [options.phoneBreakpoint] Default 480. The pixel width where the table will turn to phone mode. 45020 * @param {Number} [options.tabletBreakpoint] Default 800. The pixel width where the table will turn to tablet mode. 45021 * @param {bool} [options.sortableColumns] Default true. If true, then the columns will be marked sortable. Can be overridden on a column basis with the sortable column option. 45022 * @param {Object} [options.caption] String|{@link dpage.widgets.Label}. A string or {@link dpage.widgets.Label} to set as the caption for the table. Write a caption node directly underneath the table node. 45023 * Following dpage conventions, if a string is passed in, the value will be property html encoded, so markup will show as text. 45024 * @param {Object} [options.colOptions] Column options. 45025 * @param {Object} [options.colOptions.colName] The name of the column in the model to set options for. 45026 * @param {dpage.widgets.SingleValueWidget} [options.colOptions.colName.widgetConstructor] Any SingleValueWidget. This widget will be bound to the data for the cell. 45027 * The table will set the model for this widget so that it is bound to the value of the cell. 45028 * The table does this by adding in the model option for the widget like this: 45029 * <pre> 45030 *new widgetConstructor({model : new TabularToSingleValueModel({ 45031 * tabularModel:this.getModel() , 45032 * dataField : currentColName , 45033 * dataRow: currentDataRow})}) 45034 * </pre> 45035 * @param {Object} [options.colOptions.colName.widgetOptions] The options that will be passed to the constructor of the widgetConstructor class. Use this to control custom cell widgets. 45036 * There is no need to pass the model option. The table will override whatever you pass in 45037 * since it has to bind the SingleValueWidget to the particular row and column. 45038 * @param {dpage.widgets.TableColumnNameWidget} [options.colOptions.colName.columnNameWidget] Widget to use for displaying the contents of the column header. 45039 * You can subclass the {@link dpage.widgets.TableColumnNameWidget} to provide custom formatting. The table will 45040 * provide the tableObj and modelFieldName options to the constructor of this widget. The getDomNode() method of this widget 45041 * must be a TH. 45042 * @param {Object} [options.colOptions.colName.columnNameWidgetOptions] Optional extra options for the columnNameWidget. Will be passed to the constructor of the 45043 * columnNameWidget if provided. 45044 * @param {bool} [options.colOptions.colName.dataHidePhone] Hide this column when sized to phone width 45045 * @param {bool} [options.colOptions.colName.dataHideTablet] Hide this column when sized to tablet 45046 * @param {String} [options.colOptions.colName.displayName] Name to display in header. The text is HTML encoded unless you override with encodeDisplayName : false 45047 * @param {bool} [options.colOptions.colName.encodeDisplayName] Default true. If false, it will not HTML encode the display name. Only applies if passing in the displayName column option. 45048 * @param {bool} [options.colOptions.colName.hideColumn] When set to true, hide the column completely. 45049 * @param {bool} [options.colOptions.colName.hideColumnInDownload] When set to true, hide the column when downloading the table data (the downloadData() method). When set to false, show the column in the download. 45050 * @param {String} [options.colOptions.colName.altSortColumn] If set, names the column in the TabularModel whose row value will control the sorting for this column. 45051 * @param {bool} [options.colOptions.colName.sortable] Default true. If true, the column will be marked sortable. Overrides the global sortableColumns o
45051ption if explicitly set. 45052 45053 * @param {dpage.modules.TabularModel} [options.model] The model to use. 45054 * @param {dpage.widgets.Container} [options.container] The container of the widget. 45055 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 45056 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 45057 * is created. 45058 * @param {Object} [containerNode] Optional container node to tie the widget to. 45059 * @memberOf dpage.widgets 45060 * @extends {dpage.widgets.MultiValueWidget} 45061 */ 45062 return dojo.declare("dpage.widgets.Table", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.Table.prototype */ { 45063 _colConstructors: null, 45064 _containerNode: null, 45065 _useExistingTable: false, 45066 _colOptions: null, 45067 _widgetList: null, 45068 _widgetLookup : null, 45069 _columnWidgets : null, 45070 _modelColNames: null, 45071 _paginate: false, 45072 _pageSize: 10, 45073 _currentPage : 1, 45074 _maxPageLinks : 20, 45075 _phoneBreakpoint: 480, 45076 _tabletBreakpoint: 800, 45077 _renderCNameAr: null, 45078 _sortableColumns: true, 45079 _captionObj: null, 45080 _initialized : false, 45081 _tFootTDNode: null, 45082 _pageLinksOnBottom: true, 45083 _pageLinksOnTop : false, 45084 45085 constructor: function (options, srcNodeRef) { 45086 var self = this; 45087 var modelColumns = null; 45088 var oneColDataType; 45089 45090 this._modelColNames = {}; 45091 this._widgetList = []; 45092 this._widgetLookup = {}; 45093 this._columnWidgets = []; 45094 this._colOptions = {}; 45095 this._colConstructors = {}; 45096 this._columnsToHideOnPhone = {}; 45097 this._columnsToHideOnTablet = {}; 45098 45099 if(srcNodeRef == null) 45100 srcNodeRef = document.createElement("TABLE"); 45101 45102 if (srcNodeRef.nodeName != "TABLE") 45103 throw new Error("Source node for widgets.Table must be a TABLE"); 45104 45105 this._containerNode = srcNodeRef; 45106 45107 if (options == null || !options.noDefaultCSS) { 45108 //register with the page obj that we have pending css. 45109 dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Table", false); 45110 //use this pattern whenever we need one css to load before another one. 45111 require(["xstyle/css!footable/footable.core.css"], function () { 45112 require(["xstyle/css!footable/footable.standalone.css"], function () { 45113 //register with the page that we are done loading css. 45114 dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Table", true); 45115 }); 45116 }); 45117 } 45118 45119 modelColumns = this.getModel().getColumns(); 45120 45121 if (options != null) { 45122 45123 if (options.sortableColumns != undefined) 45124 this._sortableColumns = options.sortableColumns; 45125 45126 if (options.caption != null) { 45127 if ((options.caption instanceof String || typeof (options.caption) == 'string') 45128 || 45129 (options.caption.isInstanceOf && options.caption.isInstanceOf(dpage.widgets.Label))) 45130 this._captionObj = options.caption; 45131 else 45132 throw new Error("caption table option must be a string or a dpage.widgets.Label object."); 45133 } 45134 45135 if (options.useExistingTable) 45136 this._useExistingTable = true; 45137 45138 if (options.paginate) 45139 this._paginate = true; 45140 45141 if (options.pageLinksOnTop !== undefined) 45142 this._pageLinksOnTop = options.pageLinksOnTop; 45143 45144 if (options.pageLinksOnBottom !== undefined) 45145 this._pageLinksOnBottom = options.pageLinksOnBottom; 45146 45147 if (options.maxPageLinks) 45148 this._maxPageLinks = options.maxPageLinks; 45149 45150 if (options.pageSize) 45151 this._pageSize = options.pageSize; 45152 45153 if (options.phoneBreakpoint) 45154 this._phoneBreakpoint = options.phoneBreakpoint; 45155
45156 if (options.tabletBreakpoint) 45157 this._tabletBreakpoint = options.tabletBreakpoint; 45158 45159 if (options.colOptions != null) { 45160 for (var idx = 0; idx < modelColumns.length; idx++) { 45161 this._modelColNames[modelColumns[idx].ColumnName] = true; 45162 } 45163 for (var idx = 0; idx < modelColumns.length; idx++) { 45164 if (options.colOptions[modelColumns[idx].ColumnName] != null) { 45165 var opt = options.colOptions[modelColumns[idx].ColumnName]; 45166 // widgetConstructor : null (can be any SingleValueWidget) 45167 // widgetOptions : null (the options object passed to the widgetConstructor. 45168 // dataHidePhone : null 45169 // dataHideTablet : null 45170 // displayName : null 45171 // hideColumn : true|false|null 45172 // hideColumnInDownload : true|false|null 45173 // altSortColumn : String 45174 if (opt.hasOwnProperty("widgetConstructor") && opt.widgetConstructor == null) 45175 throw new Error("there is a problem with the definition for the widgetConstructor for column " + modelColumns[idx].ColumnName + " on this Table (wid=" + this.getWidgetId() + "). You must require the widget in.") 45176 if (opt.hasOwnProperty("altSortColumn")) { 45177 if ((oneColDataType = this.getModel().getColumnInfo(opt.altSortColumn)) == null) 45178 throw new Error("Invalid altSortColumn name of: " + opt.altSortColumn + ". It does not exist in the model."); 45179 else { 45180 //for faster reference later when building the table. 45181 opt.altColDataType = oneColDataType.DataType; 45182 } 45183 } 45184 this._colOptions[modelColumns[idx].ColumnName] = opt; 45185 } 45186 else 45187 1 == 1;//this._colOptions[modelColumns[idx].ColumnName] = {}; 45188 } 45189 45190 //check for invalid properties. 45191 for (var colName in options.colOptions) { 45192 if (options.colOptions.hasOwnProperty(colName)) { 45193 if (!this._modelColNames[colName]) 45194 throw new Error("Invalid colOptions model column name of : " + colName); 45195 } 45196 } 45197 } 45198 } 45199 }, 45200 /** 45201 * Get the SingleValueWidget for the specified table cell. The row is the row index (for row object see overloaded method) in the model for the table. 45202 * null is returned if the column does not have a cell widget or if the specified cell widget is not on the current page or if an invalid fieldName is 45203 * passed in. 45204 * @param {Number} row The index of the row in the table model. 45205 * @param {String} fieldName The field name in the model that identifies the column. 45206 * @returns {dpage.widgets.SingleValueWidget} 45207 *//** 45208 * Get the SingleValueWidget for the specified table cell. The row is the row object (for row index see overloaded method) in the model for the table. 45209 * null is returned if the column does not have a cell widget or if the specified cell widget is not on the current page or if an invalid fieldName is 45210 * passed in. 45211 * @param {Object} row The row object in the table model. 45212 * @param {String} fieldName The field name in the model that identifies the column. 45213 * @returns {dpage.widgets.SingleValueWidget} 45214 */ 45215 getCellWidget: function (row , fieldName) { 45216 var rowObj; 45217 45218 if (typeof (row) === 'number' || row instanceof Number) 45219 rowObj = this._model.getRows()[row]; 45220 else 45221 rowObj = row; 45222 45223 var w = this._widgetLookup[this.getModel().getDataRowId(rowObj)]; 45224 45225 if (w == null) 45226 return null; 45227 45228 w = w[fieldName]; 45229 45230 if(w== null) 45231 return null; 45232 else 45233 return w; 45234 }, 45235 cleanupColumnNameWidgets : function(){ 45236 for (var i = 0; i < this._columnWidgets.length; i++) { 45237 this._columnWidgets[i].destroy();//so we get garbage collected correctly. 45238 } 45239 this._columnWidgets = []; 45240 }, 45241 cleanupEditWidgets : function(){ 45242 for (var i = 0; i < this._widgetList.length; i++) { 45243 this._widgetList[i].destroy();//so we get garbage collected correctly. 45244 } 45245 this._widgetList = []; 45246 this._widgetLookup = {}; 45247 }, 45248 destroy : function () { 45249 this.cleanupEditWidgets(); 45250 this.cleanupColumnNameWidgets(); 45251 this.inherited(arguments); 45252 }, 45253 templateString: "<div></div>", 45254 postCreate: function () { 45255 var columns = this.getModel().getColumns(); 45256 var column; 45257 var dataType; 45258 45259 if (this._dataField != null) { 45260 for (var idx = 0; idx < columns.length; idx++) { 45261 if (columns[idx].ColumnName == this._dataField) { 45262 column = columns[idx]; 45263 } 45264 } 45265 45266 if (column == null) 45267 throw new Error("Field " + this._dataField + " does not exist in the model."); 45268 45269 this._dataType = column.DataType; 45270 } 45271 45272 this.bindTable(); 45273 }, 45274 /** 45275 * Get the list of columnNameWidgets (only applies if any custom ones were passed into the constructor). Do not modify this array! 45276 * @returns {dpage.widgets.TableColumnNameWidget[]} 45277 */ 45278 getColumnNameWidgets : function(){ 45279 return this._columnWidgets; 45280 }, 45281 /** 45282 * Downloads data as csv. 45283 * @param {String} fileName The name of the file that will be returned. 45284 * @param {Array} [columnOptions] Optional column options. If passed in, they give you more control on how to format the output. The order 45285 * of the columnOptions array determines the order in which the output file columns are written. 45286 * @param {String} columnOptions.ColumnName The column name in the model. 45287 * @param {String} [columnOptions.DisplayName] The value to display as the column header. 45288 * @param {bool} [columnOptions.HideColumn] Default false. Do not show this column if set to true. 45289 * @returns {void} 45290 */ 45291 downloadData : function(fileName , columnOptions) 45292 { 45293 var url = dpage.modules.Config.dpageRoot + "/Download.ashx"; 45294 var self = this; 45295 var form = document.createElement("FORM"); 45296 var input = document.createElement("TEXTAREA");//can hold more data than input type=text. For some reason chrome was truncating the value on an <input type=text> to about 500kb. 45297 var fileNameInput = document.createElement("INPUT"); 45298 var tableModel = {}; 45299 45300 tableModel.Rows = this.getModel().getRawModel(); 45301 45302 if(columnOptions == null) 45303 { 45304 columnOptions = []; 45305 for(var i=0;i<this.getModel().getColumns().length;i++) 45306 { 45307 var options = {}; 45308 45309 //DisplayName 45310 if (this.getModel().getColumns()[i].DisplayName != null) 45311 options.DisplayName = this.getModel().getColumns()[i].DisplayName; 45312 if(this._colOptions[this.getModel().getColumns()[i].ColumnName] != null 45313 && 45314 this._colOptions[this.getModel().getColumns()[i].ColumnName].displayName != null) 45315 options.DisplayName = this._colOptions[this.getModel().getColumns()[i].ColumnName].displayName; 45316 45317 //HideColumn 45318 if (this._colOptions[this.getModel().getColumns()[i].ColumnName] != null 45319 && 45320 this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumn !== undefined) 45321 options.HideColumn = this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumn; 45322 if (this._colOptions[this.getModel().getColumns()[i].ColumnName] != null 45323 && 45324 this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumnInDownload !== undefined) 45325 options.HideColumn = this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumnInDownload; 45326 45327 options.ColumnName = this.getModel().getColumns()[i].ColumnName; 45328 columnOptions.push(options); 45329 } 45330 } 45331 45332 tableModel.Columns = columnOptions; 45333 45334 form.setAttribute("style", "display:none"); 45335 form.setAttribute("method", "POST"); 45336 form.setAttribute("action", url); 45337 45338 fileNameInput.setAttribute("name" , "fileName"); 45339 fileNameInput.setAttribute("value", fileName); 45340 form.appendChild(fileNameInput); 45341 45342 input.setAttribute("name", "model"); 45343 input.value = json.stringify(tableModel); 45344 form.appendChild(input); 45345 45346 document.body.appendChild(form); 45347 45348 form.submit(); 45349 45350 document.body.removeChild(form); 45351 }, 45352 //overridden 45353 _modelChanged: function (type, rowObj, dataField) { 45354 if(type != "CHANGE" || type == "INVALIDATE") 45355 this._updateView(); 45356 }, 45357 _updateView : function() 45358 { 45359 this.renderPage(this.getCurrentPageNumber() , false); 45360 }, 45361 _addPagination : function(){ 45362 var tfootNode; 45363 var tRowNode; 45364 var tdNode; 45365 var numVisibleColumns; 45366 var self = this; 45367 var lastPage; 45368 var nextSetStartPage; 45369 var prevSetStartPage; 45370 var firstLink; 45371 var pageLinkContainer; 45372 var containerNodes = []; 45373 45374 if (this.getModel().getRows().length > 0) 45375 lastPage = Math.floor((this.getModel().getRows().length-1) / this._pageSize); 45376 else 45377 lastPage = 0; 45378 45379 lastPage += 1; 45380 45381 firstLink = ( Math.floor((this._currentPage - 1) / this._maxPageLinks) * this._maxPageLinks)+1; 45382 45383 numVisibleColumns = query("THEAD", this._containerNode)[0].lastChild.cells.length; 45384 45385 tfootNode = query("TFOOT", this._containerNode)[0]; 45386 45387 if (tfootNode == null) { 45388 tfootNode = document.createElement("TFOOT"); 45389 this._containerNode.appendChild(tfootNode); 45390 } 45391 45392 tfootNode.innerHTML = ""; 45393 45394 //add paging links as the first row of the header. 45395 if (this._pageLinksOnTop) { 45396 var tHeadNode = query("THEAD", this._containerNode)[0]; 45397 var trNodes = query("TR", tHeadNode); 45398 tRowNode = document.createElement("TR"); 45399 if (trNodes.length > 1) 45400 tHeadNode.replaceChild(tRowNode, tHeadNode.firstChild); 45401 else 45402 tHeadNode.insertBefore(tRowNode, tHeadNode.firstChild); 45403 containerNodes.push(tRowNode); 45404 } 45405 45406 if (this._pageLinksOnBottom) { 45407 tRowNode = document.createElement("TR"); 45408 tfootNode.appendChild(tRowNode); 45409 containerNodes.push(tRowNode); 45410 } 45411 45412 for (var cni = 0; cni < containerNodes.length; cni++) { 45413 tRowNode = containerNodes[cni]; 45414 tdNode = document.createElement("TD"); 45415 tdNode.setAttribute("colspan", numVisibleColumns); 45416 //to control the paging controls. The default style makes these look good. 45417 tRowNode.appendChild(tdNode); 45418 45419 //save so that we can set display:block later. 45420 this._tFootTDNode = tdNode; 45421 45422 pageLinkContainer = document.createElement("DIV"); 45423 domClass.add(pageLinkContainer, "pagination"); 45424 domClass.add(pageLinkContainer, "pagination-centered"); 45425 tdNode.appendChild(pageLinkContainer); 45426 45427 var ulNode = document.createElement("UL"); 45428 pageLinkContainer.appendChild(ulNode); 45429 45430 var liNode = document.createElement("LI"); 45431 domClass.add(liNode, "footable-page-arrow");//add the disabled class to grey it out. 45432 ulNode.appendChild(liNode); 45433 var aNode = document.createElement("A"); 45434 aNode.setAttribute("data-page", "first"); 45435 aNode.setAttribute("href", "#first"); 45436 aNode.innerHTML = "<<"; 45437 on(aNode, "click", function () { self.renderPage(1); }); 45438 liNode.appendChild(aNode); 45439 45440 liNode = document.createElement("LI"); 45441 ulNode.appendChild(liNode); 45442 aNode = document.createElement("A"); 45443 aNode.innerHTML = "<"; 45444 on(aNode, "click", function () { self.renderPage(self.getCurrentPageNumber() - 1); }); 45445 liNode.appendChild(aNode); 45446 45447 for (var i = firstLink; i < firstLink + this._maxPageLinks; i++) { 45448 liNode = document.createElement("LI"); 45449 domClass.add(liNode, "footable-page"); 45450 ulNode.appendChild(liNode); 45451 aNode = document.createElement("A"); 45452 aNode.innerHTML = i; 45453 if (i == this._currentPage) { 45454 domClass.add(aNode, "pageLinkActive"); 45455 domClass.add(liNode, "active"); 45456 } 45457 else 45458 domClass.add(aNode, "pageLinkInActive"); 45459 45460 on(aNode, "click", (function () { var c = i; return function () { self.renderPage(c); } })()); 45461 liNode.appendChild(aNode); 45462 if (i == lastPage) 45463 break; 45464 } 45465 45466 liNode = document.createElement("LI"); 45467 ulNode.appendChild(liNode); 45468 aNode = document.createElement("A"); 45469 aNode.innerHTML = ">"; 45470 on(aNode, "click", function () { self.renderPage(self.getCurrentPageNumber() + 1); }); 45471 liNode.appendChild(aNode); 45472 45473 liNode = document.createElement("LI"); 45474 ulNode.appendChild(liNode); 45475 var aNode = document.createElement("A"); 45476 aNode.setAttribute("data-page", "last"); 45477 aNode.setAttribute("href", "#last"); 45478 aNode.innerHTML = ">>"; 45479 on(aNode, "click", function () { self.renderPage(lastPage); }); 45480 liNode.appendChild(aNode); 45481 } 45482 }, 45483 //For some reason, the td node under the tfoot gets inline style display:none applied when going into mobile. We always want it shown. This is a hack. 45484 fixHiddenFooterInMobile: function () { 45485 if (this._tFootTDNode != null) 45486 this._tFootTDNode.removeAttribute("style"); 45487 }, 45488 _doPrivateValidate : function() 45489 { 45490 if (this.getContainer() != null && this.getContainer().getValidationMessageWidget() != null) 45491 this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId()); 45492 45493 //check for valid things in the table, if not valid, call the containers validate method to show the me
45493ssage. 45494 if (this.validate() != null) 45495 { 45496 if (this.getContainer() != null) 45497 this.getContainer().validateWidgets(); 45498 return false; 45499 } 45500 return true; 45501 }, 45502 /** 45503 * Render a page of data. 45504 * @param {Number} pageNumber The page to render, from 1-maxPage. If value is > than the number of pages, the last page will be displayed. 45505 * If pageNumber <=0 the first page will be displayed. 45506 * @param {bool} doValidate Default true, perform validation for the table cell widgets. 45507 * @returns {void} 45508 */ 45509 renderPage:function(pageNumber , doValidate) { 45510 var columnInfo = this.getModel().getColumns(); 45511 var data = this.getModel().getRows(); 45512 var endIdx; 45513 var startIdx; 45514 var tbodyNode = query("TBODY", this._containerNode)[0]; 45515 var numPages; 45516 45517 if(doValidate == undefined) 45518 doValidate = true; 45519 45520 if (tbodyNode == null) { 45521 tbodyNode = document.createElement("TBODY"); 45522 if (this._containerNode.firstChild != null) 45523 this._containerNode.insertBefore(tbodyNode, this._containerNode.firstChild); 45524 else 45525 this._containerNode.appendChild(tbodyNode); 45526 } 45527 45528 if (this._paginate) { 45529 if (data.length == 0) 45530 numPages = 1; 45531 else 45532 numPages = Math.floor((data.length - 1) / this._pageSize) + 1; 45533 } 45534 else 45535 { 45536 numPages = 1; 45537 } 45538 45539 if (pageNumber > numPages) 45540 pageNumber = numPages; 45541 45542 if(doValidate && !this._doPrivateValidate()) 45543 return; 45544 45545 this._curr 45546 if (pageNumber <= 0) 45547 pageNumber = 1; 45548 45549 tbodyNode.innerHTML = ""; 45550 45551 this.cleanupEditWidgets(); 45552 45553 if (this._paginate) { 45554 if (data.length > this._pageSize) 45555 endIdx = (pageNumber - 1)*this._pageSize + this._pageSize; 45556 else 45557 endIdx = data.length; 45558 } 45559 else 45560 endIdx = data.length; 45561 45562 startIdx = (pageNumber - 1) * this._pageSize; 45563 45564 if (endIdx > data.length) 45565 endIdx = data.length; 45566 45567 if (data.length == 0) { 45568 startIdx = 0; 45569 } 45570 45571 //for each row. 45572 for (var idx = startIdx; idx < endIdx; idx++) { 45573 tbodyNode.appendChild(this._renderRow(data[idx], columnInfo)); 45574 } 45575 45576 this._currentPage = pageNumber; 45577 45578 if (this._paginate) 45579 this._addPagination(); 45580 45581 //If you are in mobile or phone width it will hide the correct columns for you. 45582 $(this._containerNode).trigger('footable_redraw'); 45583 }, 45584 /** 45585 * Get the current page number. 45586 * @returns {Number} The page number. 45587 */ 45588 getCurrentPageNumber : function() { 45589 return this._currentPage; 45590 }, 45591 renderTable: function () { 45592 var columnInfo = this.getModel().getColumns(); 45593 var data = this.getModel().getRows(); 45594 var columnNames = []; 45595 var tableNode; 45596 var theadNode; 45597 var tbodyNode; 45598 var td; 45599 var tr; 45600 var dataHideParts = []; 45601 var dataHideStr = ""; 45602 var addFooTableClass = false; 45603 var dataHidePhone = false; 45604 var dataHideTab = false; 45605 var self = this; 45606 45607 tableNode = this._containerNode; 45608 45609 var captionNode = query("caption", tableNode)[0]; 45610 45611 if (captionNode != null) 45612 tableNode.removeChild(captionNode); 45613 45614 this.cleanupColumnNameWidgets(); 45615 this.cleanupEditWidgets(); 45616 45617 if (this._captionObj != null) { 45618 captionNode = document.createElement("caption"); 45619 tableNode.appendChild(captionNode); 45620 45621 if (this._captionObj.isInstanceOf && this._captionObj.isInstanceOf(dpage.widgets.Label)) 45622 captionNode.appendChild(this._captionObj.getDomNode()); 45623 else 45624 captionNode.innerHTML = dojox.html.entities.encode(this._captionObj.toString()); 45625 } 45626 45627 this._renderCNameAr = columnNames; 45628 //we do this because footable doesn't like it when we try to bind it more than once to the same element. We have 45629 // to destroy the existing table first. 45630 if (this._initialized) { 45631 var newTableNode = document.createElement("table"); 45632 tableNode.parentNode.insertBefore(newTableNode, tableNode); 45633 tableNode.parentNode.removeChild(tableNode); 45634 tableNode = newTableNode; 45635 this._containerNode = tableNode; 45636 } 45637 this._initialized = true; 45638 45639 theadNode = document.createElement("THEAD"); 45640 tbodyNode = document.createElement("TBODY"); 45641 tableNode.appendChild(theadNode); 45642 tableNode.appendChild(tbodyNode); 45643 45644 tr = document.createElement("TR"); 45645 theadNode.appendChild(tr); 45646 45647 //build the TH section of the table. 45648 for (var idx = 0; idx < columnInfo.length; idx++) { 45649 columnNames.push(columnInfo[idx].ColumnName); 45650 45651 var colOptions = this._colOptions[columnInfo[idx].ColumnName]; 45652 45653 if (colOptions == null) 45654 this._colOptions[columnInfo[idx].ColumnName] = {}; 45655 colOptions = this._colOptions[columnInfo[idx].ColumnName]; 45656 45657 if (colOptions && colOptions.hideColumn) 45658 continue; 45659 45660 td = document.createElement("TH"); 45661 45662 if (colOptions && colOptions.columnNameWidget) { 45663 var options; 45664 45665 if (colOptions.columnNameWidgetOptions != null) 45666 options = colOptions.columnNameWidgetOptions; 45667 else 45668 options = {}; 45669 45670 options.tableObj = this; 45671 options.modelFieldName = columnNames[idx]; 45672 45673 var cnw = new colOptions.columnNameWidget(options); 45674 this._columnWidgets.push(cnw); 45675 45676 if (cnw.getDomNode().nodeName.toUpperCase() != "TH") 45677 throw new Error("The getDomNode() method of the columnNameWidget must return a TH no
45677de."); 45678 45679 td = cnw.getDomNode(); 45680 } 45681 else if (colOptions && colOptions.displayName) { 45682 if(colOptions.encodeDisplayName != undefined && colOptions.encodeDisplayName == false) 45683 td.innerHTML = colOptions.displayName; 45684 else 45685 td.innerHTML = dojox.html.entities.encode(colOptions.displayName); 45686 } 45687 else if(columnInfo[idx].DisplayName != null) 45688 td.innerHTML = dojox.html.entities.encode(columnInfo[idx].DisplayName); 45689 else { 45690 td.innerHTML = dojox.html.entities.encode(columnNames[idx]); 45691 } 45692 45693 //footable.js stuff. 45694 dataHideParts = []; 45695 if (colOptions != null) { 45696 dataHidePhone = colOptions.dataHidePhone; 45697 dataHideTab = colOptions.dataHideTablet; 45698 } 45699 if (dataHidePhone) 45700 dataHideParts.push("phone"); 45701 if (dataHideTab) 45702 dataHideParts.push("tablet"); 45703 45704 if (dataHideParts.length > 0) { 45705 addFooTableClass = true; 45706 dataHideStr = dataHideParts.join(","); 45707 domAttr.set(td, "data-hide", dataHideStr); 45708 } 45709 45710 tr.appendChild(td); 45711 45712 if ((this._sortableColumns && colOptions.sortable == undefined) || 45713 colOptions.sortable) { 45714 //the sort stuff. 45715 domClass.add(td, "sortableColumn"); 45716 var tdSortSpan = document.createElement("SPAN"); 45717 this._colOptions[columnInfo[idx].ColumnName].thNode = td; 45718 domClass.add(tdSortSpan, "footable-sort-indicator"); 45719 on(td, "click", (function () { var c = columnInfo[idx].ColumnName; return function () { self.sort(c); } })()); 45720 td.appendChild(tdSortSpan); 45721 } 45722 } 45723 45724 this.renderPage(1); 45725 }, 45726 /** 45727 * Sort the data in the table by the specified column name in the model. 45728 * @param {String} columnName The column name in the model to sort by. 45729 * @returns {void} 45730 */ 45731 sort : function(columnName) 45732 { 45733 var columnInfo = this.getModel().getColumns(); 45734 var sortDir = null; 45735 var cmpFunc; 45736 var thNode; 45737 var colOptions; 45738 var sortColName; 45739 45740 if (!this._doPrivateValidate()) 45741 return; 45742 45743 for (var idx = 0; idx < columnInfo.length; idx++) { 45744 if (columnInfo[idx].ColumnName == columnName) { 45745 colOptions = this._colOptions[columnInfo[idx].ColumnName]; 45746 if (colOptions == null) { 45747 this._colOptions[columnName] = {}; 45748 colOptions = this._colOptions[columnName]; 45749 } 45750 45751 thNode = colOptions.thNode; 45752 45753 if (colOptions.currentSortDir == null) 45754 colOptions.currentSortDir = 1; 45755 sortDir = colOptions.currentSortDir; 45756 45757 if (sortDir == 1) { 45758 domClass.remove(thNode, "footable-sorted"); 45759 domClass.add(thNode, "footable-sorted-desc"); 45760 } 45761 else { 45762 domClass.remove(thNode, "footable-sorted-desc"); 45763 domClass.add(thNode, "footable-sorted"); 45764 } 45765 } 45766 else { 45767 //remove the sort direction 45768 if (this._colOptions[columnInfo[idx].ColumnName] != null) { 45769 if (this._colOptions[columnInfo[idx].ColumnName].thNode != null) { 45770 domClass.remove(this._colOptions[columnInfo[idx].ColumnName].thNode, "footable-sorted"); 45771 domClass.remove(this._colOptions[columnInfo[idx].ColumnName].thNode, "footable-sorted-desc"); 45772 } 45773 } 45774 } 45775 } 45776 45777 if (colOptions.altSortColumn != null) 45778 sortColName = colOptions.altSortColumn; 45779 else 45780 sortColName = columnName; 45781 45782 if (sortDir == null) 45783 throw new Error("Invalid sort column name of: " + columnName); 45784 45785 if (colOptions.DataType == "DATE") 45786 { 45787 cmpFunc = function (a, b) { 45788 var v1 = a[sortColName]; 45789 var v2 = b[sortColName]; 45790 if (v1 == null && v2 == null) 45791 return 0; 45792 else if (v1 == null && v2 != null) 45793 return -sortDir; 45794 else if (v1 != null && v2 == null) 45795 return sortDir; 45796 else { 45797 v1 = new Date(v1); 45798 v2 = new Date(v2); 45799 return v1 > v2 ? sortDir : v1 < v2 ? -sortDir : 0; 45800 } 45801 }; 45802 } 45803 else if (colOptions.DataType == "NUMBER") { 45804 cmpFunc = function (a, b) { 45805 var v1 = a[sortColName]; 45806 var v2 = b[sortColName]; 45807 if (v1 == null && v2 == null) 45808 return 0; 45809 else if (v1 == null && v2 != null) 45810 return -sortDir; 45811 else if (v1 != null && v2 == null) 45812 return sortDir; 45813 else { 45814 v1 = new Number(v1); 45815 v2 = new Number(v2); 45816 return v1 > v2 ? sortDir : v1 < v2 ? -sortDir : 0; 45817 } 45818 }; 45819 } 45820 else { 45821 cmpFunc = function (a, b) { 45822 var v1 = a[sortColName]; 45823 var v2 = b[sortColName]; 45824 if (v1 == null && v2 == null) 45825 return 0; 45826 else if (v1 == null && v2 != null) 45827 return -sortDir; 45828 else if (v1 != null && v2 == null) 45829 return sortDir; 45830 else { 45831 return v1 > v2 ? sortDir : v1 < v2 ? -sortDir : 0; 45832 } 45833 }; 45834 } 45835 45836 this.getModel().getRows().sort(cmpFunc); 45837 45838 this.renderPage(this._currentPage); 45839 45840 //If you are in mobile or phone width it will hide the correct columns for you. 45841 $(this._containerNode).trigger('footable_redraw'); 45842 45843 colOptions.currentSortDir *= -1; 45844 }, 45845 /*
45846 * Render a row of data. Intended to be used as an internal method in a derived table. 45847 * Can be overridden to render a row any way you would like. Default behavior 45848 * is to return a fully populated TR node. This is the node that is inserted onto the TBODY 45849 * of the table. 45850 * @param {Object} dataRow The row of data from the model. 45851 * @param {Array} columnInfo The column info for this table. 45852 * @returns {DomNode} The TR node to append to the TBODY for this row. 45853 */ 45854 _renderRow: function (dataRow , columnInfo) { 45855 var columnNames = this._renderCNameAr; 45856 var tr = document.createElement("TR"); 45857 var td; 45858 45859 for (var cIdx = 0; cIdx < columnNames.length; cIdx++) { 45860 var colOptions = this._colOptions[columnNames[cIdx]]; 45861 45862 if (colOptions && colOptions.hideColumn) 45863 continue; 45864 45865 td = document.createElement("TD"); 45866 45867 tr.appendChild(td); 45868 //instantiate a widget? 45869 if (colOptions != null && colOptions.widgetConstructor != null) { 45870 var widgetOptions = colOptions.widgetOptions; 45871 if (widgetOptions == null) 45872 widgetOptions = {}; 45873 45874 //add in options to bind the widget to the ds. 45875 widgetOptions.model = new dpage.modules.TabularToSingleValueModel({tabularModel : this.getModel() , dataField : columnNames[cIdx] , dataRow : dataRow}); 45876 45877 var w = new colOptions.widgetConstructor(widgetOptions); 45878 td.appendChild(w.getDomNode()); 45879 this._widgetList.push(w); 45880 var sl = this._widgetLookup[this.getModel().getDataRowId(dataRow)]; 45881 if (sl == null) { 45882 sl = {}; 45883 this._widgetLookup[this.getModel().getDataRowId(dataRow)] = sl; 45884 } 45885 sl[columnNames[cIdx]] = w; 45886 } 45887 else { 45888 if (dataRow[columnNames[cIdx]] != null) 45889 td.innerHTML = dojox.html.entities.encode(dataRow[columnNames[cIdx]].toString()); 45890 } 45891 45892 //alternate value to use for sorting. 45893 if (colOptions != null && colOptions.altSortColumn) { 45894 45895 if (colOptions.altColDataType == "DATE") { 45896 var dateVal = new Date(dataRow[columnNames[cIdx]]); 45897 domAttr.set(td, "data-value", dateVal.getTime()); 45898 } 45899 else { 45900 domAttr.set(td, "data-value", dataRow[colOptions.altSortColumn]); 45901 } 45902 } 45903 } 45904 45905 return tr; 45906 }, 45907 //either render a new table, or just bind an existing table to data. 45908 bindTable: function () { 45909 var self = this; 45910 45911 if (this._useExistingTable) 45912 this.bindExistingTable(); 45913 else 45914 this.renderTable(); 45915 45916 domClass.add(this._containerNode, "footable"); 45917 domClass.add(this._containerNode, "table"); 45918 45919 //Now turn the table into a footable. 45920 //these require jquery to be loaded first which we load in the outter require. 45921 require(["footable/footable"], function () { 45922 $(self._containerNode).footable({ breakpoints: { phone: self._phoneBreakpoint, tablet: self._tabletBreakpoint } }); 45923 }); 45924 45925 $(self._containerNode).bind({ 'footable_redrawn': function () { self.fixHiddenFooterInMobile(); } }); 45926 }, 45927 bindExistingTable: function () { 45928 var thead; 45929 var tbody; 45930 var curNode; 45931 var curRowNode; 45932 var modelNames = []; 45933 var self = this; 45934 45935 this._renderCNameAr = []; 45936 45937 for (var i = 0; i < this.getModel().getColumns().length; i++) 45938 this._renderCNameAr.push(this.getModel().getColumns()[i].ColumnName); 45939 45940 thead = query("THEAD", this._containerNode)[0]; 45941 if (thead.nodeName != "THEAD") 45942 throw new Error("First child of a widgets.Table must be a thead when specifying to use the existing table."); 45943 45944 tbody = query("TBODY", this._containerNode)[0]; 45945 45946 if (tbody.nodeName != "TBODY") 45947 throw new Error("Second child of a widgets.Table must be a tbody when specifying to use the existing table."); 45948 45949 curNode = query("TH", thead); 45950 45951 for (var idx = 0 ; idx < curNode.length ; idx++) { 45952 //look for this attribute on thead nodes so we know to bind this column to a model column.
45953 var modelProp = domAttr.get(curNode[idx], "data-model-prop"); 45954 45955 if (modelProp) { 45956 if (!this._modelColNames[modelProp]) 45957 throw new Error("Invalid model column name of: " + modelProp + " specified in a data-model-prop attribute."); 45958 modelNames.push(modelProp); 45959 } 45960 else 45961 modelNames.push(null); 45962 } 45963 45964 //check to see if we have colOptions, that the table has a data-model-prop attribute that corresponds to it to help usability of the control 45965 for (var colName in this._colOptions) { 45966 if (this._colOptions.hasOwnProperty(colName)) { 45967 var good = false; 45968 for (var idx = 0; idx < modelNames.length; idx++) 45969 if (modelNames[idx] == colName) 45970 good = true; 45971 45972 if (!good) { 45973 throw new Error("Table: " + this.getWidgetId() + ". You have specified a colOption for column " + colName + " but have not added a data-model-prop attribute on the <th> node, like this: <th data-model-prop='" + colName + "'>" + colName + " (or custom header content)</th>"); 45974 } 45975 } 45976 } 45977 45978 45979 curRowNode = query("TR", tbody); 45980 45981 //for each row. 45982 for (var idx = 0; idx < curRowNode.length; idx++) { 45983 curNode = query("TD", curRowNode[idx]); 45984 //for each row 45985 for (var idxCol = 0; idxCol < curNode.length; idxCol++) { 45986 var modelColumn = modelNames[idxCol]; 45987 45988 if (modelColumn != null) { 45989 if (this._colOptions[modelColumn] != null && this._colOptions[modelColumn].widgetConstructor != null) { 45990 var widgetOptions = this._colOptions[modelColumn].widgetOptions; 45991 if (widgetOptions == null) 45992 widgetOptions = {}; 45993 45994 //add in options to bind the widget to the ds. 45995 widgetOptions.model = new dpage.modules.TabularToSingleValueModel({ tabularModel: this.getModel(), dataField: modelColumn, dataRow: this.getModel().getRows()[idx] }); 45996 45997 curNode[idxCol].innerHTML = ""; 45998 if (idx >= this.getModel().getRows().length) 45999 throw new Error("When bound to a model, the number of model rows and table rows must match. Num model rows= " + this.getModel().getRows().length + " num table rows= " + curRowNode.length); 46000 var w = new this._colOptions[modelColumn].widgetConstructor(widgetOptions); 46001 curNode[idxCol].appendChild(w.domNode); 46002 this._widgetList.push(w); 46003 var sl = this._widgetLookup[this.getModel().getDataRowId(this.getModel().getRows()[idx])]; 46004 if (sl == null) { 46005 sl = {}; 46006 this._widgetLookup[this.getModel().getDataRowId(this.getModel().getRows()[idx])] = sl; 46007 } 46008 sl[modelColumn] = w; 46009 } 46010 } 46011 } 46012 } 46013 }, 46014 /** 46015 * Set the model for the Table. Will cause the table to be redrawn. 46016 * @param {dpage.modules.TabularModel} model The model to set. 46017 * @param {bool} [dontRenderTable] if true, the table will not be re-drawn to match the data. 46018 * @returns {void} 46019 */ 46020 setModel: function (model, dontRenderTable) { 46021 this.inherited(arguments); 46022 46023 if (!dontRenderTable) 46024 this.bindTable(); 46025 }, 46026 //overridden 46027 validate: function () { 46028 var message; 46029 var ret = ""; 46030 46031 for (var idx = 0; idx < this._widgetList.length ; idx++) { 46032 message = this._widgetList[idx].validate(); 46033 if (message != null) 46034 ret += message + " "; 46035 } 46036 46037 if (ret != "") 46038 return ret; 46039 else 46040 return null; 46041 } 46042 46043 });
46044}); 46045 46046}, 46047'dpage/modules/TabularToSingleValueModel':function(){ 46048define([ 46049 "dojo/_base/declare" 46050 , "dojo/on" 46051 , "dojo/_base/event" 46052 46053 , "dpage/modules/SingleValueModel" 46054], 46055 function (declare, on, event) { 46056 /** 46057 * @namespace dpage 46058 */ 46059 /** 46060 * @namespace modules 46061 * @memberOf dpage 46062 */ 46063 /** 46064 * This class is intended to provide a wrapper around a TabularModel so that the multi-column, multi-row TabularModel can look like a 46065 * SingleValueModel. Great for when you need to bind a SingleValueWidget to a particular value in a TabularModel. You have to tell this 46066 * class which column and row to bind to. Then, this class exposes that value the same as a SingleValueModel would. 46067 * @class TabularToSingleValueModel 46068 * @param {Object} [options] Optional options for the TabularModel. 46069 * @param {dpage.modules.TabularModel} [options.tabularModel] The TabularModel we are wrapping. 46070 * @param {String} [options.dataField] The dataField in the TabularModel we are binding to. If not specified, will default to the "first" column in the TabularModel. 46071 * @param {Object} [options.dataRow] Number|Object The row object in the TabularModel we are binding to. If not specified, will default to the first row in the TabularModel. 46072 * You can pass in either a row object from the TabularModel or a row index (zero-based). 46073 46074 * @param {Object} [options.displayName] The display name of this property. This will be used in things like validation messages. If passed, overrides the DisplayName and FieldName properties in the modelProps. 46075 * @param {Object} [options.modelProps] Optional properties describing the model value including DataType, etc. 46076 * @param {String} [options.modelProps.ColumnName] Name of the field in the model (Deprecated). 46077 * @param {String} [options.modelProps.DataType] NUMBER, BOOL, or TEXT 46078 * @param {String} [options.modelProps.DisplayName] Value used for display of the field to the user. 46079 * @param {String} [options.modelProps.FieldName] Name of the field in the model. 46080 * @param {Number} [options.modelProps.MaxLength] Maximum character length. 46081 * @param {String} [options.modelProps.MaxLengthValidationMessage] Message to display for MaxLength validation failure. 46082 * @param {Number} [options.modelProps.MaxValue] Maximum value for NUMBER type. 46083 * @param {Number} [options.modelProps.MinValue] Minimum value for NUMBER type. 46084 * @param {String} [options.modelProps.NumberValidationMessage] Message to display if the number validation fails. 46085 * @param {Number} [options.modelProps.NumDecimals] Maximum number of decimals for NUMBER type. 46086 * @param {bool} [options.modelProps.Required] Is a non-blank value required in this field 46087 * @param {String} [options.modelProps.RequiredValidationMessage] Message to display for Required validation failure. 46088 * @param {String} [options.modelProps.ValidationPattern] Javascript regular expression for input validation. 46089 * @param {String} [options.modelProps.ValidationPatternMessage] Custom message to display if ValidationPattern fails. 46090 * @memberOf dpage.modules 46091 * @extends {dpage.modules.SingleValueModel} 46092 */ 46093 return declare("dpage.modules.TabularToSingleValueModel", [dpage.modules.SingleValueModel], /** @lends dpage.modules.TabularToSingleValueModel.prototype */ { 46094 _model: null, 46095 _dataCallbacks: null, 46096 _lastDataCallbackId: 0, 46097 _dataCallbackRowId: 0, 46098 _modelProps: null, 46099 _dataField:null, 46100 _dataRow:null, 46101 46102 constructor: function (options) { 46103 var self = this; 46104 46105 this._dataCallbacks = []; 46106 46107 if (options == null || options.tabularModel == null)
46108 throw new Error("Must pass in a non-null tabularModel property that is an instance of a dpage.modules.TabularModel"); 46109 46110 if (options != null) { 46111 46112 if (options.tabularModel != null) { 46113 this._model = options.tabularModel; 46114 } 46115 46116 if (options.dataField != null) { 46117 this._dataField = options.dataField; 46118 } 46119 46120 if (options.dataRow != null) { 46121 if (typeof (options.dataRow) == 'number' || options.dataRow instanceof (Number)) 46122 this._dataRow = this._model.getRow(options.dataRow); 46123 else 46124 this._dataRow = options.dataRow; 46125 } 46126 46127 if (options.modelProps != null) 46128 this._modelProps = options.modelProps; 46129 } 46130 46131 if (this._dataRow == null) { 46132 if (this._model.getRows().length == 0) 46133 throw new Error("Problem binding to row of a TabularModel. Must pass the dataRow option and the TabularModel must have at least one row of data."); 46134 this._dataRow = this._model.getRows()[0]; 46135 } 46136 46137 if (this._dataField == null) 46138 this._dataField = this._model.getColumns()[0].ColumnName; 46139 46140 if (options == null || options.modelProps == null) 46141 this._modelProps = this._model.getColumnInfo(this._dataField); 46142 46143 46144 this._model.addDataCallback(function (changeType, rowObj, propName) { self.tmCallback(changeType, rowObj, propName); }, this._dataRow); 46145 }, 46146 /** 46147 * Provides the single scalar value. 46148 * @returns {Object} 46149 */ 46150 getRawModel : function() 46151 { 46152 return this.getValue(); 46153 }, 46154 /** 46155 * Get the dataField from the wrapped TabularModel that we are bound to. 46156 * @returns {String} The dataField. 46157 */ 46158 getDataField : function() 46159 { 46160 return this._dataField; 46161 }, 46162 /** 46163 * Get the dataRow from the wrapped TabularModel that we are bound to. 46164 * @returns {Object} The row object from the TabularModel. 46165 */ 46166 getDataRow : function() 46167 { 46168 return this._dataRow; 46169 }, 46170 //Called whenever the TabularModel changes. 46171 tmCallback : function(changeType , rowObj , propName) 46172 { 46173 if(changeType == "CHANGE" && propName == this._dataField) 46174 { 46175 this.doCallbacks(); 46176 } 46177 }, 46178 /** 46179 * Get the TabularModel object that this object is wrapping. This is usefull if you need to get or set the value 46180 * of a different field in the same row of the TabularModel this object is wrapping. 46181 * @returns {dpage.modules.TabularModel} 46182 */ 46183 getTabularModel : function() 46184 { 46185 return this._model; 46186 }, 46187 /** 46188 * Overrides SingleValueModel.setModel(). Set the value in the row and cell of the 46189 * TabularModel this object is bound to. The official way to set a value. 46190 * @param {Object} value The value to set. Must be a bool, String, or Number 46191 * @returns {void} 46192 */ 46193 setValue: function (value) { 46194 46195 this._model.setValue(this._dataRow , this._dataField , value); 46196 }, 46197 //overridden. 46198 isDirty : function() 46199 { 46200 return this._model.isDirty(); 46201 }, 46202 /** 46203 * Overrides SingleValueModel.getValue(). Gets the value of the row and cell that this object 46204 * is bound to. The official way to get a value. 46205 * @returns {Object} The data. Will be String, Number, or Boolean 46206 */ 46207 getValue: function () { 46208 return this._model.getValue(this._dataRow , this._dataField); 46209 } 46210 46211 }); 46212 } 46213); 46214}, 46215'dpage/modules/Config':function(){ 46216define([ 46217 "dojo/_base/declare" 46218], 46219 function (declare) { 46220 var c = declare("dpage.modules.Config", [], { 46221 }); 46222 46223 c.dpageRoot = "https://svc.mt.gov/itsd/dpage/"; 46224 c.dpageScriptRoot = "https://svc.mt.gov/itsd/dpage/Scripts/1.0/"; 46225 46226 return c; 46227 } 46228); 46229}, 46230'dpage/widgets/TableColumnNameWidget':function(){ 46231define([ 46232 "dojo/_base/declare", 46233 "dpage/widgets/BaseWidget"], 46234function () { 46235 /** 46236 * @namespace dpage 46237 */ 46238 /** 46239 * @namespace widgets 46240 * @memberOf dpage 46241 */ 46242 /** 46243 * Class for creating a custom column header for the dpage.widgets.Table class. Use this class to control how the TH node of the table looks. 46244 * @class TableColumnNameWidget 46245 * @param {Object} [options] Optional options for the widget 46246 * 46247 * @param {dpage.widgets.Table} options.tableObj The table object this widget is in. 46248 * @param {String} options.modelFieldName The name of the model field this cell is bound to. 46249 * 46250 * @param {dpage.widgets.Container} [options.container] The container of the widget. 46251 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 46252 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 46253 * is created. 46254 * @param {Object} [containerNode] Optional container node to tie the widget to. 46255 * @memberOf dpage.widgets 46256 * @extends {dpage.widgets.BaseWidget} 46257 */ 46258 return dojo.declare("dpage.widgets.TableColumnNameWidget", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.TableColumnNameWidget.prototype */ { 46259 _tableObj: null, 46260 _modelFieldName : null, 46261 46262 constructor: function (options, srcNodeRef) { 46263 if (options == null || options.tableObj == null || options.modelFieldName == null) 46264 throw new Exception("Must define options.tableObj and options.modelFieldName"); 46265 46266 this._containerNode = srcNodeRef; 46267 46268 if (this._containerNode == null) 46269 this._containerNode = document.createElement("th"); 46270 46271 this._tableObj = options.tableObj; 46272 this._modelFieldName = options.modelFieldName; 46273 }, 46274 postCreate : function(){ 46275 this._updateView(); 46276 }, 46277 //The default view. 46278 _updateView : function(){ 46279 var meta = this._tableObj.getModel().getColumnInfo(this._modelFieldName); 46280 var text; 46281 46282 if (meta.DisplayName != null) 46283 text = dojox.html.entities.encode(meta.DisplayName); 46284 else 46285 text = dojox.html.entities.encode(this._modelFieldName); 46286 46287 this._containerNode.innerHTML = text; 46288 }, 46289 getTableObj : function() 46290 { 46291 return this._tableObj; 46292 }, 46293 getModelFieldName: function () { 46294 return this._modelFieldName; 46295 }, 46296 destroy: function () { 46297 this._tableObj = null; 46298 this._modelFieldName = null; 46299 return this.inherited(arguments); 46300 } 46301 46302 });
46303}); 46304 46305}, 46306'dpage/widgets/DateTextBox':function(){ 46307define([ 46308 "dojo/_base/event" 46309 , "dojo/on" 46310 , "dojo/dom-attr" 46311 , "dojo/dom-class" 46312 , "dojo/mouse" 46313 , "dojo/dom-geometry" 46314 , "dojo/dom-style" 46315 , "dojo/json" 46316 , "dojo/_base/declare" 46317 , "jQueryPrivate" 46318 , "dojo/date/locale" 46319 46320 , "xstyle/css!//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" 46321 , "dpage/widgets/TextBox" 46322 , "jquery-ui/ui/datepicker" 46323 , "dpage/modules/Date" 46324 , "dpage/widgets/SingleValueWidget"], 46325function (event, on, domAttr, domClass, mouse, domGeom, style, json, declare, $, locale) { 46326 /** 46327 * @namespace dpage 46328 */ 46329 /** 46330 * @namespace widgets 46331 * @memberOf dpage 46332 */ 46333 /** 46334 * Specialized TextBox for dates. Uses the default date format specified in dpage.modules.Date.getDatePattern() unless you specify a custom one in the options. 46335 * @class DateTextBox 46336 * @param {Object} [options] Optional options for the widget. 46337 * @param {bool} [options.datePicker] Default true. Add a date picker to the textbox. 46338 * @param {string} [options.dateFormatString] Default null. If null, defaults to the dpage.modules.Date.getDatePattern() string. This string contains the pattern used to 46339 * parse and format the dates. This string conforms to the specification here: 46340 * <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a> 46341 46342 * @param {String} [options.placeHolder] Optional placeholder text. Backwards compatible on browsers that don't natively support this attribute. 46343 * @param {Function} [options.formatter] string options.formatter(rawValue). Function to call for formatting the text. The formatter will be used 46344 * to set the value of the input when the input is non-focused. When the input is focused, 46345 * the raw value from the model will be shown. This function returns the value to display in the textbox. 46346 * @param {Function} [options.editFormatter] string options.formatter(rawValue). Function to call for formatting the text when the TextBox is focused. 46347 * The formatter will be used 46348 * to set the value of the input when the input is focused. 46349 * @param {Function} [options.inputFilter] string options.inputFilter(rawValue). This function will be called to return the value that is saved to the model. 46350 * Default behavior is to store the value the user types into the TextBox to the model. Passing in this function overrides 46351 * this behavior. 46352 * The function is passed the raw value that the user types into the textbox. The function will return the value 46353 * to store in the model. This function only operates on user input and is meant to be used to coerce different forms of user 46354 * input to the correct model value. 46355 * @param {bool} [options.highlightOnFocus] Default false. Highlight the text when the input is focused. 46356 * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input. 46357 46358 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 46359 * @param {dpage.widgets.Container} [options.container] The container of the widget. 46360 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 46361 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 46362 * is created. 46363 * @param {Object} [containerNode] Optional container node to tie the widget to. 46364 * @memberOf dpage.widgets 46365 * @extends {dpage.widgets.SingleValueWidget} 46366 */ 46367 return declare("dpage.widgets.DateTextBox", [dpage.widgets.TextBox], /** @lends dpage.widgets.DateTextBox.prototype */ { 46368 _datePicker: true, 46369 _dateFormatString: null, 46370 46371 constructor: function (options, srcNodeRef) { 46372 var self=this; 46373 46374 if(options == null) 46375 options = {}; 46376 46377 if (options.dateFormatString != null) 46378 this._dateFormatString = options.dateFormatString; 46379 if(options.formatter == null) 46380 this._formatter = function (v) { return self.formatDate(v); }; 46381 if (options.editFormatter == null) 46382 this._editFormatter = function (v) { return self.formatDate(v); }; 46383 if (options.inputFilter == null) 46384 this._inputFilter = function (v) { return self.inputFilter(v); }; 46385 if (options.datePicker != undefined && options.datePicker == false) 46386 this._datePicker = false; 46387 if (options.model != null && options.model.getMetadata().DataType != "DATE") 46388 throw new Error("The DataType for a DateTextBox must be DATE. WidgetId: " + this.getWidgetId()); 46389 }, 46390 postCreate : function(){ 46391 var self = this; 46392 if (this._datePicker) { 46393 $(this.getDomNode()).datepicker({ 46394 onSelect: function (dateText) { self.datePicker_OnChange(dateText); }, 46395 beforeShow : function(inputElement , instance) { return self.datePicker_BeforeShow(inputElement , instance);}, 46396 constrainInput:false 46397 }); 46398 } 46399 return this.inherited(arguments); 46400 }, 46401 setModel: function (model) { 46402 //validate the model and all. 46403 this.inherited(arguments); 46404 46405 if (model != null && model.getMetadata().DataType != "DATE") 46406 throw new Error("The DataType for a DateTextBox must be DATE. WidgetId: " + this.getWidgetId()); 46407 }, 46408 datePicker_BeforeShow: function (inputElement, instance) { 46409 var d = dpage.modules.Date.parseDateString(inputElement.value , this._dateFormatString); 46410 var oldInputText = inputElement.value; 46411 //causes the input to be updated. 46412 $(this.getDomNode()).datepicker("setDate", d); 46413 46414 setTimeout(function () { inputElement.value = oldInputText; }, 0); 46415 }, 46416 datePicker_OnChange : function(dateText) 46417 { 46418 var prevDate = dpage.modules.Date.parseModelValue(this.getValue()); 46419 var newDate = $(this.getDomNode()).datepicker("getDate"); 46420 46421 //We want to keep the minutes/seconds/milliseconds parts. 46422 if (isFinite(newDate) && prevDate != null){ 46423 //possibly change the value to keep the minutes/seconds. 46424 newDate.setSeconds(prevDate.getSeconds()); 46425 newDate.setMinutes(prevDate.getMinutes()); 46426 newDate.setMilliseconds(prevDate.getMilliseconds()); 46427 newDate.setHours(prevDate.getHours()); 46428 } 46429 46430 this.setValue(dpage.modules.Date.toModelValue(newDate)); 46431 }, 46432 //default date formatter 46433 formatDate : function(strVal){ 46434 var v; 46435 46436 if (strVal == null) 46437 return ""; 46438 46439 v = dpage.modules.Date.parseModelValue(strVal); 46440 46441 if (v == null) 46442 return strVal; 46443 else { 46444 var str; 46445 46446 if(this._dateFormatString == null) 46447 str = dpage.modules.Date.formatDate(v); 46448 else 46449 str = locale.format(v, { 46450 datePattern: this._dateFormatString, 46451 selector: "date" 46452 }); 46453 46454 return str; 46455 } 46456 }, 46457 inputFilter: function (strVal) { 46458 var d; 46459 46460 if (strVal == null || strVal.match(/^\s*$/) != null) 46461 return null; 46462 46463 if(this._dateFormatString == null) 46464 d = dpage.modules.Date.parseDateString(strVal); 46465 else 46466 d = locale.parse(strVal, { 46467 datePattern: this._dateFormatString, 46468 selector: "date" 46469 }); 46470 46471 if (d!=null) 46472 return dpage.modules.Date.toModelValue(d); 46473 else 46474 return strVal; 46475 }, 46476 //get the displayed value from the textbox and validate that. 46477 validate: function () { 46478 var value = this.getTextValue(); //get the value displayed in the textbox. 46479 var ret; 46480 46481 domClass.remove(this._containerNode, "input-invalid"); 46482
46483 ret = this._validateDate(value, this.getModel().getMetadata(), this.getModel().getDisplayName()); 46484 46485 if (ret != null) 46486 domClass.add(this._containerNode, "input-invalid"); 46487 46488 return ret; 46489 }, 46490 /* 46491 * Return a message indicating the error or null for no validation error. 46492 * @param {Object} value The value to validate. 46493 * @param {Object} metaData The metadata object from the model. 46494 * @param {String} fieldName The name of the field to display in the non-custom error message. 46495 * @returns {String} null for success. non-empty string otherwise. 46496 */ 46497 _validateDate : function (value, metaData, fieldName) { 46498 var maxLength = metaData.MaxLength; 46499 var required = metaData.Required; 46500 var requiredMessage = metaData.RequiredValidationMessage; 46501 var maxLengthMessage = metaData.MaxLengthValidationMessage; 46502 var patternMessage = metaData.ValidationPatternMessage; 46503 var pattern = metaData.ValidationPattern; 46504 46505 if (fieldName == null) 46506 fieldName = metaData.FieldName; 46507 46508 if (maxLength != null && value.length > maxLength) { 46509 if (maxLengthMessage != null) 46510 return maxLengthMessage; 46511 else 46512 return fieldName + " must be less than " + (maxLength + 1) + " characters."; 46513 } 46514 46515 if (required && (value == null || /^\s*$/.exec(value))) { 46516 if (requiredMessage != null) 46517 return requiredMessage; 46518 else 46519 return fieldName + " is required."; 46520 } 46521 46522 if (pattern != null) { 46523 var re = new RegExp(pattern); 46524 if (!re.exec(value)) { 46525 if (patternMessage != null) 46526 return patternMessage; 46527 else 46528 return fieldName + " must match the pattern: '" + pattern + "'."; 46529 } 46530 } 46531 46532 if (value != null && value != "") { 46533 //attempt to parse the date. 46534 var v = dpage.modules.Date.parseDateString(value , this._dateFormatString); 46535 46536 if (v == null) { 46537 var pString; 46538 46539 if (this._dateFormatString == null) 46540 pString = dpage.modules.Date.getDatePattern(); 46541 else 46542 pString = this._dateFormatString; 46543 46544 return fieldName + " must be a valid date in the format of: " + pString; 46545 } 46546 } 46547 46548 return null; 46549 } 46550 46551 }); 46552}); 46553 46554}, 46555'dpage/widgets/TextBox':function(){ 46556define([ 46557 "dojo/_base/event" 46558 ,"dojo/on" 46559 ,"dojo/dom-attr" 46560 ,"dojo/dom-class" 46561 ,"dojo/mouse" 46562 ,"dojo/dom-geometry" 46563 , "dojo/dom-style" 46564 , "dojo/json" 46565 46566 , "xstyle/css!dpage/widgets/TextBox.css" 46567 , "dpage/modules/LegacyPlaceholder" 46568 , "dpage/modules/TabularModel" 46569 , "dojo/request/xhr" 46570 ,"dojox/html/entities" 46571 ,"dojo/_base/declare" 46572 , "dpage/widgets/SingleValueWidget"], 46573function (event, on, domAttr, domClass, mouse, domGeom, style, json) { 46574 /** 46575 * @namespace dpage 46576 */ 46577 /** 46578 * @namespace widgets 46579 * @memberOf dpage 46580 */ 46581 /** 46582 * Class to encapulate the functionality of a <input type="text"> element. Supports containerNode type 46583 * of either an INPUT type='text' or a TEXTAREA. INPUT's have a known 46584 *size limitation in the browser that cannot be overcome. Use a TEXTAREA for large amounts > .5MB. of data. 46585 * @class TextBox 46586 * @param {Object} [options] Optional options for the widget. 46587 * @param {String} [options.placeHolder] Optional placeholder text. Backwards compatible on browsers that don't natively support this attribute. 46588 * @param {Function} [options.formatter] string options.formatter(rawValue). Function to call for formatting the text. The formatter will be used 46589 * to set the value of the input when the input is non-focused. When the input is focused, 46590 * the raw value from the model will be shown (or the value returned from editFormatter(). This function returns the value to display in the textbox. 46591 * @param {Function} [options.editFormatter] string options.formatter(rawValue). Function to call for formatting the text when the TextBox is focused. Either the model value 46592 * will be passed in, or the last user inputted value. In an inputFilter() is specified, the last user input is fed to that function first. 46593 * @param {Function} [options.inputFilter] string options.inputFilter(rawValue). This function will be called to return the value that is saved to the model. 46594 * Default behavior is to store the value the user types into the TextBox to the model. Passing in this function overrides 46595 * this behavior. 46596 * The function is passed the raw value that the user types into the textbox. The function will return the value 46597 * to store in the model. This function only operates on user input and is meant to be used to coerce different forms of user 46598 * input to the correct model value. 46599 * @param {bool} [options.highlightOnFocus] Default false. Highlight the text when the input is focused. 46600 * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input. 46601 46602 * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 46603 * @param {dpage.widgets.Container} [options.container] The container of the widget. 46604 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 46605 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 46606 * is created. 46607 * @param {Object} [containerNode] Optional container node to tie the widget to. 46608 * @memberOf dpage.widgets 46609 * @extends {dpage.widgets.SingleValueWidget} 46610 */ 46611 return dojo.declare("dpage.widgets.TextBox", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.TextBox.prototype */ { 46612 _containerNode: null, 46613 _placeholder: null, 46614 _emulatePlaceholder: false, //support for IE9 placeholder. 46615 _onChange: null, //needs to be null here an initialized in the constructor otherwise it acts like a static member. 46616 _formatter: null, 46617 _editFormatter: null, 46618 _inputFilter:null, 46619 _lastUserInput: null, //This gets populated when the user focuses into or out of the input. 46620 _focused: false, 46621 _highlightOnFocus: false, 46622 46623 constructor : function(options , srcNodeRef) 46624 { 46625 var self = this; 46626 this._containerNode = srcNodeRef; 46627 46628 this._onChange = []; 46629 46630 if (this._containerNode == null) { 46631 this._containerNode = document.createElement("INPUT"); 46632 } 46633 46634 if (this._containerNode.nodeName != "INPUT" && this._containerNode.nodeName != "TEXTAREA") 46635 throw new Error("Source node for widgets.TextBox must be an INPUT or a TEXTAREA"); 46636 46637 if (options != null) 46638 { 46639 if (options.placeholder != null) { 46640 this._placeholder = options.placeholder; 46641 } 46642 if (options.onChange != null) { 46643 this.on("change", options.onChange); 46644 } 46645 if (options.formatter != null) { 46646 this._formatter = options.formatter; 46647 } 46648 if (options.editFormatter != null) { 46649 this._editFormatter = options.editFormatter; 46650 } 46651 if (options.inputFilter != null) { 46652 this._inputFilter = options.inputFilter; 46653 } 46654 if (options.highlightOnFocus) 46655 this._highlightOnFocus = options.highlightOnFocus; 46656 } 46657 46658 on(this._containerNode, "blur", function (event) { self.input_OnBlur(event); });
46659 on(this._containerNode, "focus", function (event) { self.input_OnFocus(event); }); 46660 on(this._containerNode, "change", function (event) { self.input_OnChange(event); }); 46661 on(this._containerNode, mouse.enter, function (event) { self._item_OnMouseEnter(event); }); 46662 on(this._containerNode, mouse.leave, function (event) { self._item_OnMouseLeave(event); }); 46663 }, 46664 postCreate: function () 46665 { 46666 //initialize from the dom node. 46667 if (domAttr.get(this.domNode, "placeholder") != null) 46668 this._placeholder = domAttr.get(this.domNode, "placeholder"); 46669 46670 if (this._placeholder != null) { 46671 if (dpage.modules.LegacyPlaceholder.hasNativePlaceholderSupport()) 46672 domAttr.set(this.domNode, "placeholder", this._placeholder); 46673 else { 46674 this._emulatePlaceholder = true; 46675 } 46676 } 46677 46678 //support setting the model value based on a value in the markup. 46679 if (this._containerNode.getAttribute("value") != null) { 46680 this.setModelValue(this._containerNode.getAttribute("value")); 46681 } 46682 46683 return this.inherited(arguments); 46684 }, 46685 46686 setModel : function(model) 46687 { 46688 this.inherited(arguments); 46689 this._updateView(); 46690 }, 46691 input_OnFocus: function () 46692 { 46693 var self = this; 46694 var nonFormattedValue; 46695 46696 if (this._lastUserInput != null) { 46697 if(this.getDomNode().value != this._lastUserInput) 46698 this.getDomNode().value = this._lastUserInput; 46699 } 46700 else { 46701 if (this._editFormatter != null) { 46702 if (this.getDomNode().value != this._editFormatter(this.getValue())) 46703 this.getDomNode().value = this._editFormatter(this.getValue()); 46704 } 46705 else { 46706 if (this.getDomNode().value != this.getValue()) 46707 this.getDomNode().value = this.getValue() == null ? "" : this.getValue(); 46708 } 46709 } 46710 46711 if(this._emulatePlaceholder) 46712 { 46713 if(this.domNode.value == this._placeholder) 46714 { 46715 this.domNode.value = ""; 46716 domClass.remove(this.getDomNode(), "placeholder"); 46717 } 46718 } 46719 46720 if(this._highlightOnFocus){ 46721 setTimeout(function () { 46722 self._containerNode.setSelectionRange(0, self._containerNode.value.length); 46723 }); 46724 } 46725 46726 this._focused = true; 46727 }, 46728 /** 46729 * This method returns the same value as getValue(), except in the case of bad user input. In that case, it will return back the user input value with the inputFilter() function 46730 * applied (if applicable). With no inputFilter, formatter, or editFormatter applied, this function, and the getTextValue() function should return the same value. 46731 * @returns {Object} 46732 */ 46733 getCandidateValue: function () { 46734 var v; 46735 46736 //if for some reason, we get here and we have focus, we need to update the _lastUserInput var. 46737 if (this._focused) 46738 this._lastUserInput = this.getDomNode().value; 46739 46740 v = this._lastUserInput; 46741 46742 //if the control hasn't been focused since the last _updateView. 46743 if (v == null) 46744 return this.getValue(); 46745 46746 //if we are a non-text datatype, we need to set the value to null on empty input. 46747 if (this._lastUserInput.match(/^\s*$/) != null && 46748 (this.getModel().getMetadata().DataType == "NUMBER" || 46749 this.getModel().getMetadata().DataType == "BOOL" || 46750 this.getModel().getMetadata().DataType == "DATE")) { 46751 v = null; 46752 } 46753 46754 if (this._inputFilter != null) 46755 v = this._inputFilter(this._lastUserInput); 46756 46757 return v; 46758 }, 46759 /* 46760 * Defined in TextBox. This method is designed to *ONLY* be called when the blur event fires. At this point, the value in the input is raw user input. 46761 */ 46762 _doValueChanged: function (evt) { 46763 var cleansedValue; 46764 46765 if (this.validate() == null) { 46766 if (this.getContainer()) { 46767 if (this.getContainer().getValidationMessageWidget()) { 46768 this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId()); 46769 } 46770 } 46771 46772 //only set the value if it is changed. Otherwise we taint the model. 46773 if (this.getCandidateValue() != this.getValue()) { 46774 this.setModelValue(this.getCandidateValue()); 46775 //call callbacks in order. 46776 for (var i = 0; i < this._onChange.length; i++) 46777 this._onChange[i]({ event: evt, widget: this }); 46778 } 46779 } 46780 46781 //we are moving out of focused and into a non-focused state. 46782 if (this._formatter != null) { 46783 //Q: Why do we do this instead of getting the value from the model? A: because the value in the textbox may be invalid input and in that case is not 46784 // saved to the model. 46785 46786 this.getDomNode().value = this._formatter(this.getCandidateValue()); 46787 } 46788 46789 //ie9 support. 46790 if (this._emulatePlaceholder) { 46791 if (this.domNode.value == "") { 46792 this.domNode.value = this._placeholder; 46793 domClass.add(this.getDomNode(), "placeholder"); 46794 } 46795 else { 46796 domClass.remove(this.getDomNode(), "placeholder"); 46797 } 46798 } 46799 }, 46800 input_OnBlur: function (evt) { 46801 var self = this; 46802 46803 //store the value the user entered in. 46804 this._lastUserInput = this._containerNode.value; 46805 46806 this._doValueChanged(evt); 46807 46808 this._focused = false; 46809 }, 46810 input_OnChange: function (evt) 46811 { 46812 46813 }, 46814 /** 46815 * Focus the widget for user input. 46816 * @returns {void} 46817 */ 46818 focus: function () { 46819 this.getDomNode().focus(); 46820 this._focused = true; 46821 }, 46822 /** 46823 * Get the raw value displayed in the control. This may not match the value returned from getValue() because the input could be invalid. There could also be formatter routines. 46824 * @returns {string} 46825 */ 46826 getTextValue: function () { 46827 if (this._emulatePlaceholder && this.domNode.value == this._placeholder) 46828 return ""; 46829 46830 return this.getDomNode().value; 46831 }, 46832 /* 46833 * Update the view based on model changes. This will also clear any invali
46833d state. Direct model changes should not be validated. 46834 */ 46835 _updateView : function() 46836 { 46837 //call the base class (BaseWidget). This clears the validation state common to all BaseWidget _updateView methods. 46838 this.inherited(arguments); 46839 46840 var val = this.getValue(); 46841 46842 //update the value in the textbox. 46843 if (val == null) 46844 val = ""; 46845 46846 this._lastUserInput = null; 46847 46848 if (this._focused) { 46849 if (this._editFormatter != null) 46850 this.getDomNode().value = this._editFormatter(val); 46851 else 46852 this.getDomNode().value = val; 46853 } 46854 else { 46855 var valToSet; 46856 if (this._formatter != null) 46857 valToSet = this._formatter(val); 46858 else 46859 valToSet = val; 46860 46861 if (this._emulatePlaceholder && valToSet == "") { 46862 domClass.add(this.getDomNode(), "placeholder"); 46863 this.getDomNode().value = this._placeholder; 46864 } 46865 else { 46866 if (this._emulatePlaceholder) 46867 domClass.remove(this.getDomNode(), "placeholder"); 46868 46869 this.getDomNode().value = valToSet; 46870 } 46871 } 46872 }, 46873 templateString: "<div></div>", 46874 /** 46875 * Set an event handler. 46876 * @param {String} eventName The event to bind to. Only supported events are "change". 46877 * @param {function} functionRef The callback function to call. 46878 * @returns {void} 46879 */ 46880 on: function (eventName, functionRef) { 46881 var self = this; 46882 46883 if (eventName != "change") 46884 throw new Error("Supported events are: 'change'."); 46885 46886 this._onChange.push(functionRef); 46887 46888 }, 46889 /* 46890 * Make sure that this works when the control is focused and non-focused with an inputFormatter and without. When an inputFilter is specified, 46891 */ 46892 validate: function () 46893 { 46894 var value = this.getCandidateValue(); 46895 var ret; 46896 46897 ret = dpage.widgets.BaseWidget.validate(value, this.getModel().getMetadata(), this.getModel().getDisplayName()); 46898 46899 this.setValidationMessage(ret); 46900 46901 return ret; 46902 }, 46903 setValidationMessage: function (message) { 46904 46905 //call the base class. 46906 this.inherited(arguments); 46907 46908 domClass.remove(this._containerNode, "input-invalid"); 46909 46910 if (message != null) 46911 domClass.add(this._containerNode, "input-invalid"); 46912 }, 46913 _item_OnMouseEnter: function (newLookupItem) { 46914 46915 }, 46916 _item_OnMouseLeave: function (newLookupItem) { 46917 46918 } 46919 }); 46920}); 46921 46922}, 46923'jquery-ui/ui/datepicker':function(){ 46924/*! 46925 * jQuery UI Datepicker 1.11.2 46926 * http://jqueryui.com 46927 * 46928 * Copyright 2014 jQuery Foundation and other contributors 46929 * Released under the MIT license. 46930 * http://jquery.org/license 46931 * 46932 * http://api.jqueryui.com/datepicker/ 46933 */ 46934(function( factory ) { 46935 if ( typeof define === "function" && define.amd ) { 46936 46937 // AMD. Register as an anonymous module. 46938 define([ 46939 "jquery", 46940 "./core" 46941 ], factory ); 46942 } else { 46943 46944 // Browser globals 46945 factory( jQuery ); 46946 } 46947}(function( $ ) { 46948 46949$.extend($.ui, { datepicker: { version: "1.11.2" } }); 46950 46951var datepicker_instActive; 46952 46953function datepicker_getZindex( elem ) { 46954 var position, value; 46955 while ( elem.length && elem[ 0 ] !== document ) { 46956 // Ignore z-index if position is set to a value where z-index is ignored by the browser 46957 // This makes behavior of this function consistent across browsers 46958 // WebKit always returns auto if the element is positioned 46959 position = elem.css( "position" ); 46960 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 46961 // IE returns 0 when zIndex is not specified 46962 // other browsers return a string 46963 // we ignore the case of nested elements with an explicit value of 0 46964 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 46965 value = parseInt( elem.css( "zIndex" ), 10 ); 46966 if ( !isNaN( value ) && value !== 0 ) { 46967 return value; 46968 } 46969 } 46970 elem = elem.parent(); 46971 } 46972 46973 return 0; 46974} 46975/* Date picker manager.
46976 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 46977 Settings for (groups of) date pickers are maintained in an instance object, 46978 allowing multiple different settings on the same page. */ 46979 46980function Datepicker() { 46981 this._curInst = null; // The current instance in use 46982 this._keyEvent = false; // If the last event was a key event 46983 this._disabledInputs = []; // List of date picker inputs that have been disabled 46984 this._datepickerShowing = false; // True if the popup picker is showing , false if not 46985 this._inDialog = false; // True if showing within a "dialog", false if not 46986 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 46987 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 46988 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 46989 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 46990 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 46991 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 46992 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 46993 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 46994 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 46995 this.regional = []; // Available regional settings, indexed by language code 46996 this.regional[""] = { // Default regional settings 46997 closeText: "Done", // Display text for close link 46998 prevText: "Prev", // Display text for previous month link 46999 nextText: "Next", // Display text for next month link 47000 currentText: "Today", // Display text for current month link 47001 monthNames: ["January","February","March","April","May","June", 47002 "July","August","September","October","November","December"], // Names of months for drop-down and formatting 47003 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 47004 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 47005 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 47006 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday 47007 weekHeader: "Wk", // Column header for week of the year 47008 dateFormat: "mm/dd/yy", // See format options on parseDate 47009 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 47010 isRTL: false, // True if right-to-left language, false if left-to-right 47011 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 47012 yearSuffix: "" // Additional text to append to the year in the month headers 47013 }; 47014 this._defaults = { // Global defaults for all the date picker instances 47015 showOn: "focus", // "focus" for popup on focus, 47016 // "button" for trigger button, or "both" for either 47017 showAnim: "fadeIn", // Name of jQuery animation for popup 47018 showOptions: {}, // Options for enhanced animations 47019 defaultDate: null, // Used when field is blank: actual date, 47020 // +/-number for offset from today, null for today 47021 appendText: "", // Display text following the input box, e.g. showing the format 47022 buttonText: "...", // Text for trigger button 47023 buttonImage: "", // URL for trigger button image 47024 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 47025 hideIfNoPrevNext: false, // True to hide next/previous month links 47026 // if not applicable, false to just disable them 47027 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 47028 gotoCurrent: false, // True if today link goes back to current selection instead 47029 changeMonth: false, // True if month can be selected directly, false if only prev/next 47030 changeYear: false, // True if year can be selected directly, false if only prev/next 47031 yearRange: "c-10:c+10", // Range of years to display in drop-down, 47032 // either relative to today's year (-nn:+nn), relative to currently displayed year 47033 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
vendor: 27,281 bytes, lines 47034-47754
47034 showOtherMonths: false, // True to show dates in other months, false to leave blank 47035 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 47036 showWeek: false, // True to show week of the year, false to not show it 47037 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 47038 // takes a Date and returns the number of the week for it 47039 shortYearCutoff: "+10", // Short year values < this are in the current century, 47040 // > this are in the previous century, 47041 // string value starting with "+" for current year + value 47042 minDate: null, // The earliest selectable date, or null for no limit 47043 maxDate: null, // The latest selectable date, or null for no limit 47044 duration: "fast", // Duration of display/closure 47045 beforeShowDay: null, // Function that takes a date and returns an array with 47046 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 47047 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 47048 beforeShow: null, // Function that takes an input field and 47049 // returns a set of custom settings for the date picker 47050 onSelect: null, // Define a callback function when a date is selected 47051 onChangeMonthYear: null, // Define a callback function when the month or year is changed 47052 onClose: null, // Define a callback function when the datepicker is closed 47053 numberOfMonths: 1, // Number of months to show at a time 47054 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 47055 stepMonths: 1, // Number of months to step back/forward 47056 stepBigMonths: 12, // Number of months to step back/forward for the big links 47057 altField: "", // Selector for an alternate field to store selected dates into 47058 altFormat: "", // The date format to use for the alternate field 47059 constrainInput: true, // The input is constrained by the current date format 47060 showButtonPanel: false, // True to show button panel, false to not show it 47061 autoSize: false, // True to size the input for the date format, false to leave as is 47062 disabled: false // The initial disabled state 47063 }; 47064 $.extend(this._defaults, this.regional[""]); 47065 this.regional.en = $.extend( true, {}, this.regional[ "" ]); 47066 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); 47067 this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 47068} 47069 47070$.extend(Datepicker.prototype, { 47071 /* Class name added to elements to indicate already configured with a date picker. */ 47072 markerClassName: "hasDatepicker", 47073 47074 //Keep track of the maximum number of rows displayed (see #7043) 47075 maxRows: 4, 47076 47077 // TODO rename to "widget" when switching to widget factory 47078 _widgetDatepicker: function() { 47079 return this.dpDiv; 47080 }, 47081 47082 /* Override the default settings for all instances of the date picker. 47083 * @param settings object - the new settings to use as defaults (anonymous object) 47084 * @return the manager object 47085 */ 47086 setDefaults: function(settings) { 47087 datepicker_extendRemove(this._defaults, settings || {}); 47088 return this; 47089 }, 47090 47091 /* Attach the date picker to a jQuery selection. 47092 * @param target element - the target input field or division or span 47093 * @param settings object - the new settings to use for this date picker instance (anonymous) 47094 */ 47095 _attachDatepicker: function(target, settings) { 47096 var nodeName, inline, inst; 47097 nodeName = target.nodeName.toLowerCase(); 47098 inline = (nodeName === "div" || nodeName === "span"); 47099 if (!target.id) { 47100 this.uuid += 1; 47101 target.id = "dp" + this.uuid; 47102 } 47103 inst = this._newInst($(target), inline); 47104 inst.settings = $.extend({}, settings || {}); 47105 if (nodeName === "input") { 47106 this._connectDatepicker(target, inst); 47107 } else if (inline) { 47108 this._inlineDatepicker(target, inst); 47109 } 47110 }, 47111 47112 /* Create a new instance object. */ 47113 _newInst: function(target, inline) { 47114 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 47115 return {id: id, input: target, // associated target 47116 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 47117 drawMonth: 0, drawYear: 0, // month being drawn 47118 inline: inline, // is datepicker inline or not 47119 dpDiv: (!inline ? this.dpDiv : // presentation div 47120 datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; 47121 }, 47122 47123 /* Attach the date picker to an input field. */ 47124 _connectDatepicker: function(target, inst) { 47125 var input = $(target); 47126 inst.append = $([]); 47127 inst.trigger = $([]); 47128 if (input.hasClass(this.markerClassName)) { 47129 return; 47130 } 47131 this._attachments(input, inst); 47132 input.addClass(this.markerClassName).keydown(this._doKeyDown). 47133 keypress(this._doKeyPress).keyup(this._doKeyUp); 47134 this._autoSize(inst); 47135 $.data(target, "datepicker", inst); 47136 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 47137 if( inst.settings.disabled ) { 47138 this._disableDatepicker( target ); 47139 } 47140 }, 47141 47142 /* Make attachments based on settings. */ 47143 _attachments: function(input, inst) { 47144 var showOn, buttonText, buttonImage, 47145 appendText = this._get(inst, "appendText"), 47146 isRTL = this._get(inst, "isRTL"); 47147 47148 if (inst.append) { 47149 inst.append.remove(); 47150 } 47151 if (appendText) { 47152 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); 47153 input[isRTL ? "before" : "after"](inst.append); 47154 } 47155 47156 input.unbind("focus", this._showDatepicker); 47157 47158 if (inst.trigger) { 47159 inst.trigger.remove(); 47160 } 47161 47162 showOn = this._get(inst, "showOn"); 47163 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 47164 input.focus(this._showDatepicker); 47165 } 47166 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 47167 buttonText = this._get(inst, "buttonText"); 47168 buttonImage = this._get(inst, "buttonImage"); 47169 inst.trigger = $(this._get(inst, "buttonImageOnly") ? 47170 $("<img/>").addClass(this._triggerClass). 47171 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 47172 $("<button type='button'></button>").addClass(this._triggerClass). 47173 html(!buttonImage ? buttonText : $("<img/>").attr( 47174 { src:buttonImage, alt:buttonText, title:buttonText }))); 47175 input[isRTL ? "before" : "after"](inst.trigger); 47176 inst.trigger.click(function() { 47177 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 47178 $.datepicker._hideDatepicker(); 47179 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 47180 $.datepicker._hideDatepicker(); 47181 $.datepicker._showDatepicker(input[0]); 47182 } else { 47183 $.datepicker._showDatepicker(input[0]); 47184 } 47185 return false; 47186 }); 47187 } 47188 }, 47189 47190 /* Apply the maximum length for the date format. */ 47191 _autoSize: function(inst) { 47192 if (this._get(inst, "autoSize") && !inst.inline) { 47193 var findMax, max, maxI, i, 47194 date = new Date(2009, 12 - 1, 20), // Ensure double digits 47195 dateFormat = this._get(inst, "dateFormat"); 47196 47197 if (dateFormat.match(/[DM]/)) { 47198 findMax = function(names) { 47199 max = 0; 47200 maxI = 0; 47201 for (i = 0; i < names.length; i++) { 47202 if (names[i].length > max) { 47203 max = names[i].length; 47204 maxI = i; 47205 } 47206 } 47207 return maxI; 47208 }; 47209 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 47210 "monthNames" : "monthNamesShort")))); 47211 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 47212 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 47213 } 47214 inst.input.attr("size", this._formatDate(inst, date).length); 47215 } 47216 }, 47217 47218 /* Attach an inline date picker to a div. */ 47219 _inlineDatepicker: function(target, inst) { 47220 var divSpan = $(target); 47221 if (divSpan.hasClass(this.markerClassName)) { 47222 return; 47223 } 47224 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 47225 $.data(target, "datepicker", inst); 47226 this._setDate(inst, this._getDefaultDate(inst), true); 47227 this._updateDatepicker(inst); 47228 this._updateAlternate(inst); 47229 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 47230 if( inst.settings.disabled ) { 47231 this._disableDatepicker( target ); 47232 } 47233 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 47234 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 47235 inst.dpDiv.css( "display", "block" ); 47236 }, 47237 47238 /* Pop-up the date picker in a "dialog" box. 47239 * @param input element - ignored 47240 * @param date string or Date - the initial date to display 47241 * @param onSelect function - the function to call when a date is selected 47242 * @param settings object - update the dialog date picker instance's settings (anonymous object) 47243 * @param pos int[2] - coordinates for the dialog's position within the screen or 47244 * event - with x/y coordinates or 47245 * leave empty for default (screen centre) 47246 * @return the manager object 47247 */ 47248 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 47249 var id, browserWidth, browserHeight, scrollX, scrollY, 47250 inst = this._dialogInst; // internal instance 47251 47252 if (!inst) { 47253 this.uuid += 1; 47254 id = "dp" + this.uuid; 47255 this._dialogInput = $("<input type='text' id='" + id + 47256 "' style='position: absolute; top: -100px; width: 0px;'/>"); 47257 this._dialogInput.keydown(this._doKeyDown); 47258 $("body").append(this._dialogInput); 47259 inst = this._dialogInst = this._newInst(this._dialogInput, false); 47260 inst.settings = {}; 47261 $.data(this._dialogInput[0], "datepicker", inst); 47262 } 47263 datepicker_extendRemove(inst.settings, settings || {}); 47264 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 47265 this._dialogInput.val(date); 47266 47267 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 47268 if (!this._pos) { 47269 browserWidth = document.documentElement.clientWidth; 47270 browserHeight = document.documentElement.clientHeight; 47271 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 47272 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 47273 this._pos = // should use actual width/height below 47274 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 47275 } 47276 47277 // move input on screen for focus, but hidden behind dialog 47278 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 47279 inst.settings.onSelect = onSelect; 47280 this._inDialog = true; 47281 this.dpDiv.addClass(this._dialogClass); 47282 this._showDatepicker(this._dialogInput[0]); 47283 if ($.blockUI) { 47284 $.blockUI(this.dpDiv); 47285 } 47286 $.data(this._dialogInput[0], "datepicker", inst); 47287 return this; 47288 }, 47289 47290 /* Detach a datepicker from its control. 47291 * @param target element - the target input field or division or span 47292 */ 47293 _destroyDatepicker: function(target) { 47294 var nodeName, 47295 $target = $(target), 47296 inst = $.data(target, "datepicker"); 47297 47298 if (!$target.hasClass(this.markerClassName)) { 47299 return; 47300 } 47301 47302 nodeName = target.nodeName.toLowerCase(); 47303 $.removeData(target, "datepicker"); 47304 if (nodeName === "input") { 47305 inst.append.remove(); 47306 inst.trigger.remove(); 47307 $target.removeClass(this.markerClassName). 47308 unbind("focus", this._showDatepicker). 47309 unbind("keydown", this._doKeyDown). 47310 unbind("keypress", this._doKeyPress). 47311 unbind("keyup", this._doKeyUp); 47312 } else if (nodeName === "div" || nodeName === "span") { 47313 $target.removeClass(this.markerClassName).empty(); 47314 } 47315 }, 47316 47317 /* Enable the date picker to a jQuery selection. 47318 * @param target element - the target input field or division or span 47319 */ 47320 _enableDatepicker: function(target) { 47321 var nodeName, inline, 47322 $target = $(target), 47323 inst = $.data(target, "datepicker"); 47324 47325 if (!$target.hasClass(this.markerClassName)) { 47326 return; 47327 } 47328 47329 nodeName = target.nodeName.toLowerCase(); 47330 if (nodeName === "input") { 47331 target.disabled = false; 47332 inst.trigger.filter("button"). 47333 each(function() { this.disabled = false; }).end(). 47334 filter("img").css({opacity: "1.0", cursor: ""}); 47335 } else if (nodeName === "div" || nodeName === "span") { 47336 inline = $target.children("." + this._inlineClass); 47337 inline.children().removeClass("ui-state-disabled"); 47338 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 47339 prop("disabled", false); 47340 } 47341 this._disabledInputs = $.map(this._disabledInputs, 47342 function(value) { return (value === target ? null : value); }); // delete entry 47343 }, 47344 47345 /* Disable the date picker to a jQuery selection. 47346 * @param target element - the target input field or division or span 47347 */ 47348 _disableDatepicker: function(target) { 47349 var nodeName, inline, 47350 $target = $(target), 47351 inst = $.data(target, "datepicker"); 47352 47353 if (!$target.hasClass(this.markerClassName)) { 47354 return; 47355 } 47356 47357 nodeName = target.nodeName.toLowerCase(); 47358 if (nodeName === "input") { 47359 target.disabled = true; 47360 inst.trigger.filter("button"). 47361 each(function() { this.disabled = true; }).end(). 47362 filter("img").css({opacity: "0.5", cursor: "default"}); 47363 } else if (nodeName === "div" || nodeName === "span") { 47364 inline = $target.children("." + this._inlineClass); 47365 inline.children().addClass("ui-state-disabled"); 47366 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 47367 prop("disabled", true); 47368 } 47369 this._disabledInputs = $.map(this._disabledInputs, 47370 function(value) { return (value === target ? null : value); }); // delete entry 47371 this._disabledInputs[this._disabledInputs.length] = target; 47372 }, 47373 47374 /* Is the first field in a jQuery collection disabled as a datepicker? 47375 * @param target element - the target input field or division or span 47376 * @return boolean - true if disabled, false if enabled 47377 */ 47378 _isDisabledDatepicker: function(target) { 47379 if (!target) { 47380 return false; 47381 } 47382 for (var i = 0; i < this._disabledInputs.length; i++) { 47383 if (this._disabledInputs[i] === target) { 47384 return true; 47385 } 47386 } 47387 return false; 47388 }, 47389 47390 /* Retrieve the instance data for the target control. 47391 * @param target element - the target input field or division or span 47392 * @return object - the associated instance data 47393 * @throws error if a jQuery problem getting data 47394 */ 47395 _getInst: function(target) { 47396 try { 47397 return $.data(target, "datepicker"); 47398 } 47399 catch (err) { 47400 throw "Missing instance data for this datepicker"; 47401 } 47402 }, 47403 47404 /* Update or retrieve the settings for a date picker attached to an input field or division. 47405 * @param target element - the target input field or division or span 47406 * @param name object - the new settings to update or 47407 * string - the name of the setting to change or retrieve, 47408 * when retrieving also "all" for all instance settings or 47409 * "defaults" for all global defaults 47410 * @param value any - the new value for the setting 47411 * (omit if above is an object or to retrieve a value) 47412 */ 47413 _optionDatepicker: function(target, name, value) { 47414 var settings, date, minDate, maxDate, 47415 inst = this._getInst(target); 47416 47417 if (arguments.length === 2 && typeof name === "string") { 47418 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 47419 (inst ? (name === "all" ? $.extend({}, inst.settings) : 47420 this._get(inst, name)) : null)); 47421 } 47422 47423 settings = name || {}; 47424 if (typeof name === "string") { 47425 settings = {}; 47426 settings[name] = value; 47427 } 47428 47429 if (inst) { 47430 if (this._curInst === inst) { 47431 this._hideDatepicker(); 47432 } 47433 47434 date = this._getDateDatepicker(target, true); 47435 minDate = this._getMinMaxDate(inst, "min"); 47436 maxDate = this._getMinMaxDate(inst, "max"); 47437 datepicker_extendRemove(inst.settings, settings); 47438 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 47439 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 47440 inst.settings.minDate = this._formatDate(inst, minDate); 47441 } 47442 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 47443 inst.settings.maxDate = this._formatDate(inst, maxDate); 47444 } 47445 if ( "disabled" in settings ) { 47446 if ( settings.disabled ) { 47447 this._disableDatepicker(target); 47448 } else { 47449 this._enableDatepicker(target); 47450 } 47451 } 47452 this._attachments($(target), inst); 47453 this._autoSize(inst); 47454 this._setDate(inst, date); 47455 this._updateAlternate(inst); 47456 this._updateDatepicker(inst); 47457 } 47458 }, 47459 47460 // change method deprecated 47461 _changeDatepicker: function(target, name, value) { 47462 this._optionDatepicker(target, name, value); 47463 }, 47464 47465 /* Redraw the date picker attached to an input field or division. 47466 * @param target element - the target input field or division or span 47467 */ 47468 _refreshDatepicker: function(target) { 47469 var inst = this._getInst(target); 47470 if (inst) { 47471 this._updateDatepicker(inst); 47472 } 47473 }, 47474 47475 /* Set the dates for a jQuery selection. 47476 * @param target element - the target input field or division or span 47477 * @param date Date - the new date 47478 */ 47479 _setDateDatepicker: function(target, date) { 47480 var inst = this._getInst(target); 47481 if (inst) { 47482 this._setDate(inst, date); 47483 this._updateDatepicker(inst); 47484 this._updateAlternate(inst); 47485 } 47486 }, 47487 47488 /* Get the date(s) for the first entry in a jQuery selection. 47489 * @param target element - the target input field or division or span 47490 * @param noDefault boolean - true if no default date is to be used 47491 * @return Date - the current date 47492 */ 47493 _getDateDatepicker: function(target, noDefault) { 47494 var inst = this._getInst(target); 47495 if (inst && !inst.inline) { 47496 this._setDateFromField(inst, noDefault); 47497 } 47498 return (inst ? this._getDate(inst) : null); 47499 }, 47500 47501 /* Handle keystrokes. */ 47502 _doKeyDown: function(event) { 47503 var onSelect, dateStr, sel, 47504 inst = $.datepicker._getInst(event.target), 47505 handled = true, 47506 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 47507 47508 inst._keyEvent = true; 47509 if ($.datepicker._datepickerShowing) { 47510 switch (event.keyCode) { 47511 case 9: $.datepicker._hideDatepicker(); 47512 handled = false; 47513 break; // hide on tab out 47514 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 47515 $.datepicker._currentClass + ")", inst.dpDiv); 47516 if (sel[0]) { 47517 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 47518 } 47519 47520 onSelect = $.datepicker._get(inst, "onSelect"); 47521 if (onSelect) { 47522 dateStr = $.datepicker._formatDate(inst); 47523 47524 // trigger custom callback 47525 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 47526 } else { 47527 $.datepicker._hideDatepicker(); 47528 } 47529 47530 return false; // don't submit the form 47531 case 27: $.datepicker._hideDatepicker(); 47532 break; // hide on escape 47533 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 47534 -$.datepicker._get(inst, "stepBigMonths") : 47535 -$.datepicker._get(inst, "stepMonths")), "M"); 47536 break; // previous month/year on page up/+ ctrl 47537 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 47538 +$.datepicker._get(inst, "stepBigMonths") : 47539 +$.datepicker._get(inst, "stepMonths")), "M"); 47540 break; // next month/year on page down/+ ctrl 47541 case 35: if (event.ctrlKey || event.metaKey) { 47542 $.datepicker._clearDate(event.target); 47543 } 47544 handled = event.ctrlKey || event.metaKey; 47545 break; // clear on ctrl or command +end 47546 case 36: if (event.ctrlKey || event.metaKey) { 47547 $.datepicker._gotoToday(event.target); 47548 } 47549 handled = event.ctrlKey || event.metaKey; 47550 break; // current on ctrl or command +home 47551 case 37: if (event.ctrlKey || event.metaKey) { 47552 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 47553 } 47554 handled = event.ctrlKey || event.metaKey; 47555 // -1 day on ctrl or command +left 47556 if (event.originalEvent.altKey) { 47557 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 47558 -$.datepicker._get(inst, "stepBigMonths") : 47559 -$.datepicker._get(inst, "stepMonths")), "M"); 47560 } 47561 // next month/year on alt +left on Mac 47562 break; 47563 case 38: if (event.ctrlKey || event.metaKey) { 47564 $.datepicker._adjustDate(event.target, -7, "D"); 47565 } 47566 handled = event.ctrlKey || event.metaKey; 47567 break; // -1 week on ctrl or command +up 47568 case 39: if (event.ctrlKey || event.metaKey) { 47569 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 47570 } 47571 handled = event.ctrlKey || event.metaKey; 47572 // +1 day on ctrl or command +right 47573 if (event.originalEvent.altKey) { 47574 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 47575 +$.datepicker._get(inst, "stepBigMonths") : 47576 +$.datepicker._get(inst, "stepMonths")), "M"); 47577 } 47578 // next month/year on alt +right 47579 break; 47580 case 40: if (event.ctrlKey || event.metaKey) { 47581 $.datepicker._adjustDate(event.target, +7, "D"); 47582 } 47583 handled = event.ctrlKey || event.metaKey; 47584 break; // +1 week on ctrl or command +down 47585 default: handled = false; 47586 } 47587 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 47588 $.datepicker._showDatepicker(this); 47589 } else { 47590 handled = false; 47591 } 47592 47593 if (handled) { 47594 event.preventDefault(); 47595 event.stopPropagation(); 47596 } 47597 }, 47598 47599 /* Filter entered characters - based on date format. */ 47600 _doKeyPress: function(event) { 47601 var chars, chr, 47602 inst = $.datepicker._getInst(event.target); 47603 47604 if ($.datepicker._get(inst, "constrainInput")) { 47605 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 47606 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 47607 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 47608 } 47609 }, 47610 47611 /* Synchronise manual entry and field/alternate field. */ 47612 _doKeyUp: function(event) { 47613 var date, 47614 inst = $.datepicker._getInst(event.target); 47615 47616 if (inst.input.val() !== inst.lastVal) { 47617 try { 47618 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 47619 (inst.input ? inst.input.val() : null), 47620 $.datepicker._getFormatConfig(inst)); 47621 47622 if (date) { // only if valid 47623 $.datepicker._setDateFromField(inst); 47624 $.datepicker._updateAlternate(inst); 47625 $.datepicker._updateDatepicker(inst); 47626 } 47627 } 47628 catch (err) { 47629 } 47630 } 47631 return true; 47632 }, 47633 47634 /* Pop-up the date picker for a given input field. 47635 * If false returned from beforeShow event handler do not show. 47636 * @param input element - the input field attached to the date picker or 47637 * event - if triggered by focus 47638 */ 47639 _showDatepicker: function(input) { 47640 input = input.target || input; 47641 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 47642 input = $("input", input.parentNode)[0]; 47643 } 47644 47645 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 47646 return; 47647 } 47648 47649 var inst, beforeShow, beforeShowSettings, isFixed, 47650 offset, showAnim, duration; 47651 47652 inst = $.datepicker._getInst(input); 47653 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 47654 $.datepicker._curInst.dpDiv.stop(true, true); 47655 if ( inst && $.datepicker._datepickerShowing ) { 47656 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 47657 } 47658 } 47659 47660 beforeShow = $.datepicker._get(inst, "beforeShow"); 47661 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 47662 if(beforeShowSettings === false){ 47663 return; 47664 } 47665 datepicker_extendRemove(inst.settings, beforeShowSettings); 47666 47667 inst.lastVal = null; 47668 $.datepicker._lastInput = input; 47669 $.datepicker._setDateFromField(inst); 47670 47671 if ($.datepicker._inDialog) { // hide cursor 47672 input.value = ""; 47673 } 47674 if (!$.datepicker._pos) { // position below input 47675 $.datepicker._pos = $.datepicker._findPos(input); 47676 $.datepicker._pos[1] += input.offsetHeight; // add the height 47677 } 47678 47679 isFixed = false; 47680 $(input).parents().each(function() { 47681 isFixed |= $(this).css("position") === "fixed"; 47682 return !isFixed; 47683 }); 47684 47685 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 47686 $.datepicker._pos = null; 47687 //to avoid flashes on Firefox 47688 inst.dpDiv.empty(); 47689 // determine sizing offscreen 47690 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); 47691 $.datepicker._updateDatepicker(inst); 47692 // fix width for dynamic number of date pickers 47693 // and adjust position before showing 47694 offset = $.datepicker._checkOffset(inst, offset, isFixed); 47695 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 47696 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 47697 left: offset.left + "px", top: offset.top + "px"}); 47698 47699 if (!inst.inline) { 47700 showAnim = $.datepicker._get(inst, "showAnim"); 47701 duration = $.datepicker._get(inst, "duration"); 47702 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); 47703 $.datepicker._datepickerShowing = true; 47704 47705 if ( $.effects && $.effects.effect[ showAnim ] ) { 47706 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 47707 } else { 47708 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 47709 } 47710 47711 if ( $.datepicker._shouldFocusInput( inst ) ) { 47712 inst.input.focus(); 47713 } 47714 47715 $.datepicker._curInst = inst; 47716 } 47717 }, 47718 47719 /* Generate the date picker content. */ 47720 _updateDatepicker: function(inst) { 47721 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 47722 datepicker_instActive = inst; // for delegate hover events 47723 inst.dpDiv.empty().append(this._generateHTML(inst)); 47724 this._attachHandlers(inst); 47725 47726 var origyearshtml, 47727 numMonths = this._getNumberOfMonths(inst), 47728 cols = numMonths[1], 47729 width = 17, 47730 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ); 47731 47732 if ( activeCell.length > 0 ) { 47733 datepicker_handleMouseover.apply( activeCell.get( 0 ) ); 47734 } 47735 47736 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 47737 if (cols > 1) { 47738 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 47739 } 47740 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 47741 "Class"]("ui-datepicker-multi"); 47742 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 47743 "Class"]("ui-datepicker-rtl"); 47744 47745 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 47746 inst.input.focus(); 47747 } 47748 47749 // deffered render of the years select (to avoid flashes on Firefox) 47750 if( inst.yearshtml ){ 47751 origyearshtml = inst.yearshtml; 47752 setTimeout(function(){ 47753 //assure that inst.yearshtml didn't change. 47754 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
vendor: 5,457 bytes, lines 47755-47911
47755 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); 47756 } 47757 origyearshtml = inst.yearshtml = null; 47758 }, 0); 47759 } 47760 }, 47761 47762 // #6694 - don't focus the input if it's already focused 47763 // this breaks the change event in IE 47764 // Support: IE and jQuery <1.9 47765 _shouldFocusInput: function( inst ) { 47766 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); 47767 }, 47768 47769 /* Check positioning to remain on screen. */ 47770 _checkOffset: function(inst, offset, isFixed) { 47771 var dpWidth = inst.dpDiv.outerWidth(), 47772 dpHeight = inst.dpDiv.outerHeight(), 47773 inputWidth = inst.input ? inst.input.outerWidth() : 0, 47774 inputHeight = inst.input ? inst.input.outerHeight() : 0, 47775 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 47776 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 47777 47778 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 47779 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 47780 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 47781 47782 // now check if datepicker is showing outside window viewport - move to a better place if so. 47783 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 47784 Math.abs(offset.left + dpWidth - viewWidth) : 0); 47785 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 47786 Math.abs(dpHeight + inputHeight) : 0); 47787 47788 return offset; 47789 }, 47790 47791 /* Find an object's position on the screen. */ 47792 _findPos: function(obj) { 47793 var position, 47794 inst = this._getInst(obj), 47795 isRTL = this._get(inst, "isRTL"); 47796 47797 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { 47798 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 47799 } 47800 47801 position = $(obj).offset(); 47802 return [position.left, position.top]; 47803 }, 47804 47805 /* Hide the date picker from view. 47806 * @param input element - the input field attached to the date picker 47807 */ 47808 _hideDatepicker: function(input) { 47809 var showAnim, duration, postProcess, onClose, 47810 inst = this._curInst; 47811 47812 if (!inst || (input && inst !== $.data(input, "datepicker"))) { 47813 return; 47814 } 47815 47816 if (this._datepickerShowing) { 47817 showAnim = this._get(inst, "showAnim"); 47818 duration = this._get(inst, "duration"); 47819 postProcess = function() { 47820 $.datepicker._tidyDialog(inst); 47821 }; 47822 47823 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 47824 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 47825 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 47826 } else { 47827 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 47828 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 47829 } 47830 47831 if (!showAnim) { 47832 postProcess(); 47833 } 47834 this._datepickerShowing = false; 47835 47836 onClose = this._get(inst, "onClose"); 47837 if (onClose) { 47838 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 47839 } 47840 47841 this._lastInput = null; 47842 if (this._inDialog) { 47843 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 47844 if ($.blockUI) { 47845 $.unblockUI(); 47846 $("body").append(this.dpDiv); 47847 } 47848 } 47849 this._inDialog = false; 47850 } 47851 }, 47852 47853 /* Tidy up after a dialog display. */ 47854 _tidyDialog: function(inst) { 47855 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); 47856 }, 47857 47858 /* Close date picker if clicked elsewhere. */ 47859 _checkExternalClick: function(event) { 47860 if (!$.datepicker._curInst) { 47861 return; 47862 } 47863 47864 var $target = $(event.target), 47865 inst = $.datepicker._getInst($target[0]); 47866 47867 if ( ( ( $target[0].id !== $.datepicker._mainDivId && 47868 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 47869 !$target.hasClass($.datepicker.markerClassName) && 47870 !$target.closest("." + $.datepicker._triggerClass).length && 47871 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 47872 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { 47873 $.datepicker._hideDatepicker(); 47874 } 47875 }, 47876 47877 /* Adjust one of the date sub-fields. */ 47878 _adjustDate: function(id, offset, period) { 47879 var target = $(id), 47880 inst = this._getInst(target[0]); 47881 47882 if (this._isDisabledDatepicker(target[0])) { 47883 return; 47884 } 47885 this._adjustInstDate(inst, offset + 47886 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning 47887 period); 47888 this._updateDatepicker(inst); 47889 }, 47890 47891 /* Action for current link. */ 47892 _gotoToday: function(id) { 47893 var date, 47894 target = $(id), 47895 inst = this._getInst(target[0]); 47896 47897 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 47898 inst.selectedDay = inst.currentDay; 47899 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 47900 inst.drawYear = inst.selectedYear = inst.currentYear; 47901 } else { 47902 date = new Date(); 47903 inst.selectedDay = date.getDate(); 47904 inst.drawMonth = inst.selectedMonth = date.getMonth(); 47905 inst.drawYear = inst.selectedYear = date.getFullYear(); 47906 } 47907 this._notifyChange(inst); 47908 this._adjustDate(target); 47909 }, 47910 47911 /* Action for selecting a new month/year. */
vendor: 45,146 bytes, lines 47912-49069
47912 _selectMonthYear: function(id, select, period) { 47913 var target = $(id), 47914 inst = this._getInst(target[0]); 47915 47916 inst["selected" + (period === "M" ? "Month" : "Year")] = 47917 inst["draw" + (period === "M" ? "Month" : "Year")] = 47918 parseInt(select.options[select.selectedIndex].value,10); 47919 47920 this._notifyChange(inst); 47921 this._adjustDate(target); 47922 }, 47923 47924 /* Action for selecting a day. */ 47925 _selectDay: function(id, month, year, td) { 47926 var inst, 47927 target = $(id); 47928 47929 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 47930 return; 47931 } 47932 47933 inst = this._getInst(target[0]); 47934 inst.selectedDay = inst.currentDay = $("a", td).html(); 47935 inst.selectedMonth = inst.currentMonth = month; 47936 inst.selectedYear = inst.currentYear = year; 47937 this._selectDate(id, this._formatDate(inst, 47938 inst.currentDay, inst.currentMonth, inst.currentYear)); 47939 }, 47940 47941 /* Erase the input field and hide the date picker. */ 47942 _clearDate: function(id) { 47943 var target = $(id); 47944 this._selectDate(target, ""); 47945 }, 47946 47947 /* Update the input field with the selected date. */ 47948 _selectDate: function(id, dateStr) { 47949 var onSelect, 47950 target = $(id), 47951 inst = this._getInst(target[0]); 47952 47953 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 47954 if (inst.input) { 47955 inst.input.val(dateStr); 47956 } 47957 this._updateAlternate(inst); 47958 47959 onSelect = this._get(inst, "onSelect"); 47960 if (onSelect) { 47961 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 47962 } else if (inst.input) { 47963 inst.input.trigger("change"); // fire the change event 47964 } 47965 47966 if (inst.inline){ 47967 this._updateDatepicker(inst); 47968 } else { 47969 this._hideDatepicker(); 47970 this._lastInput = inst.input[0]; 47971 if (typeof(inst.input[0]) !== "object") { 47972 inst.input.focus(); // restore focus 47973 } 47974 this._lastInput = null; 47975 } 47976 }, 47977 47978 /* Update any alternate field to synchronise with the main field. */ 47979 _updateAlternate: function(inst) { 47980 var altFormat, date, dateStr, 47981 altField = this._get(inst, "altField"); 47982 47983 if (altField) { // update alternate field too 47984 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 47985 date = this._getDate(inst); 47986 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 47987 $(altField).each(function() { $(this).val(dateStr); }); 47988 } 47989 }, 47990 47991 /* Set as beforeShowDay function to prevent selection of weekends. 47992 * @param date Date - the date to customise 47993 * @return [boolean, string] - is this date selectable?, what is its CSS class? 47994 */ 47995 noWeekends: function(date) { 47996 var day = date.getDay(); 47997 return [(day > 0 && day < 6), ""]; 47998 }, 47999 48000 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 48001 * @param date Date - the date to get the week for 48002 * @return number - the number of the week within the year that contains this date 48003 */ 48004 iso8601Week: function(date) { 48005 var time, 48006 checkDate = new Date(date.getTime()); 48007 48008 // Find Thursday of this week starting on Monday 48009 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 48010 48011 time = checkDate.getTime(); 48012 checkDate.setMonth(0); // Compare with Jan 1 48013 checkDate.setDate(1); 48014 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 48015 }, 48016 48017 /* Parse a string value into a date object. 48018 * See formatDate below for the possible formats. 48019 * 48020 * @param format string - the expected format of the date 48021 * @param value string - the date in the above format 48022 * @param settings Object - attributes include: 48023 * shortYearCutoff number - the cutoff year for determining the century (optional) 48024 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 48025 * dayNames string[7] - names of the days from Sunday (optional) 48026 * monthNamesShort string[12] - abbreviated names of the months (optional) 48027 * monthNames string[12] - names of the months (optional) 48028 * @return Date - the extracted date value or null if value is blank 48029 */ 48030 parseDate: function (format, value, settings) { 48031 if (format == null || value == null) { 48032 throw "Invalid arguments"; 48033 } 48034 48035 value = (typeof value === "object" ? value.toString() : value + ""); 48036 if (value === "") { 48037 return null; 48038 } 48039 48040 var iFormat, dim, extra, 48041 iValue = 0, 48042 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 48043 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 48044 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 48045 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 48046 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 48047 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 48048 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 48049 year = -1, 48050 month = -1, 48051 day = -1, 48052 doy = -1, 48053 literal = false, 48054 date, 48055 // Check whether a format character is doubled 48056 lookAhead = function(match) { 48057 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 48058 if (matches) { 48059 iFormat++; 48060 } 48061 return matches; 48062 }, 48063 // Extract a number from the string value 48064 getNumber = function(match) { 48065 var isDoubled = lookAhead(match), 48066 size = (match === "@" ? 14 : (match === "!" ? 20 : 48067 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 48068 minSize = (match === "y" ? size : 1), 48069 digits = new RegExp("^\\d{" + minSize + "," + size + "}"), 48070 num = value.substring(iValue).match(digits); 48071 if (!num) { 48072 throw "Missing number at position " + iValue; 48073 } 48074 iValue += num[0].length; 48075 return parseInt(num[0], 10); 48076 }, 48077 // Extract a name from the string value and convert to an index 48078 getName = function(match, shortNames, longNames) { 48079 var index = -1, 48080 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 48081 return [ [k, v] ]; 48082 }).sort(function (a, b) { 48083 return -(a[1].length - b[1].length); 48084 }); 48085 48086 $.each(names, function (i, pair) { 48087 var name = pair[1]; 48088 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 48089 index = pair[0]; 48090 iValue += name.length; 48091 return false; 48092 } 48093 }); 48094 if (index !== -1) { 48095 return index + 1; 48096 } else { 48097 throw "Unknown name at position " + iValue; 48098 } 48099 }, 48100 // Confirm that a literal character matches the string value 48101 checkLiteral = function() { 48102 if (value.charAt(iValue) !== format.charAt(iFormat)) { 48103 throw "Unexpected literal at position " + iValue; 48104 } 48105 iValue++; 48106 }; 48107 48108 for (iFormat = 0; iFormat < format.length; iFormat++) { 48109 if (literal) { 48110 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 48111 literal = false; 48112 } else { 48113 checkLiteral(); 48114 } 48115 } else { 48116 switch (format.charAt(iFormat)) { 48117 case "d": 48118 day = getNumber("d"); 48119 break; 48120 case "D": 48121 getName("D", dayNamesShort, dayNames); 48122 break; 48123 case "o": 48124 doy = getNumber("o"); 48125 break; 48126 case "m": 48127 month = getNumber("m"); 48128 break; 48129 case "M": 48130 month = getName("M", monthNamesShort, monthNames); 48131 break; 48132 case "y": 48133 year = getNumber("y"); 48134 break; 48135 case "@": 48136 date = new Date(getNumber("@")); 48137 year = date.getFullYear(); 48138 month = date.getMonth() + 1; 48139 day = date.getDate(); 48140 break; 48141 case "!": 48142 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 48143 year = date.getFullYear(); 48144 month = date.getMonth() + 1; 48145 day = date.getDate(); 48146 break; 48147 case "'": 48148 if (lookAhead("'")){ 48149 checkLiteral(); 48150 } else { 48151 literal = true; 48152 } 48153 break; 48154 default: 48155 checkLiteral(); 48156 } 48157 } 48158 } 48159 48160 if (iValue < value.length){ 48161 extra = value.substr(iValue); 48162 if (!/^\s+/.test(extra)) { 48163 throw "Extra/unparsed characters found in date: " + extra; 48164 } 48165 } 48166 48167 if (year === -1) { 48168 year = new Date().getFullYear(); 48169 } else if (year < 100) { 48170 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 48171 (year <= shortYearCutoff ? 0 : -100); 48172 } 48173 48174 if (doy > -1) { 48175 month = 1; 48176 day = doy; 48177 do { 48178 dim = this._getDaysInMonth(year, month - 1); 48179 if (day <= dim) { 48180 break; 48181 } 48182 month++; 48183 day -= dim; 48184 } while (true); 48185 } 48186 48187 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 48188 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 48189 throw "Invalid date"; // E.g. 31/02/00 48190 } 48191 return date; 48192 }, 48193 48194 /* Standard date formats. */ 48195 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 48196 COOKIE: "D, dd M yy", 48197 ISO_8601: "yy-mm-dd", 48198 RFC_822: "D, d M y", 48199 RFC_850: "DD, dd-M-y", 48200 RFC_1036: "D, d M y", 48201 RFC_1123: "D, d M yy", 48202 RFC_2822: "D, d M yy", 48203 RSS: "D, d M y", // RFC 822 48204 TICKS: "!", 48205 TIMESTAMP: "@", 48206 W3C: "yy-mm-dd", // ISO 8601 48207 48208 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 48209 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 48210 48211 /* Format a date object into a string value. 48212 * The format can be combinations of the following: 48213 * d - day of month (no leading zero) 48214 * dd - day of month (two digit) 48215 * o - day of year (no leading zeros) 48216 * oo - day of year (three digit) 48217 * D - day name short 48218 * DD - day name long 48219 * m - month of year (no leading zero) 48220 * mm - month of year (two digit) 48221 * M - month name short 48222 * MM - month name long 48223 * y - year (two digit) 48224 * yy - year (four digit) 48225 * @ - Unix timestamp (ms since 01/01/1970) 48226 * ! - Windows ticks (100ns since 01/01/0001) 48227 * "..." - literal text 48228 * '' - single quote 48229 * 48230 * @param format string - the desired format of the date 48231 * @param date Date - the date value to format 48232 * @param settings Object - attributes include: 48233 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 48234 * dayNames string[7] - names of the days from Sunday (optional) 48235 * monthNamesShort string[12] - abbreviated names of the months (optional) 48236 * monthNames string[12] - names of the months (optional) 48237 * @return string - the date in the above format 48238 */ 48239 formatDate: function (format, date, settings) { 48240 if (!date) { 48241 return ""; 48242 } 48243 48244 var iFormat, 48245 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 48246 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 48247 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 48248 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 48249 // Check whether a format character is doubled 48250 lookAhead = function(match) { 48251 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 48252 if (matches) { 48253 iFormat++; 48254 } 48255 return matches; 48256 }, 48257 // Format a number, with leading zero if necessary 48258 formatNumber = function(match, value, len) { 48259 var num = "" + value; 48260 if (lookAhead(match)) { 48261 while (num.length < len) { 48262 num = "0" + num; 48263 } 48264 } 48265 return num; 48266 }, 48267 // Format a name, short or long as requested 48268 formatName = function(match, value, shortNames, longNames) { 48269 return (lookAhead(match) ? longNames[value] : shortNames[value]); 48270 }, 48271 output = "", 48272 literal = false; 48273 48274 if (date) { 48275 for (iFormat = 0; iFormat < format.length; iFormat++) { 48276 if (literal) { 48277 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 48278 literal = false; 48279 } else { 48280 output += format.charAt(iFormat); 48281 } 48282 } else { 48283 switch (format.charAt(iFormat)) { 48284 case "d": 48285 output += formatNumber("d", date.getDate(), 2); 48286 break; 48287 case "D": 48288 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 48289 break; 48290 case "o": 48291 output += formatNumber("o", 48292 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 48293 break; 48294 case "m": 48295 output += formatNumber("m", date.getMonth() + 1, 2); 48296 break; 48297 case "M": 48298 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 48299 break; 48300 case "y": 48301 output += (lookAhead("y") ? date.getFullYear() : 48302 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); 48303 break; 48304 case "@": 48305 output += date.getTime(); 48306 break; 48307 case "!": 48308 output += date.getTime() * 10000 + this._ticksTo1970; 48309 break; 48310 case "'": 48311 if (lookAhead("'")) { 48312 output += "'"; 48313 } else { 48314 literal = true; 48315 } 48316 break; 48317 default: 48318 output += format.charAt(iFormat); 48319 } 48320 } 48321 } 48322 } 48323 return output; 48324 }, 48325 48326 /* Extract all possible characters from the date format. */ 48327 _possibleChars: function (format) { 48328 var iFormat, 48329 chars = "", 48330 literal = false, 48331 // Check whether a format character is doubled 48332 lookAhead = function(match) { 48333 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 48334 if (matches) { 48335 iFormat++; 48336 } 48337 return matches; 48338 }; 48339 48340 for (iFormat = 0; iFormat < format.length; iFormat++) { 48341 if (literal) { 48342 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 48343 literal = false; 48344 } else { 48345 chars += format.charAt(iFormat); 48346 } 48347 } else { 48348 switch (format.charAt(iFormat)) { 48349 case "d": case "m": case "y": case "@": 48350 chars += "0123456789"; 48351 break; 48352 case "D": case "M": 48353 return null; // Accept anything 48354 case "'": 48355 if (lookAhead("'")) { 48356 chars += "'"; 48357 } else { 48358 literal = true; 48359 } 48360 break; 48361 default: 48362 chars += format.charAt(iFormat); 48363 } 48364 } 48365 } 48366 return chars; 48367 }, 48368 48369 /* Get a setting value, defaulting if necessary. */ 48370 _get: function(inst, name) { 48371 return inst.settings[name] !== undefined ? 48372 inst.settings[name] : this._defaults[name]; 48373 }, 48374 48375 /* Parse existing date and initialise date picker. */ 48376 _setDateFromField: function(inst, noDefault) { 48377 if (inst.input.val() === inst.lastVal) { 48378 return; 48379 } 48380 48381 var dateFormat = this._get(inst, "dateFormat"), 48382 dates = inst.lastVal = inst.input ? inst.input.val() : null, 48383 defaultDate = this._getDefaultDate(inst), 48384 date = defaultDate, 48385 settings = this._getFormatConfig(inst); 48386 48387 try { 48388 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 48389 } catch (event) { 48390 dates = (noDefault ? "" : dates); 48391 } 48392 inst.selectedDay = date.getDate(); 48393 inst.drawMonth = inst.selectedMonth = date.getMonth(); 48394 inst.drawYear = inst.selectedYear = date.getFullYear(); 48395 inst.currentDay = (dates ? date.getDate() : 0); 48396 inst.currentMonth = (dates ? date.getMonth() : 0); 48397 inst.currentYear = (dates ? date.getFullYear() : 0); 48398 this._adjustInstDate(inst); 48399 }, 48400 48401 /* Retrieve the default date shown on opening. */ 48402 _getDefaultDate: function(inst) { 48403 return this._restrictMinMax(inst, 48404 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 48405 }, 48406 48407 /* A date may be specified as an exact value or a relative one. */ 48408 _determineDate: function(inst, date, defaultDate) { 48409 var offsetNumeric = function(offset) { 48410 var date = new Date(); 48411 date.setDate(date.getDate() + offset); 48412 return date; 48413 }, 48414 offsetString = function(offset) { 48415 try { 48416 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 48417 offset, $.datepicker._getFormatConfig(inst)); 48418 } 48419 catch (e) { 48420 // Ignore 48421 } 48422 48423 var date = (offset.toLowerCase().match(/^c/) ? 48424 $.datepicker._getDate(inst) : null) || new Date(), 48425 year = date.getFullYear(), 48426 month = date.getMonth(), 48427 day = date.getDate(), 48428 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 48429 matches = pattern.exec(offset); 48430 48431 while (matches) { 48432 switch (matches[2] || "d") { 48433 case "d" : case "D" : 48434 day += parseInt(matches[1],10); break; 48435 case "w" : case "W" : 48436 day += parseInt(matches[1],10) * 7; break; 48437 case "m" : case "M" : 48438 month += parseInt(matches[1],10); 48439 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 48440 break; 48441 case "y": case "Y" : 48442 year += parseInt(matches[1],10); 48443 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 48444 break; 48445 } 48446 matches = pattern.exec(offset); 48447 } 48448 return new Date(year, month, day); 48449 }, 48450 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 48451 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 48452 48453 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 48454 if (newDate) { 48455 newDate.setHours(0); 48456 newDate.setMinutes(0); 48457 newDate.setSeconds(0); 48458 newDate.setMilliseconds(0); 48459 } 48460 return this._daylightSavingAdjust(newDate); 48461 }, 48462 48463 /* Handle switch to/from daylight saving. 48464 * Hours may be non-zero on daylight saving cut-over: 48465 * > 12 when midnight changeover, but then cannot generate 48466 * midnight datetime, so jump to 1AM, otherwise reset. 48467 * @param date (Date) the date to check 48468 * @return (Date) the corrected date 48469 */ 48470 _daylightSavingAdjust: function(date) { 48471 if (!date) { 48472 return null; 48473 } 48474 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 48475 return date; 48476 }, 48477 48478 /* Set the date(s) directly. */ 48479 _setDate: function(inst, date, noChange) { 48480 var clear = !date, 48481 origMonth = inst.selectedMonth, 48482 origYear = inst.selectedYear, 48483 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 48484 48485 inst.selectedDay = inst.currentDay = newDate.getDate(); 48486 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 48487 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 48488 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 48489 this._notifyChange(inst); 48490 } 48491 this._adjustInstDate(inst); 48492 if (inst.input) { 48493 inst.input.val(clear ? "" : this._formatDate(inst)); 48494 } 48495 }, 48496 48497 /* Retrieve the date(s) directly. */ 48498 _getDate: function(inst) { 48499 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 48500 this._daylightSavingAdjust(new Date( 48501 inst.currentYear, inst.currentMonth, inst.currentDay))); 48502 return startDate; 48503 }, 48504 48505 /* Attach the onxxx handlers. These are declared statically so 48506 * they work with static code transformers like Caja. 48507 */ 48508 _attachHandlers: function(inst) { 48509 var stepMonths = this._get(inst, "stepMonths"), 48510 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 48511 inst.dpDiv.find("[data-handler]").map(function () { 48512 var handler = { 48513 prev: function () { 48514 $.datepicker._adjustDate(id, -stepMonths, "M"); 48515 }, 48516 next: function () { 48517 $.datepicker._adjustDate(id, +stepMonths, "M"); 48518 }, 48519 hide: function () { 48520 $.datepicker._hideDatepicker(); 48521 }, 48522 today: function () { 48523 $.datepicker._gotoToday(id); 48524 }, 48525 selectDay: function () { 48526 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 48527 return false; 48528 }, 48529 selectMonth: function () { 48530 $.datepicker._selectMonthYear(id, this, "M"); 48531 return false; 48532 }, 48533 selectYear: function () { 48534 $.datepicker._selectMonthYear(id, this, "Y"); 48535 return false; 48536 } 48537 }; 48538 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 48539 }); 48540 }, 48541 48542 /* Generate the HTML for the current state of the date picker. */ 48543 _generateHTML: function(inst) { 48544 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 48545 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 48546 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 48547 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 48548 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 48549 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 48550 tempDate = new Date(), 48551 today = this._daylightSavingAdjust( 48552 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 48553 isRTL = this._get(inst, "isRTL"), 48554 showButtonPanel = this._get(inst, "showButtonPanel"), 48555 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 48556 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 48557 numMonths = this._getNumberOfMonths(inst), 48558 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 48559 stepMonths = this._get(inst, "stepMonths"), 48560 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 48561 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 48562 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 48563 minDate = this._getMinMaxDate(inst, "min"), 48564 maxDate = this._getMinMaxDate(inst, "max"), 48565 drawMonth = inst.drawMonth - showCurrentAtPos, 48566 drawYear = inst.drawYear; 48567 48568 if (drawMonth < 0) { 48569 drawMonth += 12; 48570 drawYear--; 48571 } 48572 if (maxDate) { 48573 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 48574 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 48575 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 48576 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 48577 drawMonth--; 48578 if (drawMonth < 0) { 48579 drawMonth = 11; 48580 drawYear--; 48581 } 48582 } 48583 } 48584 inst.drawMonth = drawMonth; 48585 inst.drawYear = drawYear; 48586 48587 prevText = this._get(inst, "prevText"); 48588 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 48589 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 48590 this._getFormatConfig(inst))); 48591 48592 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 48593 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 48594 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : 48595 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>")); 48596 48597 nextText = this._get(inst, "nextText"); 48598 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 48599 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 48600 this._getFormatConfig(inst))); 48601 48602 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 48603 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 48604 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : 48605 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>")); 48606 48607 currentText = this._get(inst, "currentText"); 48608 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 48609 currentText = (!navigationAsDateFormat ? currentText : 48610 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 48611 48612 controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" + 48613 this._get(inst, "closeText") + "</button>" : ""); 48614 48615 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + 48616 (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" + 48617 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; 48618 48619 firstDay = parseInt(this._get(inst, "firstDay"),10); 48620 firstDay = (isNaN(firstDay) ? 0 : firstDay); 48621 48622 showWeek = this._get(inst, "showWeek"); 48623 dayNames = this._get(inst, "dayNames"); 48624 dayNamesMin = this._get(inst, "dayNamesMin"); 48625 monthNames = this._get(inst, "monthNames"); 48626 monthNamesShort = this._get(inst, "monthNamesShort"); 48627 beforeShowDay = this._get(inst, "beforeShowDay"); 48628 showOtherMonths = this._get(inst, "showOtherMonths"); 48629 selectOtherMonths = this._get(inst, "selectOtherMonths"); 48630 defaultDate = this._getDefaultDate(inst); 48631 html = ""; 48632 dow; 48633 for (row = 0; row < numMonths[0]; row++) { 48634 group = ""; 48635 this.maxRows = 4; 48636 for (col = 0; col < numMonths[1]; col++) { 48637 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 48638 cornerClass = " ui-corner-all"; 48639 calender = ""; 48640 if (isMultiMonth) { 48641 calender += "<div class='ui-datepicker-group"; 48642 if (numMonths[1] > 1) { 48643 switch (col) { 48644 case 0: calender += " ui-datepicker-group-first"; 48645 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 48646 case numMonths[1]-1: calender += " ui-datepicker-group-last"; 48647 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 48648 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 48649 } 48650 } 48651 calender += "'>"; 48652 } 48653 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 48654 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 48655 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 48656 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 48657 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 48658 "</div><table class='ui-datepicker-calendar'><thead>" + 48659 "<tr>"; 48660 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 48661 for (dow = 0; dow < 7; dow++) { // days of the week 48662 day = (dow + firstDay) % 7; 48663 thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 48664 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 48665 } 48666 calender += thead + "</tr></thead><tbody>"; 48667 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 48668 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 48669 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 48670 } 48671 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 48672 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 48673 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 48674 this.maxRows = numRows; 48675 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 48676 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 48677 calender += "<tr>"; 48678 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 48679 this._get(inst, "calculateWeek")(printDate) + "</td>"); 48680 for (dow = 0; dow < 7; dow++) { // create date picker days 48681 daySettings = (beforeShowDay ? 48682 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 48683 otherMonth = (printDate.getMonth() !== drawMonth); 48684 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 48685 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 48686 tbody += "<td class='" + 48687 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 48688 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 48689 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 48690 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 48691 // or defaultDate is current printedDate and defaultDate is selectedDate 48692 " " + this._dayOverClass : "") + // highlight selected day 48693 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days 48694 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 48695 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 48696 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 48697 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title 48698 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 48699 (otherMonth && !showOtherMonths ? " " : // display for other months 48700 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 48701 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 48702 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 48703 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 48704 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 48705 printDate.setDate(printDate.getDate() + 1); 48706 printDate = this._daylightSavingAdjust(printDate); 48707 } 48708 calender += tbody + "</tr>"; 48709 } 48710 drawMonth++; 48711 if (drawMonth > 11) { 48712 drawMonth = 0; 48713 drawYear++; 48714 } 48715 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 48716 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 48717 group += calender; 48718 } 48719 html += group; 48720 } 48721 html += buttonPanel; 48722 inst._keyEvent = false; 48723 return html; 48724 }, 48725 48726 /* Generate the month and year header. */ 48727 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 48728 secondary, monthNames, monthNamesShort) { 48729 48730 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 48731 changeMonth = this._get(inst, "changeMonth"), 48732 changeYear = this._get(inst, "changeYear"), 48733 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 48734 html = "<div class='ui-datepicker-title'>", 48735 monthHtml = ""; 48736 48737 // month selection 48738 if (secondary || !changeMonth) { 48739 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 48740 } else { 48741 inMinYear = (minDate && minDate.getFullYear() === drawYear); 48742 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 48743 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 48744 for ( month = 0; month < 12; month++) { 48745 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 48746 monthHtml += "<option value='" + month + "'" + 48747 (month === drawMonth ? " selected='selected'" : "") + 48748 ">" + monthNamesShort[month] + "</option>"; 48749 } 48750 } 48751 monthHtml += "</select>"; 48752 } 48753 48754 if (!showMonthAfterYear) { 48755 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 48756 } 48757 48758 // year selection 48759 if ( !inst.yearshtml ) { 48760 inst.yearshtml = ""; 48761 if (secondary || !changeYear) { 48762 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 48763 } else { 48764 // determine range of years to display 48765 years = this._get(inst, "yearRange").split(":"); 48766 thisYear = new Date().getFullYear(); 48767 determineYear = function(value) { 48768 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 48769 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 48770 parseInt(value, 10))); 48771 return (isNaN(year) ? thisYear : year); 48772 }; 48773 year = determineYear(years[0]); 48774 endYear = Math.max(year, determineYear(years[1] || "")); 48775 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 48776 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 48777 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 48778 for (; year <= endYear; year++) { 48779 inst.yearshtml += "<option value='" + year + "'" + 48780 (year === drawYear ? " selected='selected'" : "") + 48781 ">" + year + "</option>"; 48782 } 48783 inst.yearshtml += "</select>"; 48784 48785 html += inst.yearshtml; 48786 inst.yearshtml = null; 48787 } 48788 } 48789 48790 html += this._get(inst, "yearSuffix"); 48791 if (showMonthAfterYear) { 48792 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 48793 } 48794 html += "</div>"; // Close datepicker_header 48795 return html; 48796 }, 48797 48798 /* Adjust one of the date sub-fields. */ 48799 _adjustInstDate: function(inst, offset, period) { 48800 var year = inst.drawYear + (period === "Y" ? offset : 0), 48801 month = inst.drawMonth + (period === "M" ? offset : 0), 48802 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 48803 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 48804 48805 inst.selectedDay = date.getDate(); 48806 inst.drawMonth = inst.selectedMonth = date.getMonth(); 48807 inst.drawYear = inst.selectedYear = date.getFullYear(); 48808 if (period === "M" || period === "Y") { 48809 this._notifyChange(inst); 48810 } 48811 }, 48812 48813 /* Ensure a date is within any min/max bounds. */ 48814 _restrictMinMax: function(inst, date) { 48815 var minDate = this._getMinMaxDate(inst, "min"), 48816 maxDate = this._getMinMaxDate(inst, "max"), 48817 newDate = (minDate && date < minDate ? minDate : date); 48818 return (maxDate && newDate > maxDate ? maxDate : newDate); 48819 }, 48820 48821 /* Notify change of month/year. */ 48822 _notifyChange: function(inst) { 48823 var onChange = this._get(inst, "onChangeMonthYear"); 48824 if (onChange) { 48825 onChange.apply((inst.input ? inst.input[0] : null), 48826 [inst.selectedYear, inst.selectedMonth + 1, inst]); 48827 } 48828 }, 48829 48830 /* Determine the number of months to show. */ 48831 _getNumberOfMonths: function(inst) { 48832 var numMonths = this._get(inst, "numberOfMonths"); 48833 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 48834 }, 48835 48836 /* Determine the current maximum date - ensure no time components are set. */ 48837 _getMinMaxDate: function(inst, minMax) { 48838 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 48839 }, 48840 48841 /* Find the number of days in a given month. */ 48842 _getDaysInMonth: function(year, month) { 48843 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 48844 }, 48845 48846 /* Find the day of the week of the first of a month. */ 48847 _getFirstDayOfMonth: function(year, month) { 48848 return new Date(year, month, 1).getDay(); 48849 }, 48850 48851 /* Determines if we should allow a "next/prev" month display change. */ 48852 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 48853 var numMonths = this._getNumberOfMonths(inst), 48854 date = this._daylightSavingAdjust(new Date(curYear, 48855 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 48856 48857 if (offset < 0) { 48858 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 48859 } 48860 return this._isInRange(inst, date); 48861 }, 48862 48863 /* Is the given date in the accepted range? */ 48864 _isInRange: function(inst, date) { 48865 var yearSplit, currentYear, 48866 minDate = this._getMinMaxDate(inst, "min"), 48867 maxDate = this._getMinMaxDate(inst, "max"), 48868 minYear = null, 48869 maxYear = null, 48870 years = this._get(inst, "yearRange"); 48871 if (years){ 48872 yearSplit = years.split(":"); 48873 currentYear = new Date().getFullYear(); 48874 minYear = parseInt(yearSplit[0], 10); 48875 maxYear = parseInt(yearSplit[1], 10); 48876 if ( yearSplit[0].match(/[+\-].*/) ) { 48877 minYear += currentYear; 48878 } 48879 if ( yearSplit[1].match(/[+\-].*/) ) { 48880 maxYear += currentYear; 48881 } 48882 } 48883 48884 return ((!minDate || date.getTime() >= minDate.getTime()) && 48885 (!maxDate || date.getTime() <= maxDate.getTime()) && 48886 (!minYear || date.getFullYear() >= minYear) && 48887 (!maxYear || date.getFullYear() <= maxYear)); 48888 }, 48889 48890 /* Provide the configuration settings for formatting/parsing. */ 48891 _getFormatConfig: function(inst) { 48892 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 48893 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 48894 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 48895 return {shortYearCutoff: shortYearCutoff, 48896 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 48897 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; 48898 }, 48899 48900 /* Format the given date for display. */ 48901 _formatDate: function(inst, day, month, year) { 48902 if (!day) { 48903 inst.currentDay = inst.selectedDay; 48904 inst.currentMonth = inst.selectedMonth; 48905 inst.currentYear = inst.selectedYear; 48906 } 48907 var date = (day ? (typeof day === "object" ? day : 48908 this._daylightSavingAdjust(new Date(year, month, day))) : 48909 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 48910 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 48911 } 48912}); 48913 48914/* 48915 * Bind hover events for datepicker elements. 48916 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 48917 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 48918 */ 48919function datepicker_bindHover(dpDiv) { 48920 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 48921 return dpDiv.delegate(selector, "mouseout", function() { 48922 $(this).removeClass("ui-state-hover"); 48923 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 48924 $(this).removeClass("ui-datepicker-prev-hover"); 48925 } 48926 if (this.className.indexOf("ui-datepicker-next") !== -1) { 48927 $(this).removeClass("ui-datepicker-next-hover"); 48928 } 48929 }) 48930 .delegate( selector, "mouseover", datepicker_handleMouseover ); 48931} 48932 48933function datepicker_handleMouseover() { 48934 if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) { 48935 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 48936 $(this).addClass("ui-state-hover"); 48937 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 48938 $(this).addClass("ui-datepicker-prev-hover"); 48939 } 48940 if (this.className.indexOf("ui-datepicker-next") !== -1) { 48941 $(this).addClass("ui-datepicker-next-hover"); 48942 } 48943 } 48944} 48945 48946/* jQuery extend now ignores nulls! */ 48947function datepicker_extendRemove(target, props) { 48948 $.extend(target, props); 48949 for (var name in props) { 48950 if (props[name] == null) { 48951 target[name] = props[name]; 48952 } 48953 } 48954 return target; 48955} 48956 48957/* Invoke the datepicker functionality. 48958 @param options string - a command, optionally followed by additional parameters or 48959 Object - settings for attaching new datepicker functionality 48960 @return jQuery object */ 48961$.fn.datepicker = function(options){ 48962 48963 /* Verify an empty collection wasn't passed - Fixes #6976 */ 48964 if ( !this.length ) { 48965 return this; 48966 } 48967 48968 /* Initialise the date picker. */ 48969 if (!$.datepicker.initialized) { 48970 $(document).mousedown($.datepicker._checkExternalClick); 48971 $.datepicker.initialized = true; 48972 } 48973 48974 /* Append datepicker main container to body if not exist. */ 48975 if ($("#"+$.datepicker._mainDivId).length === 0) { 48976 $("body").append($.datepicker.dpDiv); 48977 } 48978 48979 var otherArgs = Array.prototype.slice.call(arguments, 1); 48980 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 48981 return $.datepicker["_" + options + "Datepicker"]. 48982 apply($.datepicker, [this[0]].concat(otherArgs)); 48983 } 48984 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 48985 return $.datepicker["_" + options + "Datepicker"]. 48986 apply($.datepicker, [this[0]].concat(otherArgs)); 48987 } 48988 return this.each(function() { 48989 typeof options === "string" ? 48990 $.datepicker["_" + options + "Datepicker"]. 48991 apply($.datepicker, [this].concat(otherArgs)) : 48992 $.datepicker._attachDatepicker(this, options); 48993 }); 48994}; 48995 48996$.datepicker = new Datepicker(); // singleton instance 48997$.datepicker.initialized = false; 48998$.datepicker.uuid = new Date().getTime(); 48999$.datepicker.version = "1.11.2"; 49000 49001return $.datepicker; 49002 49003})); 49004 49005}, 49006'dpage/widgets/TokenizedInput':function(){ 49007define([ 49008 "dojo/_base/event" 49009 , "dojo/on" 49010 , "dojo/dom-attr" 49011 , "dojo/dom-class" 49012 , "dojo/mouse" 49013 , "dojo/dom-geometry" 49014 , "dojo/dom-style" 49015 49016 , "dpage/widgets/MultiValueWidget" 49017 , "dojox/html/entities" 49018 , "dpage/modules/LegacyPlaceholder" 49019 , "dojo/_base/declare" 49020 , "dijit/_WidgetBase" 49021 , "dpage/widgets/BaseWidget" 49022 , "dijit/_TemplatedMixin" 49023 , "dijit/_Container"], 49024function (event, on, domAttr, domClass, mouse, domGeom, style) { 49025 /** 49026 * @namespace dpage 49027 */ 49028 /** 49029 * @namespace widgets 49030 * @memberOf dpage 49031 */ 49032 /** 49033 * Implementation of a structured input box. Use for things like address pickers. 49034 * @class TokenizedInput 49035 * @param {Object} [options] Optional options for the widget. 49036 * @param {dpage.modules.TabularModel} [options.model] The model for the widget. 49037 * @param {bool} [options.noDefaultCSS] If true, won't bring in any default styling. Use this only if you will creating your own styles. 49038 * @param {String} [options.css] url path to user defined css for this widget. 49039 * @param {bool} [options.stayFocusedOnTab] If true, focus won't be lost when the tab key is pressed. 49040 * @param {String} [options.separaterPattern] The pattern used to split the input up into items. 49041 * @param {String} [options.validItemPattern] The pattern used to verify if an item is valid or not. 49042 * @param {bool} [options.trimWhitespace] If true, trim any whitespace off of item names. 49043 * @param {bool} [options.allowBlanks] Allow blank values in. 49044 * @param {String} [options.dataDisplayField] The field used to display the item text. 49045 * @param {String} [options.captionDisplayField] The field used to display the caption. 49046 * @param {bool} [options.captionFieldIsHTML] Default false. If true, the caption field will not be html-encoded. You open up yourself to XSS attacks if set to true. 49047 * @param {bool} [options.backspaceDeletesItem] If true, a backspace will delete the last item. 49048 * @param {Function} [options.dataAddCallback] Very powerfull way of controlling whether items get added, what gets added, and if they are valid. 49049 * @param {bool} [options.disabled] Default=false. 49050 * @param {String} [options.placeholder] Placeholder text to display in input. 49051 49052 * @param {dpage.widgets.Container} [options.container] The container of the widget. 49053 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 49054 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 49055 * is created. 49056 * @param {Object} [containerNode] Optional container node to tie the widget to. 49057 * @memberOf dpage.widgets 49058 * @extends {dpage.widgets.MultiValueWidget} 49059 */ 49060 return dojo.declare("dpage.widgets.TokenizedInput", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.TokenizedInput.prototype */ { 49061 _itemLookup: [], //[ {dataIdx : idx , parentDiv: div , captionDiv : div} ] 49062 _data: null, 49063 _stayFocusedOnTab: false, 49064 _inputNode: null, // 49065 _separaterPattern: new RegExp("\\s+"), //the default pattern. Separate items based on whitespace 49066 _validItemPattern: new RegExp(".*"), //all items are valid. 49067 _trimWhitespace: true, 49068 _allowBlanks: false, //allow whitespace only data? 49069 _dataDisplayField: "value", //if set will add a row to data with this field set when a token is matched. The field in the ds MUST BE HTML ENCODED.
49070 _dataFieldIsHTML: false, 49071 _captionDisplayField: "value", //field in the dataset that holds the caption. The field in the ds MUST BE HTML ENCODED. 49072 _captionFieldIsHTML: false, 49073 _ulNode: null, 49074 _dataAddCallback: null, 49075 _backspaceDeletesItem: true, 49076 _invalidMessage: 'Invalid Item', 49077 _disabled: false, 49078 _placeholder: null, //placeholder text for the input. 49079 _emulatePlaceholder: false, //support for IE9 placeholder. 49080 _containerNode : null, 49081 49082 constructor: function (options , containerNode) { 49083 var self = this; 49084 var defaultCSSLoaded = false; 49085 var userCSS = null; 49086 49087 this._containerNode = containerNode; 49088 49089 if (containerNode == null) 49090 this._containerNode = document.createElement("DIV"); 49091 49092 //load the default CSS, unless user specified not to. 49093 if (options == null || !options.noDefaultCSS) 49094 { 49095 defaultCSSLoaded = true; 49096 require(["xstyle/css!dpage/widgets/TokenizedInput.css"], function () { 49097 if (userCSS) { 49098 //load user css after the default css. 49099 require(["xstyle/css!" + userCSS], function () { });
49100 } 49101 }); 49102 } 49103 49104 if (options != null) { 49105 49106 //amd path to optional css to style the widget. 49107 if (options.css != null) 49108 { 49109 if(defaultCSSLoaded) 49110 userCSS = options.css; 49111 else 49112 require(["xstyle/css!" + options.css], function () { }); 49113 } 49114 if (options.stayFocusedOnTab != null) 49115 this._stayFocusedOnTab = options.stayFocusedOnTab; 49116 49117 if (options.separaterPattern != null) 49118 this._separaterPattern = options.separaterPattern; 49119 if (options.validItemPattern != null) 49120 this._validItemPattern = options.validItemPattern; 49121 49122 if (options.trimWhitespace != null) 49123 this._trimWhitespace = options.trimWhitespace; 49124 49125 if (options.allowBlanks != null) 49126 this._allowBlanks = options.allowBlanks; 49127 49128 if (options.dataDisplayField != null) 49129 this._dataDisplayField = options.dataDisplayField; 49130 49131 if (options.dataFieldIsHTML != null) 49132 this._dataFieldIsHTML = options.dataFieldIsHTML; 49133 49134 if (options.captionDisplayField != null) 49135 this._captionDisplayField = options.captionDisplayField; 49136 49137 if (options.captionFieldIsHTML != null) 49138 this._captionFieldIsHTML = options.captionFieldIsHTML; 49139 49140 if (options.backspaceDeletesItem != null) 49141 this._backspaceDeletesItem = options.backspaceDeletesItem; 49142 49143 if (options.dataAddCallback != null) 49144 this._dataAddCallback = options.dataAddCallback; 49145 49146 if (options.invalidMessage != null) 49147 this._invalidMessage = options.invalidMessage; 49148 49149 if (options.disabled != null) 49150 this._disabled = options.disabled; 49151 49152 if (options.model != null) { 49153 if (options.dataDisplayField == null) 49154 throw new Error("If passing in a model to a TokenizedInput, you must also specify the dataDisplayField property"); 49155 49156 if (options.captionDisplayField == null) { 49157 this._captionDisplayField = this._dataDisplayField; 49158 this._captionFieldIsHTML = this._dataFieldIsHTML; 49159 } 49160 49161 this._model = options.model; 49162 } 49163 if (options.placeholder != null) { 49164 this._placeholder = options.placeholder; 49165 } 49166 49167 } 49168 49169 if(options == null || options.model == null) 49170 this._model = new dpage.modules.TabularModel({ defaultColName: this._dataDisplayField }); 49171 }, 49172 buildRendering : function() 49173 { 49174 this.inherited(arguments); 49175 return this._containerNode; 49176 }, 49177 /** 49178 * Turn a model into a {@link dpage.modules.TabularModel} if it isn't already. Some fuzzy logic going on here. If the 49179 * passed in modelObj doesn't look like a {@link dpage.modules.TabularModel}, the Object is passed to the 49180 * {@link dpage.modules.TabularModel} constructor in the "model" property. Refer to the documentation for {@link dpage.modules.TabularModel} 49181 * for information regarding the structure of the modelObj param (or just pass in a {@link dpage.modules.TabularModel}). 49182 * @param {Object} modelObj 49183 * @param {bool} excludeDomRender if true don't re-render the widget. 49184 * @returns {void} 49185 */ 49186 setModel: function (model, excludeDomRender) { 49187 this.inherited(arguments); 49188 this._data = this.getModel().getRows(); 49189 49190 this._updateView(); 49191 } 49192 , _buildDomStructure : function() 49193 { 49194 //build up the dom structure. 49195 for (var idx = 0; idx < this._data.length ; idx++) { 49196 var value; 49197 49198 value = this._data[idx][this._dataDisplayField]; 49199 49200 var newLookupItem = this._addDomNodeForItem(dojox.html.entities.encode(value) , true); 49201 49202 newLookupItem.dataIdx = idx; 49203 49204 this._itemLookup.push(newLookupItem); 49205 } 49206 } 49207 , templateString: "<div></div>" 49208 , postCreate: function () { 49209 if(this.getModel() != null) 49210 this._data = this.getModel().getRows(); 49211 49212 this._updateView(); 49213 }, 49214 _updateView : function() 49215 { 49216 var inputNode = document.createElement("INPUT"); 49217 var inputContainer = document.createElement("LI"); 49218 var ulNode = document.createElement("UL"); 49219 var containerNode = this._containerNode;
49220 var domNode = this.domNode; 49221 var self = this; 49222 var classes; 49223 //take the style from the parent div. 49224 49225 //re-initialize. 49226 domNode.innerHTML = ""; 49227 49228 domClass.add(inputNode, "mt-tok-input"); 49229 domClass.add(domNode, "mt-tok-container"); 49230 49231 if (!this._disabled) { 49232 domClass.add(ulNode, "mt-tok-items-container"); 49233 } 49234 else { 49235 domClass.add(ulNode, "mt-tok-items-container-disabled"); 49236 domAttr.set(inputNode, "disabled", true); 49237 } 49238 domClass.add(inputContainer, "mt-tok-item-input-container"); 49239 49240 if (containerNode.nodeName != "DIV") 49241 throw new Error("The parent node for a TokenizedInput must be a DIV element"); 49242 49243 domAttr.set(domNode, "style", domAttr.get(containerNode, "style")); 49244 49245 classes = containerNode.className; 49246 if (classes != null) 49247 classes = classes.split(/\s+/); 49248 else 49249 classes = []; 49250 for (var i = 0; i < classes.length; i++) 49251 domClass.add(domNode, classes[i]); 49252 49253 domNode.appendChild(ulNode); 49254 ulNode.appendChild(inputContainer); 49255 inputContainer.appendChild(inputNode); 49256 49257 this._ulNode = ulNode; 49258 this._inputNode = inputNode; 49259 49260 if (this._placeholder != null) 49261 { 49262 if(dpage.modules.LegacyPlaceholder.hasNativePlaceholderSupport()) 49263 domAttr.set(this._inputNode, "placeholder", this._placeholder); 49264 else 49265 { 49266 this._emulatePlaceholder = true; 49267 domClass.add(this._inputNode, "placeholder"); 49268 this._inputNode.value = this._placeholder; 49269 } 49270 } 49271 49272 on(inputNode, "keypress", function () { self._onInputKeyPress(arguments); }); 49273 on(inputNode, "keydown", function () { self._onInputKeyDown(arguments); }); 49274 on(inputNode, "keyup", function () { self._onInputKeyUp(arguments); }); 49275 on(inputNode, "blur", function () { self._onInputBlur(arguments); }); 49276 on(inputNode, "focus", function () { self._onInputFocus(arguments); }); 49277 on(this.domNode, "click", function () { self._input_OnClick(arguments); }); 49278 49279 if (this._data.length != 0) 49280 this._buildDomStructure(); 49281 }, 49282 //ie9 support 49283 _onInputFocus: function (e) { 49284 if(this._emulatePlaceholder) 49285 { 49286 if(this._inputNode.value == this._placeholder) 49287 { 49288 this._inputNode.value = ""; 49289 } 49290 } 49291 } 49292 , _onInputBlur: function (e) { 49293 this._doInputChange(this._inputNode.value , true); 49294 49295 this._autoSizeInput(); 49296 49297 //ie9 support. 49298 if (this._emulatePlaceholder) { 49299 if (this._inputNode.value == "") { 49300 this._inputNode.value = this._placeholder; 49301 } 49302 } 49303 49304 } 49305 , _input_OnClick: function (e) { 49306 this._inputNode.focus(); 49307 } 49308 , _onInputKeyPress: function (e) { 49309 //value "before" the keypress 49310 var value = this._inputNode.value; 49311 var currentChar; 49312 var tokens; 49313 49314 e = e[0]; 49315 49316 //special case for CR because it doesn't seem to work with String.fromCharCode 49317 if (e.charCode == 13) 49318 { 49319 currentChar = "\n"; 49320 } 49321 //the key just pressed. 49322 else 49323 currentChar = String.fromCharCode(e.charCode); 49324 49325 if (this._doInputChange(value + currentChar, false)) 49326 event.stop(e); 49327 49328 this._autoSizeInput(); 49329 } 49330 , _onInputKeyDown: function (e) { 49331 e = e[0]; 49332 //the key that is pressed. 49333 var c = e.keyCode; 49334 var val; 49335 var inputDimensions; 49336 var testerDimensions; 49337 var tokens; 49338 var ourLookupItem; 49339 var self = this; 49340 49341 //the value of the input "before" the keypress. 49342 val = this._inputNode.value; 49343 49344 if (c == 9 && this._stayFocusedOnTab) { 49345 //stop the event. We would otherwise loose focus. 49346 event.stop(e); 49347 49348 //assume that the tab was the last char typed (at the end of the input). 49349 this._doInputChange(this._inputNode.value + '\t' , false); 49350 } 49351 49352 if (c == 8 && this._backspaceDeletesItem && this._itemLookup.length > 0 && this._inputNode.value.length == 0) 49353 { 49354 ourLookupItem = this._itemLookup[0]; 49355 49356 for(var idx = 0; idx < this._itemLookup.length ; idx++) 49357 { 49358 var lookupItem = this._itemLookup[idx]; 49359 49360 if (lookupItem.dataIdx > ourLookupItem.dataIdx) 49361 ourLookupItem = lookupItem; 49362 } 49363 49364 this._removeItem(ourLookupItem); 49365 } 49366 49367 this._autoSizeInput(); 49368 } 49369 //make min width the width of the container - items, otherwise size to content width. 49370 , _autoSizeInput: function () { 49371 var inputStyleProps; 49372 //resize the input based on width of text 49373 var domEl = document.createElement("SPAN"); 49374 var strVal; 49375 var contentWidth; 49376 var widthToFill;
49377 var domNodeDimensions; 49378 var testerDimensions; 49379 var inputNodeDimensions; 49380 var newInputWidth; 49381 var lastItemDimensions; 49382 var lastListItem; 49383 var referenceLeft; 49384 49385 inputStyleProps = style.getComputedStyle(this._inputNode); 49386 49387 style.set(domEl, { 49388 top: "-9999px" 49389 , left: "-9999px" 49390 , padding: "1em" 49391 , position: "absolute" 49392 , whiteSpace: "nowrap" 49393 , fontSize: inputStyleProps.fontSize 49394 , fontFamily: inputStyleProps.fontFamily 49395 , fontWeight: inputStyleProps.fontWeight 49396 , letterSpacing: inputStyleProps.letterSpacing 49397 }); 49398 49399 strVal = this._inputNode.value; 49400 49401 strVal = strVal.replace(new RegExp("\\s", "g"), " "); 49402 document.body.appendChild(domEl); 49403 domEl.innerHTML = strVal; 49404 49405 testerDimensions = domGeom.position(domEl); 49406 domNodeDimensions = domGeom.position(this.domNode); 49407 inputNodeDimensions = domGeom.position(this._inputNode); 49408 49409 lastListItem = this._ulNode.lastChild; 49410 49411 if (lastListItem != null) { 49412 lastItemDimensions = domGeom.position(lastListItem); 49413 referenceLeft = lastItemDimensions.x + lastItemDimensions.w; 49414 } 49415 else 49416 referenceLeft = inputNodeDimensions.x; 49417 49418 contentWidth = testerDimensions.w; 49419 49420 widthToFill = domNodeDimensions.w - (referenceLeft - domNodeDimensions.x) - 20; 49421 49422 if (widthToFill > contentWidth) 49423 newInputWidth = widthToFill; 49424 else 49425 newInputWidth = contentWidth; 49426 49427 document.body.removeChild(domEl); 49428 style.set(this._inputNode, { width: (newInputWidth) + "px" }); 49429 } 49430 , _onInputKeyUp: function (e) { 49431 var x = e[0].keyCode; 49432 } 49433 , _removeItem: function (lookupItem) { 49434 var containerDiv = lookupItem.parentDiv; 49435 var dataIdx = lookupItem.dataIdx; 49436 49437 containerDiv.parentNode.removeChild(containerDiv); 49438 49439 if (lookupItem.captionDiv != null) { 49440 document.body.removeChild(lookupItem.captionDiv); 49441 lookupItem.captionDiv = null; 49442 } 49443 49444 //remove the data record. 49445 this._data.splice(dataIdx, 1); 49446 //remove the item lookup record. 49447 this._itemLookup.splice(dataIdx, 1); 49448 49449 for (var idx = 0; idx < this._itemLookup.length; idx++) { 49450 var item = this._itemLookup[idx]; 49451 //normalize the indexes. 49452 if (item.dataIdx > dataIdx) 49453 item.dataIdx--; 49454 } 49455 } 49456 , _itemClose_OnClick: function (lookupItem) { 49457 this._removeItem(lookupItem); 49458 } 49459 //raw input value. This gets called by the control. 49460 , _doInputChange: function (value , loosingFocusFlag) { 49461 var self = this; 49462 var newLookupItem; 49463 var item; 49464 var parseOutput; 49465 var items; 49466 49467 parseOutput = this.parseInput(value, loosingFocusFlag); 49468 49469 items = parseOutput.parsedItems; 49470 49471 for (var idx = 0; idx < items.length ; idx++) { 49472 item = items[idx]; 49473 var dataRow = item.data; 49474 var valid = item.valid; 49475 var valueToDisplay = dataRow[this._dataDisplayField]; 49476 var newLookupItem = this._addDomNodeForItem(dojox.html.entities.encode(valueToDisplay) , valid); 49477 49478 newLookupItem.dataIdx = self._data.length; 49479 newLookupItem.valid = valid; 49480 this._data.push(dataRow); 49481 this._itemLookup.push(newLookupItem); 49482 } 49483 49484 this.validate(); 49485 49486 if (parseOutput.newText != null) { 49487 this._inputNode.value = parseOutput.newText; 49488 //input text was changed 49489 return true; 49490 } 49491 49492 if (this._emulatePlaceholder) 49493 { 49494 if(value == "") 49495 { 49496 this._inputNode.value = this._placeholder; 49497 } 49498 } 49499 49500 //input text was not changed 49501 return false; 49502 }, 49503 /**
49504 * Can be called from an external consumer. 49505 * @param {Object} value A row of data to add. 49506 * @returns {void} 49507 */ 49508 addDataRow: function (value) { 49509 var valueToDisplay; 49510 var self = this; 49511 49512 valueToDisplay = value[this._dataDisplayField]; 49513 49514 if (!this._dataFieldIsHTML) 49515 valueToDisplay = dojox.html.entities.encode(valueToDisplay); 49516 49517 var newLookupItem = this._addDomNodeForItem(valueToDisplay , true); 49518 49519 newLookupItem.dataIdx = self._data.length; 49520 newLookupItem.valid = true;//assume valid if called external. 49521 49522 this._data.push(value); 49523 49524 this._itemLookup.push(newLookupItem); 49525 this._autoSizeInput(); 49526 this.validate(); 49527 }, 49528 //method is called whenever the input value changes. It parses the input into items and returns back the new text 49529 // to display in the input or null for no change. 49530 /* 49531 var returnVal = 49532 { 49533 newText: "new text to put in input" | null 49534 ,parsedItems : 49535 [ 49536 { 49537 valid: true | false 49538 , data : 49539 { 49540 //dataset row here. 49541 } 49542 } 49543 ] 49544 } 49545 */ 49546 parseInput: function (rawData, loosingFocusFlag) { 49547 var ret = { newText: null, parsedItems: [] }; 49548 var re = this._separaterPattern; 49549 var tokens; 49550 var checkValue; 49551 var newItem; 49552 var separaterPatternMatches; 49553 49554 tokens = rawData.split(re); 49555 separaterPatternMatches = rawData.match(re); 49556 49557 //special case for one item and input loosing focus. 49558 if (!separaterPatternMatches && loosingFocusFlag) { 49559 checkValue = rawData; 49560 if (!this._allowBlanks) { 49561 checkValue = checkValue.replace(/\s+$/, ""); 49562 checkValue = checkValue.replace(/^\s+/, ""); 49563 if (!checkValue) 49564 return ret; 49565 } 49566 49567 if (checkValue.match(this._validItemPattern) != null) { 49568 49569 newItem = this.buildDataRow(checkValue); 49570 49571 if(newItem != null) 49572 ret.parsedItems.push(newItem); 49573 49574 ret.newText = ""; 49575 return ret; 49576 } 49577 //invalid item 49578 else { 49579 49580 if (this._trimWhitespace) { 49581 checkValue = checkValue.replace(/\s+$/, ""); 49582 checkValue = checkValue.replace(/^\s+$/, ""); 49583 } 49584 49585 newItem = this.buildDataRow(checkValue, true); 49586 49587 if (newItem != null) 49588 ret.parsedItems.push(newItem); 49589 } 49590 } 49591 49592 if (!separaterPatternMatches) 49593 return ret; 49594 49595 for (var idx = 0; idx < tokens.length; idx++) { 49596 checkValue = tokens[idx]; 49597 49598 if (!this._allowBlanks) { 49599 checkValue = checkValue.replace(/\s+$/, ""); 49600 checkValue = checkValue.replace(/^\s+/, ""); 49601 if (!checkValue) 49602 continue; 49603 } 49604 49605 //valid item. 49606 if (checkValue.match(this._validItemPattern) != null) { 49607 49608 if (this._trimWhitespace) { 49609 checkValue = checkValue.replace(/\s+$/, ""); 49610 checkValue = checkValue.replace(/^\s+$/, ""); 49611 } 49612 49613 newItem = this.buildDataRow(checkValue); 49614 49615 if(newItem != null) 49616 ret.parsedItems.push(newItem); 49617 } 49618 //invalid item 49619 else 49620 { 49621 49622 if (this._trimWhitespace) { 49623 checkValue = checkValue.replace(/\s+$/, ""); 49624 checkValue = checkValue.replace(/^\s+$/, ""); 49625 } 49626 49627 newItem = this.buildDataRow(checkValue , true); 49628 49629 if (newItem != null) 49630 ret.parsedItems.push(newItem); 49631 } 49632 } 49633 49634 //so the input will be cleared out. 49635 ret.newText = ""; 49636 49637 return ret; 49638 }, 49639 //override this method to build a custom dataset row when a value is input. Called when an item is added. 49640 //return back null to stop the item from being added. 49641 buildDataRow: function (rawData , isBad) { 49642 var cookedValue; 49643 49644 //if someone has set a callback, use that instead. 49645 if (this._dataAddCallback != null) 49646 return this._dataAddCallback(rawData , isBad); 49647 49648 var dataObj = {}; 49649 dataObj[this._dataDisplayField] = rawData; 49650 49651 dataObj[this._captionDisplayField] = rawData; 49652 cookedValue.data = dataObj; 49653 cookedValue.valid = !isBad; 49654 49655 return cookedValue; 49656 }, 49657 //return the correct data for the caption. 49658 _getCaptionContent: function (lookupItem) { 49659 var value; 49660 49661 value = this._data[lookupItem.dataIdx]; 49662 49663 value = value[this._captionDisplayField]; 49664 49665 if (!this._captionFieldIsHTML) 49666 value = dojox.html.entities.encode(value); 49667 49668 return value; 49669 }, 49670 _item_OnMouseEnter: function (newLookupItem) { 49671 var titleDiv = document.createElement("DIV"); 49672 var tailDiv = document.createElement("DIV"); 49673 var captionDimensions; 49674 var itemObjDimensions; 49675 var tailDimensions; 49676 49677 49678 titleDiv.innerHTML = this._getCaptionContent(newLookupItem); 49679 titleDiv.appendChild(tailDiv); 49680 49681 domClass.add(titleDiv, "mt-tok-caption"); 49682 domClass.add(tailDiv, "mt-tok-down-arrow"); 49683 49684 document.body.appendChild(titleDiv); 49685 49686 //get the width of the caption 49687 captionDimensions = domGeom.position(titleDiv); 49688 itemObjDimensions = domGeom.position(newLookupItem.parentDiv); 49689 tailDimensions = domGeom.position(tailDiv); 49690 49691 newLookupItem.captionDiv = titleDiv; 49692 49693 style.set(titleDiv, { 49694 left: (itemObjDimensions.x + (itemObjDimensions.w / 2) - (captionDimensions.w / 2)) + "px" 49695 , top: (itemObjDimensions.y - 10 - (captionDimensions.h)) + "px" 49696 }); 49697 }, 49698 _item_OnMouseLeave: function (newLookupItem) { 49699 if (newLookupItem.captionDiv != null) { 49700 document.body.removeChild(newLookupItem.captionDiv); 49701 newLookupItem.captionDiv = null; 49702 } 49703 }, 49704 _addDomNodeForItem: function (value, valid) { 49705 var self = this; 49706 var itemContainer = document.createElement("LI"); 49707 var itemContentContainer = document.createElement("SPAN"); 49708 var itemIconContainer = document.createElement("SPAN"); 49709 var closeContainer = document.createElement("A"); 49710 var newLookupItem = { dataIdx: null, parentDiv: itemContainer }; 49711 49712 on(itemContainer, mouse.enter, function () { self._item_O
49712nMouseEnter(newLookupItem); }); 49713 on(itemContainer, mouse.leave, function () { self._item_OnMouseLeave(newLookupItem); }); 49714 49715 itemIconContainer.innerHTML = " "; 49716 itemContainer.appendChild(itemIconContainer); 49717 itemContainer.appendChild(itemContentContainer); 49718 itemContainer.appendChild(closeContainer); 49719 49720 on(closeContainer, "click", function () { self._itemClose_OnClick(newLookupItem); }); 49721 49722 domClass.add(itemContainer, "mt-tok-item-container"); 49723 domClass.add(itemIconContainer, "mt-tok-icon-container"); 49724 domClass.add(itemContentContainer, "mt-tok-item-content"); 49725 domClass.add(closeContainer, "mt-tok-close-container"); 49726 49727 if(!valid) 49728 domClass.add(itemContainer, "mt-tok-item-invalid"); 49729 49730 //html encoded value 49731 itemContentContainer.innerHTML = value; 49732 this._ulNode.insertBefore(itemContainer, this._inputNode.parentNode); 49733 this._inputNode.value = ""; 49734 49735 return newLookupItem; 49736 }, 49737 validate: function () 49738 { 49739 var valid = this.inherited(arguments); 49740 if (valid === null) { 49741 if (this.getContainer()) { 49742 if (this.getContainer().getValidationMessageWidget()) { 49743 this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId()); 49744 } 49745 } 49746 } 49747 return valid; 49748 }, 49749 /** 49750 * Call this to see if the widget contains invalid items. 49751 * @returns {bool} 49752 */ 49753 containsInvalidItems: function () 49754 { 49755 for(var idx=0;idx<this._itemLookup.length;idx++) 49756 { 49757 var lookupItem = this._itemLookup[idx]; 49758 49759 if (!lookupItem.valid) 49760 return true; 49761 } 49762 return false; 49763 } 49764 }); 49765}); 49766 49767}, 49768'dijit/_Container':function(){ 49769define([ 49770 "dojo/_base/array", // array.forEach array.indexOf 49771 "dojo/_base/declare", // declare 49772 "dojo/dom-construct", // domConstruct.place 49773 "dojo/_base/kernel" // kernel.deprecated 49774], function(array, declare, domConstruct, kernel){ 49775 49776 // module: 49777 // dijit/_Container 49778 49779 return declare("dijit._Container", null, { 49780 // summary: 49781 // Mixin for widgets that contain HTML and/or a set of widget children. 49782 49783 buildRendering: function(){ 49784 this.inherited(arguments); 49785 if(!this.containerNode){ 49786 // All widgets with descendants must set containerNode. 49787 // NB: this code doesn't quite work right because for TabContainer it runs before 49788 // _TemplatedMixin::buildRendering(), and thus 49789 // sets this.containerNode to this.domNode, later to be overridden by the assignment in the template. 49790 this.containerNode = this.domNode; 49791 } 49792 }, 49793 49794 addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){ 49795 // summary: 49796 // Makes the given widget a child of this widget. 49797 // description: 49798 // Inserts specified child widget's dom node as a child of this widget's 49799 // container node, and possibly does other processing (such as layout). 49800 49801 // I want to just call domConstruct.place(widget.domNode, this.containerNode, insertIndex), but the counting 49802 // is thrown off by text nodes and comment nodes that show up when constructed by markup. 49803 // In the future consider stripping those nodes on construction, either in the parser or this widget code. 49804 var refNode = this.containerNode; 49805 if(insertIndex > 0){ 49806 // Old-school way to get nth child; dojo.query would be easier but _Container was weened from dojo.query 49807 // in #10087 to minimize download size. Not sure if that's still and issue with new smaller dojo/query. 49808 refNode = refNode.firstChild; 49809 while(insertIndex > 0){ 49810 if(refNode.nodeType == 1){ insertIndex--; } 49811 refNode = refNode.nextSibling; 49812 } 49813 if(refNode){ 49814 insertIndex = "before"; 49815 }else{ 49816 // to support addChild(child, n-1) where there are n children (should add child at end) 49817 refNode = this.containerNode; 49818 insertIndex = "last"; 49819 } 49820 } 49821 49822 domConstruct.place(widget.domNode, refNode, insertIndex); 49823 49824 // If I've been started but the child widget hasn't been started, 49825 // start it now. Make sure to do this after widget has been 49826 // inserted into the DOM tree, so it can see that it's being controlled by me, 49827 // so it doesn't try to size itself. 49828 if(this._started && !widget._started){ 49829 widget.startup(); 49830 } 49831 }, 49832 49833 removeChild: function(/*Widget|int*/ widget){ 49834 // summary: 49835 // Removes the passed widget instance from this widget but does 49836 // not destroy it. You can also pass in an integer indicating 49837 // the index within the container to remove (ie, removeChild(5) removes the sixth widget). 49838 49839 if(typeof widget == "number"){ 49840 widget = this.getChildren()[widget]; 49841 } 49842 49843 if(widget){ 49844 var node = widget.domNode; 49845 if(node && node.parentNode){ 49846 node.parentNode.removeChild(node); // detach but don't destroy 49847 } 49848 } 49849 }, 49850 49851 hasChildren: function(){ 49852 // summary: 49853 // Returns true if widget has child widgets, i.e. if this.containerNode
49853contains widgets. 49854 return this.getChildren().length > 0; // Boolean 49855 }, 49856 49857 _getSiblingOfChild: function(/*dijit/_WidgetBase*/ child, /*int*/ dir){ 49858 // summary: 49859 // Get the next or previous widget sibling of child 49860 // dir: 49861 // if 1, get the next sibling 49862 // if -1, get the previous sibling 49863 // tags: 49864 // private 49865 kernel.deprecated(this.declaredClass+"::_getSiblingOfChild() is deprecated. Use _KeyNavMixin::_getNext() instead.", "", "2.0"); 49866 var children = this.getChildren(), 49867 idx = array.indexOf(children, child); // int 49868 return children[idx + dir]; 49869 }, 49870 49871 getIndexOfChild: function(/*dijit/_WidgetBase*/ child){ 49872 // summary: 49873 // Gets the index of the child in this container or -1 if not found 49874 return array.indexOf(this.getChildren(), child); // int 49875 } 49876 }); 49877}); 49878 49879}, 49880'dpage/widgets/Tree':function(){ 49881define([ 49882 "jquery", 49883 "dojo/on", 49884 49885 "dpage/modules/Config", 49886 "dojo/_base/declare", 49887 "xstyle/css!dpage/3p/jstree/style.css", 49888 "dpage/widgets/MultiValueWidget"], 49889function ($, on) { 49890 /** 49891 * @namespace dpage 49892 */ 49893 /** 49894 * @namespace widgets 49895 * @memberOf dpage 49896 */ 49897 /** 49898 * Tree view control. 49899 * @class Tree 49900 * @param {Object} [options] Optional options for the widget. 49901 * @param {String} options.propId The field in the model that holds the value of the tree node id. This has to be unique in the model. 49902 * @param {String} options.propParent The field in the model that holds the value of the id of the nodes parent node. 49903 * @param {String} options.propText The field in the model that holds the value of the text of the node. 49904 * @param {bool} [options.enableDragAndDrop] Default false. If true, a user can drag and drop nodes to different parent nodes. 49905 * @param {function} [options.itemMoveCallback] void itemMoveCallback(modelRowMoved , modelRowParent) If passed in, this function will be called when an item is moved via drag-and-drop. 49906 * @param {function} [options.itemCheckCallback] bool itemCheckCallback(modelRowToMove , modelRowNewParent) If passed in, the return value of this function determines whether a node can be moved to a particular parent node. 49907 * @param {function} [options.itemSelectCallback] void itemSelectCallback(modelRow) If passed in, this is called whenever a node is selected. 49908 49909 * @param {dpage.modules.TabularModel} [options.model] The model to use. 49910 * @param {dpage.widgets.Container} [options.container] The container of the widget. 49911 * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called. 49912 * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one 49913 * is created. 49914 * @param {Object} [containerNode] Optional container node to tie the widget to. 49915 * @memberOf dpage.widgets 49916 * @extends {dpage.widgets.MultiValueWidget} 49917 */ 49918 return dojo.declare("dpage.widgets.Tree", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.Tree.prototype */{ 49919 _initialized: false, 49920 _scriptReady: false, 49921 _jsTreeData: null, 49922 _propId: null, 49923 _propParent: null, 49924 _propText: null, 49925 _enableDragAndDrop: false, 49926 _itemMoveCallback: null, 49927 _itemCheckCallback: null, 49928 _itemSelectCallback: null, 49929 _skipEventOnce: false, 49930 _modelRowLookup: null, 49931 _allIds : null, 49932 49933 constructor: function (options, srcNodeRef) { 49934 var self = this; 49935 49936 if (this._containerNode == null) 49937 this._containerNode = document.createElement("DIV"); 49938 49939 if (options != null) { 49940 if (options.propId != null) 49941 this._propId = options.propId; 49942 49943 if (options.propParent != null) 49944 this._propParent = options.propParent; 49945 49946 if (options.propText != null) 49947 this._propText = options.propText; 49948 49949 if (options.enableDragAndDrop != undefined) 49950 this._enableDragAndDrop = options.enableDragAndDrop; 49951 49952 if (options.itemMoveCallback != undefined) 49953 this._itemMoveCallback = options.itemMoveCallback; 49954 49955 if (options.itemCheckCallback != undefined) 49956 this._itemCheckCallback = options.itemCheckCallback; 49957 49958 if (options.itemSelectCallback != undefined) 49959 this._itemSelectCallback = options.itemSelectCallback; 49960 49961 } 49962 49963 if (this._propId == null || this._propParent == null || this._propText == null) { 49964 throw new Error("You must pass in the propId, propParent, and propText config options."); 49965 } 49966 49967 require([dpage.modules.Config.dpageScriptRoot + "dpage/3p/jstree/jstree.js"], function () { self._jsTreeLoaded(); }); 49968 }, 49969 /* 49970 * Can be overridden to listen to events on the Model. 49971 * @param {String} type CHANGE|ADD|DEL|INS|INVALIDATE 49972 * @param {Object} rowObj The row of data that was altered 49973 * @param {String} dataField The column of data that was changed. 49974 * @returns {void} 49975 */ 49976 _modelChanged: function (type, rowObj, dataField) { 49977 var tree; 49978 var treeNode; 49979 var oldParent; 49980 var newParent; 49981 var treeKey; 49982 49983 treeKey = rowObj[this._propId]; 49984 parentKey = rowObj[this._propParent]; 49985 49986 tree = $(this._containerNode); 49987 49988 if (treeKey == null) 49989 treeKey = "#";
49990 if (parentKey == null) 49991 parentKey = "#"; 49992 49993 treeNode = tree.jstree('get_node', treeKey); 49994 49995 if (type == "CHANGE") { 49996 if (dataField == this._propId) { 49997 throw new Error("You can't change the id property on a row of a TabularModel when bound to a dpage.widgets.Tree for widget id: " + this.getWidgetId()); 49998 } 49999 if (dataField == this._propParent) { 50000 newParent = tree.jstree('get_node', parentKey); 50001 this._skipEventOnce = true; 50002 tree.jstree('move_node' , treeNode , newParent); 50003 } 50004 else if (dataField == this._propText) { 50005 tree.jstree('rename_node',treeNode , rowObj[this._propText]); 50006 } 50007 } 50008 else if (type == "DEL") { 50009 //will not cause a cascading delete, so be aware. 50010 if (treeNode.children.length > 0) 50011 throw new Error("Row that was deleted from model corresponds to a tree node that contains children. This is an error. Delete the children rows first. Tree id: " + this.getWidgetId()); 50012 this._allIds[rowObj[this._propId]] = undefined; 50013 this._modelRowLookup[this.getModel().getDataRowId(rowObj)] = undefined; 50014 tree.jstree('delete_node', treeNode); 50015 } 50016 else if (type == "INS" || type == "ADD") { 50017 50018 //Don't add again. Someone added a row that already exists to the model. 50019 if (this._modelRowLookup[this.getModel().getDataRowId(rowObj)] != null) 50020 return; 50021 50022 if (this._allIds[rowObj[this._propId]] != null) 50023 throw new Error("The " + this._propId + " field on a data row must be unique when bound to a dpage.widgets.Tree for widget id: " + this.getWidgetId()); 50024 50025 this._allIds[rowObj[this._propId]] = 1; 50026 this._modelRowLookup[this.getModel().getDataRowId(rowObj)] = rowObj; 50027 50028 //will not cause a cascading insert. Parent must exist. 50029 var treeDataRow = { 50030 id: rowObj[this._propId], 50031 parent: rowObj[this._propParent] == null ? "#" : rowObj[this._propParent], 50032 text: rowObj[this._propText] 50033 }; 50034 50035 treeDataRow.modelRowId = this.getModel().getDataRowId(rowObj); 50036 newParent = tree.jstree('get_node', parentKey); 50037 tree.jstree('create_node', newParent, treeDataRow); 50038 } 50039 else if (type == "INVALIDATE") { 50040 //at some point we could make this smarter. Right now it redraws the whole tree causing it to collapse and de-select whatever was selected. 50041 this._updateView(); 50042 } 50043 }, 50044 //overridden method on BaseWidget. Gets called when the model is updated on the MultiValueWidget. 50045 _updateView: function () { 50046 var self = this; 50047 50048 if (!this._scriptReady) 50049 return; 50050 50051 if (this._initialized) 50052 $(this._containerNode).jstree('destroy'); 50053 50054 50055 this._bindModelData(); 50056 var config = {}; 50057 50058 config.core = { data: this._jsTreeData }; 50059 50060 config.core.multiple = false; 50061 if (this._enableDragAndDrop) { 50062 config.core.check_callback = function (operation, node, node_parent, node_position, more) { return self._treeCheckCallback(operation, node, node_parent, node_position, more); }; 50063 if (config.plugins == null) 50064 config.plugins = []; 50065 config.plugins.push("dnd"); 50066 } 50067 50068 $(this._containerNode).jstree(config); 50069 50070 $(this._containerNode).bind("select_node.jstree", function (evt, data) { self._itemSelectCallbackInternal(evt, data); }); 50071 50072 this._initialized = true; 50073 50074 }, 50075 //Not meant to be overridden. 50076 _itemSelectCallbackInternal : function(evt , data){ 50077 //call the callback function with the row of data from the item that was selected. 50078 var modelRow = this._modelRowLookup[data.node.original.modelRowId]; 50079 50080 if (this._itemSelectCallback != null) 50081 this._itemSelectCallback(modelRow); 50082 else 50083 this._itemSelected(modelRow); 50084 }, 50085 _treeCheckCallback: function (operation, node, node_parent, node_position, more) { 50086 var parentRow = null; 50087 var itemRow = null; 50088 var ret; 50089 50090 if (this._skipEventOnce) { 50091 this._skipEventOnce = false; 50092 return; 50093 } 50094 50095 if (node_parent.parent != null) 50096 parentRow = this._modelRowLookup[node_parent.original.modelRowId]; 50097 50098 //seems to be the case when moving a node programatically. 50099 if (operation != "move_node") 50100 return true; 50101 50102 itemRow = this._modelRowLookup[node.original.modelRowId]; 50103 50104 if (more.pos == undefined) { 50105 //update the model. This will cause notifications to go out just like they should. 50106 if (parentRow == null) 50107 this.setModelValue(itemRow, this._propParent, null); 50108 else 50109 this.setModelValue(itemRow, this._propParent, parentRow[this._propId]); 50110 50111 //Move. 50112 if (this._itemMoveCallback != null) 50113 return this._itemMoveCallback(itemRow, parentRow); 50114 else 50115 return this._treeItemMoved(itemRow, parentRow); 50116 } 50117 else { 50118 //Check Move. 50119 if (this._itemCheckCallback != null) { 50120 ret = this._itemCheckCallback(itemRow, parentRow); 50121 return ret; 50122 } 50123 else 50124 return this._isTreeItemMoveValid(itemRow, parentRow); 50125 } 50126 }, 50127 //Can be overridden in a sub-class 50128 _itemSelected: function (dataRow) { 50129 50130 }, 50131 _treeItemMoved: function (movingRow, newParentRow) { 50132 }, 50133 _isTreeItemMoveValid: function (movingRow, newParentRow) { 50134 return true; 50135 }, 50136 _bindModelData: function () { 50137 this._jsTreeData = []; 50138 var treeDataRow; 50139 50140 this._modelRowLookup = {}; 50141 this._allIds = {}; 50142 50143 if (this.getModel() == null) 50144 return; 50145 50146 for (var i = 0; i < this.getModel().getRows().length; i++) { 50147 var row = this.getModel().getRows()[i]; 50148 50149 if (this._allIds[row[this._propId]] != null) 50150 throw new Error("Id's must be unique. Found a duplicate value of '" + row[this._propId] + "' in the propId field of '" + this._propId + "' of widget '" + this.getWidgetId()+"'"); 50151 50152 this._allIds[row[this._propId]] = 1; 50153 50154 treeDataRow = { 50155 id: row[this._propId], 50156 parent: row[this._propParent] == null ? "#" : row[this._propParent], 50157 text: row[this._propText] 50158 }; 50159 50160 //store the model row so that we can look it up and access it based on a tree item. 50161 this._modelRowLookup[this.getModel().getDataRowId(row)] = row; 50162 //store the unique model id for the row so that we can access it. 50163 treeDataRow.modelRowId = this.getModel().getDataRowId(row); 50164 50165 this._jsTreeData.push(treeDataRow); 50166 } 50167 }, 50168 50169 _jsTreeLoaded: function () { 50170 this._scriptReady = true; 50171 50172 this._updateView(); 50173 }, 50174 50175 destroy: function () { 50176 if (this._initialized) { 50177 $(this._containerNode).jstree('destroy'); 50178 this._jsTreeData = null; 50179 this._modelRowLookup = null; 50180 this._allIds = null; 50181 } 50182 } 50183 50184 });
50185}); 50186 50187}, 50188'*now':function(r){r(['dojo/i18n!*preload*dpage/nls/dpage*["ar","ca","cs","da","de","el","en-gb","es-es","fi-fi","fr-fr","he-il","hu","it-it","ja-jp","ko-kr","nl-nl","nb","pl","pt-br","pt-pt","ru","sk","sl","sv","th","tr","zh-tw","zh-cn"]']);} 50189}}); 50190(function(){ 50191 // must use this.require to make this work in node.js 50192 var require = this.require; 50193 // consume the cached dojo layer 50194 require({cache:{}}); 50195 !require.async && require(["dojo"]); 50196 require.boot && require.apply(null, require.boot); 50197})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.