Standby.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. define("dojox/widget/Standby", ["dojo/_base/kernel",
  2. "dojo/_base/declare",
  3. "dojo/_base/array",
  4. "dojo/_base/event",
  5. "dojo/_base/sniff",
  6. "dojo/dom",
  7. "dojo/dom-attr",
  8. "dojo/dom-construct",
  9. "dojo/dom-geometry",
  10. "dojo/dom-style",
  11. "dojo/window",
  12. "dojo/_base/window",
  13. "dojo/_base/fx",
  14. "dojo/fx",
  15. "dijit/_Widget",
  16. "dijit/_TemplatedMixin",
  17. "dijit/registry"],
  18. function(kernel,
  19. declare,
  20. array,
  21. event,
  22. has,
  23. dom,
  24. attr,
  25. construct,
  26. geometry,
  27. domStyle,
  28. window,
  29. baseWindow,
  30. baseFx,
  31. fx,
  32. _Widget,
  33. _TemplatedMixin,
  34. registry) {
  35. kernel.experimental("dojox.widget.Standby");
  36. return declare("dojox.widget.Standby", [_Widget, _TemplatedMixin],{
  37. // summary:
  38. // A widget designed to act as a Standby/Busy/Disable/Blocking widget to indicate a
  39. // particular DOM node is processing and cannot be clicked on at this time.
  40. // This widget uses absolute positioning to apply the overlay and image.
  41. //
  42. // image:
  43. // A URL to an image to center within the blocking overlay.
  44. // The default is a basic spinner.
  45. //
  46. // imageText:
  47. // Text to set on the ALT tag of the image.
  48. // The default is 'Please wait...'
  49. //
  50. // text:
  51. // Text to display in the center instead of an image.
  52. // Defaults to 'Please Wait...'
  53. //
  54. // centerIndicator:
  55. // Which to use as the center info, the text or the image.
  56. // Defaults to image.
  57. //
  58. // color:
  59. // The color to use for the translucent overlay.
  60. // Text string such as: darkblue, #FE02FD, etc.
  61. //
  62. // duration:
  63. // How long the fade in and out effects should run in milliseconds.
  64. // Default is 500ms
  65. //
  66. // zIndex:
  67. // Control that lets you specify if the zIndex for the overlay
  68. // should be auto-computed based off parent zIndex, or should be set
  69. // to a particular value. This is useful when you want to overlay
  70. // things in digit.Dialogs, you can specify a base zIndex to append from.
  71. // Default is 'auto'.
  72. // templateString: [protected] String
  73. // The template string defining out the basics of the widget. No need for an external
  74. // file.
  75. templateString:
  76. "<div>" +
  77. "<div style=\"display: none; opacity: 0; z-index: 9999; " +
  78. "position: absolute; cursor:wait;\" dojoAttachPoint=\"_underlayNode\"></div>" +
  79. "<img src=\"${image}\" style=\"opacity: 0; display: none; z-index: -10000; " +
  80. "position: absolute; top: 0px; left: 0px; cursor:wait;\" "+
  81. "dojoAttachPoint=\"_imageNode\">" +
  82. "<div style=\"opacity: 0; display: none; z-index: -10000; position: absolute; " +
  83. "top: 0px;\" dojoAttachPoint=\"_textNode\"></div>" +
  84. "</div>",
  85. // _underlayNode: [private] DOMNode
  86. // The node that is the translucent underlay for the
  87. // image that blocks access to the target.
  88. _underlayNode: null,
  89. // _imageNode: [private] DOMNode
  90. // The image node where we attach and define the image to display.
  91. _imageNode: null,
  92. // _textNode: [private] DOMNode
  93. // The div to attach text/HTML in the overlay center item.
  94. _textNode: null,
  95. // _centerNode: [private] DOMNode
  96. // Which node to use as the center node, the image or the text node.
  97. _centerNode: null,
  98. // image: String
  99. // The URL to the image to center in the overlay.
  100. image: require.toUrl("dojox/widget/Standby/images/loading.gif").toString(),
  101. // imageText: String
  102. // Text for the ALT tag.
  103. imageText: "Please Wait...", // TODO: i18n
  104. // text: String
  105. // Text/HTML to display in the center of the overlay
  106. // This is used if image center is disabled.
  107. text: "Please wait...",
  108. // centerIndicator: String
  109. // Property to define if the image and its alt text should be used, or
  110. // a simple Text/HTML node should be used. Allowable values are 'image'
  111. // and 'text'.
  112. // Default is 'image'.
  113. centerIndicator: "image",
  114. // _displayed: [private] Boolean
  115. // Flag to indicate if the overlay is displayed or not.
  116. _displayed: false,
  117. // _resizeCheck: [private] Object
  118. // Handle to interval function that checks the target for changes.
  119. _resizeCheck: null,
  120. // target: DOMNode||DOMID(String)||WidgetID(String)
  121. // The target to overlay when active. Can be a widget id, a
  122. // dom id, or a direct node reference.
  123. target: "",
  124. // color: String
  125. // The color to set the overlay. Should be in #XXXXXX form.
  126. // Default color for the translucent overlay is light gray.
  127. color: "#C0C0C0",
  128. // duration: integer
  129. // Integer defining how long the show and hide effects should take.
  130. duration: 500,
  131. // _started: [private] Boolean
  132. // Trap flag to ensure startup only processes once.
  133. _started: false,
  134. // _parent: [private] DOMNode
  135. // Wrapping div for the widget, also used for IE 7 in dealing with the
  136. // zoom issue.
  137. _parent: null,
  138. // zIndex: String
  139. // Control that lets you specify if the zIndex for the overlay
  140. // should be auto-computed based off parent zIndex, or should be set
  141. // to a particular value. This is useful when you want to overlay
  142. // things in digit.Dialogs, you can specify a base zIndex to append from.
  143. zIndex: "auto",
  144. startup: function(args){
  145. // summary:
  146. // Over-ride of the basic widget startup function.
  147. // Configures the target node and sets the image to use.
  148. if(!this._started){
  149. if(typeof this.target === "string"){
  150. var w = registry.byId(this.target);
  151. this.target = w ? w.domNode : dom.byId(this.target);
  152. }
  153. if(this.text){
  154. this._textNode.innerHTML = this.text;
  155. }
  156. if(this.centerIndicator === "image"){
  157. this._centerNode = this._imageNode;
  158. attr.set(this._imageNode, "src", this.image);
  159. attr.set(this._imageNode, "alt", this.imageText);
  160. }else{
  161. this._centerNode = this._textNode;
  162. }
  163. domStyle.set(this._underlayNode, {
  164. display: "none",
  165. backgroundColor: this.color
  166. });
  167. domStyle.set(this._centerNode, "display", "none");
  168. this.connect(this._underlayNode, "onclick", "_ignore");
  169. //Last thing to do is move the widgets parent, if any, to the current document body.
  170. //Avoids having to deal with parent relative/absolute mess. Otherwise positioning
  171. //tends to go goofy.
  172. if(this.domNode.parentNode && this.domNode.parentNode != baseWindow.body()){
  173. baseWindow.body().appendChild(this.domNode);
  174. }
  175. //IE 7 has a horrible bug with zoom, so we have to create this node
  176. //to cross-check later. Sigh.
  177. if(has("ie") == 7){
  178. this._ieFixNode = construct.create("div");
  179. domStyle.set(this._ieFixNode, {
  180. opacity: "0",
  181. zIndex: "-1000",
  182. position: "absolute",
  183. top: "-1000px"
  184. });
  185. baseWindow.body().appendChild(this._ieFixNode);
  186. }
  187. this.inherited(arguments);
  188. }
  189. },
  190. show: function(){
  191. // summary:
  192. // Function to display the blocking overlay and busy/status icon or text.
  193. if(!this._displayed){
  194. if(this._anim){
  195. this._anim.stop();
  196. delete this._anim;
  197. }
  198. this._displayed = true;
  199. this._size();
  200. this._disableOverflow();
  201. this._fadeIn();
  202. }
  203. },
  204. hide: function(){
  205. // summary:
  206. // Function to hide the blocking overlay and status icon or text.
  207. if(this._displayed){
  208. if(this._anim){
  209. this._anim.stop();
  210. delete this._anim;
  211. }
  212. this._size();
  213. this._fadeOut();
  214. this._displayed = false;
  215. if(this._resizeCheck !== null){
  216. clearInterval(this._resizeCheck);
  217. this._resizeCheck = null;
  218. }
  219. }
  220. },
  221. isVisible: function(){
  222. // summary:
  223. // Helper function so you can test if the widget is already visible or not.
  224. // returns:
  225. // boolean indicating if the widget is in 'show' state or not.
  226. return this._displayed; // boolean
  227. },
  228. onShow: function(){
  229. // summary:
  230. // Event that fires when the display of the Standby completes.
  231. },
  232. onHide: function(){
  233. // summary:
  234. // Event that fires when the display of the Standby completes.
  235. },
  236. uninitialize: function(){
  237. // summary:
  238. // Over-ride to hide the widget, which clears intervals, before cleanup.
  239. this._displayed = false;
  240. if(this._resizeCheck){
  241. clearInterval(this._resizeCheck);
  242. }
  243. domStyle.set(this._centerNode, "display", "none");
  244. domStyle.set(this._underlayNode, "display", "none");
  245. if(has("ie") == 7 && this._ieFixNode){
  246. baseWindow.body().removeChild(this._ieFixNode);
  247. delete this._ieFixNode;
  248. }
  249. if(this._anim){
  250. this._anim.stop();
  251. delete this._anim;
  252. }
  253. this.target = null;
  254. this._imageNode = null;
  255. this._textNode = null;
  256. this._centerNode = null;
  257. this.inherited(arguments);
  258. },
  259. _size: function(){
  260. // summary:
  261. // Internal function that handles resizing the overlay and
  262. // centering of the image on window resizing.
  263. // tags:
  264. // private
  265. if(this._displayed){
  266. var dir = attr.get(baseWindow.body(), "dir");
  267. if(dir){dir = dir.toLowerCase();}
  268. var _ie7zoom;
  269. var scrollers = this._scrollerWidths();
  270. var target = this.target;
  271. //Show the image and make sure the zIndex is set high.
  272. var curStyle = domStyle.get(this._centerNode, "display");
  273. domStyle.set(this._centerNode, "display", "block");
  274. var box = geometry.position(target, true);
  275. if(target === baseWindow.body() || target === baseWindow.doc){
  276. // Target is the whole doc, so scale to viewport.
  277. box = window.getBox();
  278. box.x = box.l;
  279. box.y = box.t;
  280. }
  281. var cntrIndicator = geometry.getMarginBox(this._centerNode);
  282. domStyle.set(this._centerNode, "display", curStyle);
  283. //IE has a horrible zoom bug. So, we have to try and account for
  284. //it and fix up the scaling.
  285. if(this._ieFixNode){
  286. _ie7zoom = -this._ieFixNode.offsetTop / 1000;
  287. box.x = Math.floor((box.x + 0.9) / _ie7zoom);
  288. box.y = Math.floor((box.y + 0.9) / _ie7zoom);
  289. box.w = Math.floor((box.w + 0.9) / _ie7zoom);
  290. box.h = Math.floor((box.h + 0.9) / _ie7zoom);
  291. }
  292. //Figure out how to zIndex this thing over the target.
  293. var zi = domStyle.get(target, "zIndex");
  294. var ziUl = zi;
  295. var ziIn = zi;
  296. if(this.zIndex === "auto"){
  297. if(zi != "auto"){
  298. ziUl = parseInt(ziUl, 10) + 1;
  299. ziIn = parseInt(ziIn, 10) + 2;
  300. }else{
  301. //We need to search up the chain to see if there
  302. //are any parent zIndexs to overlay.
  303. var cNode = target.parentNode;
  304. var oldZi = -100000;
  305. while(cNode && cNode !== baseWindow.body()){
  306. zi = domStyle.get(cNode, "zIndex");
  307. if(!zi || zi === "auto"){
  308. cNode = cNode.parentNode;
  309. }else{
  310. var newZi = parseInt(zi, 10);
  311. if(oldZi < newZi){
  312. oldZi = newZi;
  313. ziUl = newZi + 1;
  314. ziIn = newZi + 2;
  315. }
  316. // Keep looking until we run out, we want the highest zIndex.
  317. cNode = cNode.parentNode;
  318. }
  319. }
  320. }
  321. }else{
  322. ziUl = parseInt(this.zIndex, 10) + 1;
  323. ziIn = parseInt(this.zIndex, 10) + 2;
  324. }
  325. domStyle.set(this._centerNode, "zIndex", ziIn);
  326. domStyle.set(this._underlayNode, "zIndex", ziUl);
  327. var pn = target.parentNode;
  328. if(pn && pn !== baseWindow.body() &&
  329. target !== baseWindow.body() &&
  330. target !== baseWindow.doc){
  331. // If the parent is the body tag itself,
  332. // we can avoid all this, the body takes
  333. // care of overflow for me. Besides, browser
  334. // weirdness with height and width on body causes
  335. // problems with this sort of intersect testing
  336. // anyway.
  337. var obh = box.h;
  338. var obw = box.w;
  339. var pnBox = geometry.position(pn, true);
  340. //More IE zoom corrections. Grr.
  341. if(this._ieFixNode){
  342. _ie7zoom = -this._ieFixNode.offsetTop / 1000;
  343. pnBox.x = Math.floor((pnBox.x + 0.9) / _ie7zoom);
  344. pnBox.y = Math.floor((pnBox.y + 0.9) / _ie7zoom);
  345. pnBox.w = Math.floor((pnBox.w + 0.9) / _ie7zoom);
  346. pnBox.h = Math.floor((pnBox.h + 0.9) / _ie7zoom);
  347. }
  348. //Shift the parent width/height a bit if scollers are present.
  349. pnBox.w -= pn.scrollHeight > pn.clientHeight &&
  350. pn.clientHeight > 0 ? scrollers.v: 0;
  351. pnBox.h -= pn.scrollWidth > pn.clientWidth &&
  352. pn.clientWidth > 0 ? scrollers.h: 0;
  353. //RTL requires a bit of massaging in some cases
  354. //(and differently depending on browser, ugh!)
  355. //WebKit and others still need work.
  356. if(dir === "rtl"){
  357. if(has("opera")){
  358. box.x += pn.scrollHeight > pn.clientHeight &&
  359. pn.clientHeight > 0 ? scrollers.v: 0;
  360. pnBox.x += pn.scrollHeight > pn.clientHeight &&
  361. pn.clientHeight > 0 ? scrollers.v: 0;
  362. }else if(has("ie")){
  363. pnBox.x += pn.scrollHeight > pn.clientHeight &&
  364. pn.clientHeight > 0 ? scrollers.v: 0;
  365. }else if(has("webkit")){
  366. //TODO: FIX THIS!
  367. }
  368. }
  369. //Figure out if we need to adjust the overlay to fit a viewable
  370. //area, then resize it, we saved the original height/width above.
  371. //This is causing issues on IE. Argh!
  372. if(pnBox.w < box.w){
  373. //Scale down the width if necessary.
  374. box.w = box.w - pnBox.w;
  375. }
  376. if(pnBox.h < box.h){
  377. //Scale down the width if necessary.
  378. box.h = box.h - pnBox.h;
  379. }
  380. //Look at the y positions and see if we intersect with the
  381. //viewport borders. Will have to do computations off it.
  382. var vpTop = pnBox.y;
  383. var vpBottom = pnBox.y + pnBox.h;
  384. var bTop = box.y;
  385. var bBottom = box.y + obh;
  386. var vpLeft = pnBox.x;
  387. var vpRight = pnBox.x + pnBox.w;
  388. var bLeft = box.x;
  389. var bRight = box.x + obw;
  390. var delta;
  391. //Adjust the height now
  392. if(bBottom > vpTop &&
  393. bTop < vpTop){
  394. box.y = pnBox.y;
  395. //intersecting top, need to do some shifting.
  396. delta = vpTop - bTop;
  397. var visHeight = obh - delta;
  398. //If the visible height < viewport height,
  399. //We need to shift it.
  400. if(visHeight < pnBox.h){
  401. box.h = visHeight;
  402. }else{
  403. //Deal with horizontal scrollbars if necessary.
  404. box.h -= 2*(pn.scrollWidth > pn.clientWidth &&
  405. pn.clientWidth > 0? scrollers.h: 0);
  406. }
  407. }else if(bTop < vpBottom && bBottom > vpBottom){
  408. //Intersecting bottom, just figure out how much
  409. //overlay to show.
  410. box.h = vpBottom - bTop;
  411. }else if(bBottom <= vpTop || bTop >= vpBottom){
  412. //Outside view, hide it.
  413. box.h = 0;
  414. }
  415. //adjust width
  416. if(bRight > vpLeft && bLeft < vpLeft){
  417. box.x = pnBox.x;
  418. //intersecting left, need to do some shifting.
  419. delta = vpLeft - bLeft;
  420. var visWidth = obw - delta;
  421. //If the visible width < viewport width,
  422. //We need to shift it.
  423. if(visWidth < pnBox.w){
  424. box.w = visWidth;
  425. }else{
  426. //Deal with horizontal scrollbars if necessary.
  427. box.w -= 2*(pn.scrollHeight > pn.clientHeight &&
  428. pn.clientHeight > 0? scrollers.w:0);
  429. }
  430. }else if(bLeft < vpRight && bRight > vpRight){
  431. //Intersecting right, just figure out how much
  432. //overlay to show.
  433. box.w = vpRight - bLeft;
  434. }else if(bRight <= vpLeft || bLeft >= vpRight){
  435. //Outside view, hide it.
  436. box.w = 0;
  437. }
  438. }
  439. if(box.h > 0 && box.w > 0){
  440. //Set position and size of the blocking div overlay.
  441. domStyle.set(this._underlayNode, {
  442. display: "block",
  443. width: box.w + "px",
  444. height: box.h + "px",
  445. top: box.y + "px",
  446. left: box.x + "px"
  447. });
  448. var styles = ["borderRadius", "borderTopLeftRadius",
  449. "borderTopRightRadius","borderBottomLeftRadius",
  450. "borderBottomRightRadius"];
  451. this._cloneStyles(styles);
  452. if(!has("ie")){
  453. //Browser specific styles to try and clone if non-IE.
  454. styles = ["MozBorderRadius", "MozBorderRadiusTopleft",
  455. "MozBorderRadiusTopright","MozBorderRadiusBottomleft",
  456. "MozBorderRadiusBottomright","WebkitBorderRadius",
  457. "WebkitBorderTopLeftRadius", "WebkitBorderTopRightRadius",
  458. "WebkitBorderBottomLeftRadius","WebkitBorderBottomRightRadius"
  459. ];
  460. this._cloneStyles(styles, this);
  461. }
  462. var cntrIndicatorTop = (box.h/2) - (cntrIndicator.h/2);
  463. var cntrIndicatorLeft = (box.w/2) - (cntrIndicator.w/2);
  464. //Only show the image if there is height and width room.
  465. if(box.h >= cntrIndicator.h && box.w >= cntrIndicator.w){
  466. domStyle.set(this._centerNode, {
  467. top: (cntrIndicatorTop + box.y) + "px",
  468. left: (cntrIndicatorLeft + box.x) + "px",
  469. display: "block"
  470. });
  471. }else{
  472. domStyle.set(this._centerNode, "display", "none");
  473. }
  474. }else{
  475. //Target has no size, display nothing on it!
  476. domStyle.set(this._underlayNode, "display", "none");
  477. domStyle.set(this._centerNode, "display", "none");
  478. }
  479. if(this._resizeCheck === null){
  480. //Set an interval timer that checks the target size and scales as needed.
  481. //Checking every 10th of a second seems to generate a fairly smooth update.
  482. var self = this;
  483. this._resizeCheck = setInterval(function(){self._size();}, 100);
  484. }
  485. }
  486. },
  487. _cloneStyles: function(list){
  488. // summary:
  489. // Internal function to clone a set of styles from the target to
  490. // the underlay.
  491. // list: Array
  492. // An array of style names to clone.
  493. //
  494. // tags:
  495. // private
  496. array.forEach(list, function(s){
  497. domStyle.set(this._underlayNode, s, domStyle.get(this.target, s));
  498. }, this);
  499. },
  500. _fadeIn: function(){
  501. // summary:
  502. // Internal function that does the opacity style fade in animation.
  503. // tags:
  504. // private
  505. var self = this;
  506. var underlayNodeAnim = baseFx.animateProperty({
  507. duration: self.duration,
  508. node: self._underlayNode,
  509. properties: {opacity: {start: 0, end: 0.75}}
  510. });
  511. var imageAnim = baseFx.animateProperty({
  512. duration: self.duration,
  513. node: self._centerNode,
  514. properties: {opacity: {start: 0, end: 1}},
  515. onEnd: function(){
  516. self.onShow();
  517. delete self._anim;
  518. }
  519. });
  520. this._anim = fx.combine([underlayNodeAnim,imageAnim]);
  521. this._anim.play();
  522. },
  523. _fadeOut: function(){
  524. // summary:
  525. // Internal function that does the opacity style fade out animation.
  526. // tags:
  527. // private
  528. var self = this;
  529. var underlayNodeAnim = baseFx.animateProperty({
  530. duration: self.duration,
  531. node: self._underlayNode,
  532. properties: {opacity: {start: 0.75, end: 0}},
  533. onEnd: function(){
  534. domStyle.set(this.node,{"display":"none", "zIndex": "-1000"});
  535. }
  536. });
  537. var imageAnim = baseFx.animateProperty({
  538. duration: self.duration,
  539. node: self._centerNode,
  540. properties: {opacity: {start: 1, end: 0}},
  541. onEnd: function(){
  542. domStyle.set(this.node,{"display":"none", "zIndex": "-1000"});
  543. self.onHide();
  544. self._enableOverflow();
  545. delete self._anim;
  546. }
  547. });
  548. this._anim = fx.combine([underlayNodeAnim,imageAnim]);
  549. this._anim.play();
  550. },
  551. _ignore: function(e){
  552. // summary:
  553. // Function to ignore events that occur on the overlay.
  554. // event: Event
  555. // The event to halt
  556. // tags:
  557. // private
  558. if(e){
  559. event.stop(e);
  560. }
  561. },
  562. _scrollerWidths: function(){
  563. // summary:
  564. // This function will calculate the size of the vertical and
  565. // horizontaol scrollbars.
  566. // returns:
  567. // Object of form: {v: Number, h: Number} where v is vertical scrollbar width
  568. // and h is horizontal scrollbar width.
  569. // tags:
  570. // private
  571. var div = construct.create("div");
  572. domStyle.set(div, {
  573. position: "absolute",
  574. opacity: 0,
  575. overflow: "hidden",
  576. width: "50px",
  577. height: "50px",
  578. zIndex: "-100",
  579. top: "-200px",
  580. padding: "0px",
  581. margin: "0px"
  582. });
  583. var iDiv = construct.create("div");
  584. domStyle.set(iDiv, {
  585. width: "200px",
  586. height: "10px"
  587. });
  588. div.appendChild(iDiv);
  589. baseWindow.body().appendChild(div);
  590. //Figure out content size before and after
  591. //scrollbars are there, then just subtract to
  592. //get width.
  593. var b = geometry.getContentBox(div);
  594. domStyle.set(div, "overflow", "scroll");
  595. var a = geometry.getContentBox(div);
  596. baseWindow.body().removeChild(div);
  597. return { v: b.w - a.w, h: b.h - a.h };
  598. },
  599. /* The following are functions that tie into _Widget.attr() */
  600. _setTextAttr: function(text){
  601. // summary:
  602. // Function to allow widget.attr to set the text displayed in center
  603. // if using text display.
  604. // text: String
  605. // The text to set.
  606. this._textNode.innerHTML = text;
  607. this.text = text;
  608. },
  609. _setColorAttr: function(c){
  610. // summary:
  611. // Function to allow widget.attr to set the color used for the translucent
  612. // div overlay.
  613. // c: String
  614. // The color to set the background underlay to in #XXXXXX format..
  615. domStyle.set(this._underlayNode, "backgroundColor", c);
  616. this.color = c;
  617. },
  618. _setImageTextAttr: function(text){
  619. // summary:
  620. // Function to allow widget.attr to set the ALT text text displayed for
  621. // the image (if using image center display).
  622. // text: String
  623. // The text to set.
  624. attr.set(this._imageNode, "alt", text);
  625. this.imageText = text;
  626. },
  627. _setImageAttr: function(url){
  628. // summary:
  629. // Function to allow widget.attr to set the url source for the center image
  630. // text: String
  631. // The url to set for the image.
  632. attr.set(this._imageNode, "src", url);
  633. this.image = url;
  634. },
  635. _setCenterIndicatorAttr: function(indicator){
  636. // summary:
  637. // Function to allow widget.attr to set the node used for the center indicator,
  638. // either the image or the text.
  639. // indicator: String
  640. // The indicator to use, either 'image' or 'text'.
  641. this.centerIndicator = indicator;
  642. if(indicator === "image"){
  643. this._centerNode = this._imageNode;
  644. domStyle.set(this._textNode, "display", "none");
  645. }else{
  646. this._centerNode = this._textNode;
  647. domStyle.set(this._imageNode, "display", "none");
  648. }
  649. },
  650. _disableOverflow: function(){
  651. // summary:
  652. // Function to disable scrollbars on the body. Only used if the overlay
  653. // targets the body or the document.
  654. if(this.target === baseWindow.body() || this.target === baseWindow.doc){
  655. // Store the overflow state we have to restore later.
  656. // IE had issues, so have to check that it's defined. Ugh.
  657. this._overflowDisabled = true;
  658. var body = baseWindow.body();
  659. if(body.style && body.style.overflow){
  660. this._oldOverflow = domStyle.get(body, "overflow");
  661. }else{
  662. this._oldOverflow = "";
  663. }
  664. if(has("ie") && !has("quirks")){
  665. // IE will put scrollbars in anyway, html (parent of body)
  666. // also controls them in standards mode, so we have to
  667. // remove them, argh.
  668. if(body.parentNode &&
  669. body.parentNode.style &&
  670. body.parentNode.style.overflow){
  671. this._oldBodyParentOverflow = body.parentNode.style.overflow;
  672. }else{
  673. try{
  674. this._oldBodyParentOverflow = domStyle.get(body.parentNode, "overflow");
  675. }catch(e){
  676. this._oldBodyParentOverflow = "scroll";
  677. }
  678. }
  679. domStyle.set(body.parentNode, "overflow", "hidden");
  680. }
  681. domStyle.set(body, "overflow", "hidden");
  682. }
  683. },
  684. _enableOverflow: function(){
  685. // summary:
  686. // Function to restore scrollbars on the body. Only used if the overlay
  687. // targets the body or the document.
  688. if(this._overflowDisabled){
  689. delete this._overflowDisabled;
  690. var body = baseWindow.body();
  691. // Restore all the overflow.
  692. if(has("ie") && !has("quirks")){
  693. body.parentNode.style.overflow = this._oldBodyParentOverflow;
  694. delete this._oldBodyParentOverflow;
  695. }
  696. domStyle.set(body, "overflow", this._oldOverflow);
  697. if(has("webkit")){
  698. //Gotta poke WebKit, or scrollers don't come back. :-(
  699. var div = construct.create("div", { style: {
  700. height: "2px"
  701. }
  702. });
  703. body.appendChild(div);
  704. setTimeout(function(){
  705. body.removeChild(div);
  706. }, 0);
  707. }
  708. delete this._oldOverflow;
  709. }
  710. }
  711. });
  712. });