Viewport.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. define("dijit/Viewport", [
  2. "dojo/Evented",
  3. "dojo/on",
  4. "dojo/ready",
  5. "dojo/_base/sniff",
  6. "dojo/_base/window", // global
  7. "dojo/window" // getBox()
  8. ], function(Evented, on, ready, has, win, winUtils){
  9. // module:
  10. // dijit/Viewport
  11. /*=====
  12. return {
  13. // summary:
  14. // Utility singleton to watch for viewport resizes, avoiding duplicate notifications
  15. // which can lead to infinite loops.
  16. // description:
  17. // Usage: Viewport.on("resize", myCallback).
  18. //
  19. // myCallback() is called without arguments in case it's _WidgetBase.resize(),
  20. // which would interpret the argument as the size to make the widget.
  21. };
  22. =====*/
  23. var Viewport = new Evented();
  24. var focusedNode;
  25. ready(200, function(){
  26. var oldBox = winUtils.getBox();
  27. Viewport._rlh = on(win.global, "resize", function(){
  28. var newBox = winUtils.getBox();
  29. if(oldBox.h == newBox.h && oldBox.w == newBox.w){ return; }
  30. oldBox = newBox;
  31. Viewport.emit("resize");
  32. });
  33. // Also catch zoom changes on IE8, since they don't naturally generate resize events
  34. if(has("ie") == 8){
  35. var deviceXDPI = screen.deviceXDPI;
  36. setInterval(function(){
  37. if(screen.deviceXDPI != deviceXDPI){
  38. deviceXDPI = screen.deviceXDPI;
  39. Viewport.emit("resize");
  40. }
  41. }, 500);
  42. }
  43. // On iOS, keep track of the focused node so we can guess when the keyboard is/isn't being displayed.
  44. if(has("ios")){
  45. on(document, "focusin", function(evt){
  46. focusedNode = evt.target;
  47. });
  48. on(document, "focusout", function(evt){
  49. focusedNode = null;
  50. });
  51. }
  52. });
  53. Viewport.getEffectiveBox = function(/*Document*/ doc){
  54. // summary:
  55. // Get the size of the viewport, or on mobile devices, the part of the viewport not obscured by the
  56. // virtual keyboard.
  57. var box = winUtils.getBox(doc);
  58. // Account for iOS virtual keyboard, if it's being shown. Unfortunately no direct way to check or measure.
  59. var tag = focusedNode && focusedNode.tagName && focusedNode.tagName.toLowerCase();
  60. if(has("ios") && focusedNode && !focusedNode.readOnly && (tag == "textarea" || (tag == "input" &&
  61. /^(color|email|number|password|search|tel|text|url)$/.test(focusedNode.type)))){
  62. // Box represents the size of the viewport. Some of the viewport is likely covered by the keyboard.
  63. // Estimate height of visible viewport assuming viewport goes to bottom of screen, but is covered by keyboard.
  64. box.h *= (orientation == 0 || orientation == 180 ? 0.66 : 0.40);
  65. // Above measurement will be inaccurate if viewport was scrolled up so far that it ends before the bottom
  66. // of the screen. In this case, keyboard isn't covering as much of the viewport as we thought.
  67. // We know the visible size is at least the distance from the top of the viewport to the focused node.
  68. var rect = focusedNode.getBoundingClientRect();
  69. box.h = Math.max(box.h, rect.top + rect.height);
  70. }
  71. return box;
  72. };
  73. return Viewport;
  74. });