window.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojo.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojo.window"] = true;
  8. dojo.provide("dojo.window");
  9. dojo.getObject("window", true, dojo);
  10. dojo.window.getBox = function(){
  11. // summary:
  12. // Returns the dimensions and scroll position of the viewable area of a browser window
  13. var scrollRoot = (dojo.doc.compatMode == 'BackCompat') ? dojo.body() : dojo.doc.documentElement;
  14. // get scroll position
  15. var scroll = dojo._docScroll(); // scrollRoot.scrollTop/Left should work
  16. return { w: scrollRoot.clientWidth, h: scrollRoot.clientHeight, l: scroll.x, t: scroll.y };
  17. };
  18. dojo.window.get = function(doc){
  19. // summary:
  20. // Get window object associated with document doc
  21. // In some IE versions (at least 6.0), document.parentWindow does not return a
  22. // reference to the real window object (maybe a copy), so we must fix it as well
  23. // We use IE specific execScript to attach the real window reference to
  24. // document._parentWindow for later use
  25. if(dojo.isIE && window !== document.parentWindow){
  26. /*
  27. In IE 6, only the variable "window" can be used to connect events (others
  28. may be only copies).
  29. */
  30. doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
  31. //to prevent memory leak, unset it after use
  32. //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
  33. var win = doc._parentWindow;
  34. doc._parentWindow = null;
  35. return win; // Window
  36. }
  37. return doc.parentWindow || doc.defaultView; // Window
  38. };
  39. dojo.window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
  40. // summary:
  41. // Scroll the passed node into view using minimal movement, if it is not already.
  42. // Don't rely on node.scrollIntoView working just because the function is there since
  43. // it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement.
  44. // WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode
  45. // and when there's a fixed position scrollable element
  46. node = dojo.byId(node);
  47. var body, doc = node.ownerDocument || dojo.doc;
  48. // has() functions but without has() support
  49. if(!("rtl_adjust_position_for_verticalScrollBar" in dojo.window)){
  50. body = dojo.body();
  51. var scrollable = dojo.create('div', {
  52. style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'}
  53. }, body, "last"),
  54. div = dojo.create('div', {
  55. style: {overflow:'hidden', direction:'ltr'}
  56. }, scrollable, "last");
  57. dojo.window.rtl_adjust_position_for_verticalScrollBar = dojo.position(div).x != 0;
  58. scrollable.removeChild(div);
  59. body.removeChild(scrollable);
  60. }
  61. if(!("position_fixed_support" in dojo.window)){
  62. // IE6, IE7+quirks, and some older mobile browsers don't support position:fixed
  63. body = dojo.body();
  64. var outer = dojo.create('span', {
  65. style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'}
  66. }, body, "last"),
  67. inner = dojo.create('span', {
  68. style: {position:'fixed', left:'0', top:'0'}
  69. }, outer, "last");
  70. dojo.window.position_fixed_support = dojo.position(inner).x != dojo.position(outer).x;
  71. outer.removeChild(inner);
  72. body.removeChild(outer);
  73. }
  74. try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
  75. body = doc.body || doc.getElementsByTagName("body")[0];
  76. var html = doc.documentElement || body.parentNode,
  77. isIE = dojo.isIE,
  78. isWK = dojo.isWebKit;
  79. // if an untested browser, then use the native method
  80. if(node == body || node == html){ return; }
  81. if(!(dojo.isMozilla || isIE || isWK || dojo.isOpera) && ("scrollIntoView" in node)){
  82. node.scrollIntoView(false); // short-circuit to native if possible
  83. return;
  84. }
  85. var backCompat = doc.compatMode == 'BackCompat',
  86. rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth),
  87. rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight),
  88. scrollRoot = (isWK || backCompat) ? body : html,
  89. nodePos = pos || dojo.position(node),
  90. el = node.parentNode,
  91. isFixed = function(el){
  92. return (isIE <= 6 || (isIE == 7 && backCompat))
  93. ? false
  94. : (dojo.window.position_fixed_support && (dojo.style(el, 'position').toLowerCase() == "fixed"));
  95. };
  96. if(isFixed(node)){ return; } // nothing to do
  97. while(el){
  98. if(el == body){ el = scrollRoot; }
  99. var elPos = dojo.position(el),
  100. fixedPos = isFixed(el),
  101. rtl = dojo.getComputedStyle(el).direction.toLowerCase() == "rtl";
  102. if(el == scrollRoot){
  103. elPos.w = rootWidth; elPos.h = rootHeight;
  104. if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
  105. if(elPos.x < 0 || !isIE || isIE >= 9){ elPos.x = 0; } // older IE can have values > 0
  106. if(elPos.y < 0 || !isIE || isIE >= 9){ elPos.y = 0; }
  107. }else{
  108. var pb = dojo._getPadBorderExtents(el);
  109. elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
  110. var clientSize = el.clientWidth,
  111. scrollBarSize = elPos.w - clientSize;
  112. if(clientSize > 0 && scrollBarSize > 0){
  113. if(rtl && dojo.window.rtl_adjust_position_for_verticalScrollBar){
  114. elPos.x += scrollBarSize;
  115. }
  116. elPos.w = clientSize;
  117. }
  118. clientSize = el.clientHeight;
  119. scrollBarSize = elPos.h - clientSize;
  120. if(clientSize > 0 && scrollBarSize > 0){
  121. elPos.h = clientSize;
  122. }
  123. }
  124. if(fixedPos){ // bounded by viewport, not parents
  125. if(elPos.y < 0){
  126. elPos.h += elPos.y; elPos.y = 0;
  127. }
  128. if(elPos.x < 0){
  129. elPos.w += elPos.x; elPos.x = 0;
  130. }
  131. if(elPos.y + elPos.h > rootHeight){
  132. elPos.h = rootHeight - elPos.y;
  133. }
  134. if(elPos.x + elPos.w > rootWidth){
  135. elPos.w = rootWidth - elPos.x;
  136. }
  137. }
  138. // calculate overflow in all 4 directions
  139. var l = nodePos.x - elPos.x, // beyond left: < 0
  140. // t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
  141. t = nodePos.y - elPos.y, // beyond top: < 0
  142. r = l + nodePos.w - elPos.w, // beyond right: > 0
  143. bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
  144. var s, old;
  145. if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){
  146. s = Math[l < 0? "max" : "min"](l, r);
  147. if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; }
  148. old = el.scrollLeft;
  149. el.scrollLeft += s;
  150. s = el.scrollLeft - old;
  151. nodePos.x -= s;
  152. }
  153. if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){
  154. s = Math.ceil(Math[t < 0? "max" : "min"](t, bot));
  155. old = el.scrollTop;
  156. el.scrollTop += s;
  157. s = el.scrollTop - old;
  158. nodePos.y -= s;
  159. }
  160. el = (el != scrollRoot) && !fixedPos && el.parentNode;
  161. }
  162. }catch(error){
  163. console.error('scrollIntoView: ' + error);
  164. node.scrollIntoView(false);
  165. }
  166. };
  167. }