89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
define("dijit/Viewport", [
|
|
"dojo/Evented",
|
|
"dojo/on",
|
|
"dojo/ready",
|
|
"dojo/sniff",
|
|
"dojo/_base/window", // global
|
|
"dojo/window" // getBox()
|
|
], function(Evented, on, ready, has, win, winUtils){
|
|
|
|
// module:
|
|
// dijit/Viewport
|
|
|
|
/*=====
|
|
return {
|
|
// summary:
|
|
// Utility singleton to watch for viewport resizes, avoiding duplicate notifications
|
|
// which can lead to infinite loops.
|
|
// description:
|
|
// Usage: Viewport.on("resize", myCallback).
|
|
//
|
|
// myCallback() is called without arguments in case it's _WidgetBase.resize(),
|
|
// which would interpret the argument as the size to make the widget.
|
|
};
|
|
=====*/
|
|
|
|
var Viewport = new Evented();
|
|
|
|
var focusedNode;
|
|
|
|
ready(200, function(){
|
|
var oldBox = winUtils.getBox();
|
|
Viewport._rlh = on(win.global, "resize", function(){
|
|
var newBox = winUtils.getBox();
|
|
if(oldBox.h == newBox.h && oldBox.w == newBox.w){ return; }
|
|
oldBox = newBox;
|
|
Viewport.emit("resize");
|
|
});
|
|
|
|
// Also catch zoom changes on IE8, since they don't naturally generate resize events
|
|
if(has("ie") == 8){
|
|
var deviceXDPI = screen.deviceXDPI;
|
|
setInterval(function(){
|
|
if(screen.deviceXDPI != deviceXDPI){
|
|
deviceXDPI = screen.deviceXDPI;
|
|
Viewport.emit("resize");
|
|
}
|
|
}, 500);
|
|
}
|
|
|
|
// On iOS, keep track of the focused node so we can guess when the keyboard is/isn't being displayed.
|
|
if(has("ios")){
|
|
on(document, "focusin", function(evt){
|
|
focusedNode = evt.target;
|
|
});
|
|
on(document, "focusout", function(evt){
|
|
focusedNode = null;
|
|
});
|
|
}
|
|
});
|
|
|
|
Viewport.getEffectiveBox = function(/*Document*/ doc){
|
|
// summary:
|
|
// Get the size of the viewport, or on mobile devices, the part of the viewport not obscured by the
|
|
// virtual keyboard.
|
|
|
|
var box = winUtils.getBox(doc);
|
|
|
|
// Account for iOS virtual keyboard, if it's being shown. Unfortunately no direct way to check or measure.
|
|
var tag = focusedNode && focusedNode.tagName && focusedNode.tagName.toLowerCase();
|
|
if(has("ios") && focusedNode && !focusedNode.readOnly && (tag == "textarea" || (tag == "input" &&
|
|
/^(color|email|number|password|search|tel|text|url)$/.test(focusedNode.type)))){
|
|
|
|
// Box represents the size of the viewport. Some of the viewport is likely covered by the keyboard.
|
|
// Estimate height of visible viewport assuming viewport goes to bottom of screen, but is covered by keyboard.
|
|
box.h *= (orientation == 0 || orientation == 180 ? 0.66 : 0.40);
|
|
|
|
// Above measurement will be inaccurate if viewport was scrolled up so far that it ends before the bottom
|
|
// of the screen. In this case, keyboard isn't covering as much of the viewport as we thought.
|
|
// We know the visible size is at least the distance from the top of the viewport to the focused node.
|
|
var rect = focusedNode.getBoundingClientRect();
|
|
box.h = Math.max(box.h, rect.top + rect.height);
|
|
}
|
|
|
|
return box;
|
|
};
|
|
|
|
return Viewport;
|
|
});
|