viewportsizemonitor.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2007 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Utility class that monitors viewport size changes.
  16. *
  17. * @author attila@google.com (Attila Bodis)
  18. * @see ../demos/viewportsizemonitor.html
  19. */
  20. goog.provide('goog.dom.ViewportSizeMonitor');
  21. goog.require('goog.dom');
  22. goog.require('goog.events');
  23. goog.require('goog.events.EventTarget');
  24. goog.require('goog.events.EventType');
  25. goog.require('goog.math.Size');
  26. /**
  27. * This class can be used to monitor changes in the viewport size. Instances
  28. * dispatch a {@link goog.events.EventType.RESIZE} event when the viewport size
  29. * changes. Handlers can call {@link goog.dom.ViewportSizeMonitor#getSize} to
  30. * get the new viewport size.
  31. *
  32. * Use this class if you want to execute resize/reflow logic each time the
  33. * user resizes the browser window. This class is guaranteed to only dispatch
  34. * {@code RESIZE} events when the pixel dimensions of the viewport change.
  35. * (Internet Explorer fires resize events if any element on the page is resized,
  36. * even if the viewport dimensions are unchanged, which can lead to infinite
  37. * resize loops.)
  38. *
  39. * Example usage:
  40. * <pre>
  41. * var vsm = new goog.dom.ViewportSizeMonitor();
  42. * goog.events.listen(vsm, goog.events.EventType.RESIZE, function(e) {
  43. * alert('Viewport size changed to ' + vsm.getSize());
  44. * });
  45. * </pre>
  46. *
  47. * Manually verified on IE6, IE7, FF2, Opera 11, Safari 4 and Chrome.
  48. *
  49. * @param {Window=} opt_window The window to monitor; defaults to the window in
  50. * which this code is executing.
  51. * @constructor
  52. * @extends {goog.events.EventTarget}
  53. */
  54. goog.dom.ViewportSizeMonitor = function(opt_window) {
  55. goog.dom.ViewportSizeMonitor.base(this, 'constructor');
  56. /**
  57. * The window to monitor. Defaults to the window in which the code is running.
  58. * @private {Window}
  59. */
  60. this.window_ = opt_window || window;
  61. /**
  62. * Event listener key for window the window resize handler, as returned by
  63. * {@link goog.events.listen}.
  64. * @private {goog.events.Key}
  65. */
  66. this.listenerKey_ = goog.events.listen(
  67. this.window_, goog.events.EventType.RESIZE, this.handleResize_, false,
  68. this);
  69. /**
  70. * The most recently recorded size of the viewport, in pixels.
  71. * @private {goog.math.Size}
  72. */
  73. this.size_ = goog.dom.getViewportSize(this.window_);
  74. };
  75. goog.inherits(goog.dom.ViewportSizeMonitor, goog.events.EventTarget);
  76. /**
  77. * Returns a viewport size monitor for the given window. A new one is created
  78. * if it doesn't exist already. This prevents the unnecessary creation of
  79. * multiple spooling monitors for a window.
  80. * @param {Window=} opt_window The window to monitor; defaults to the window in
  81. * which this code is executing.
  82. * @return {!goog.dom.ViewportSizeMonitor} Monitor for the given window.
  83. */
  84. goog.dom.ViewportSizeMonitor.getInstanceForWindow = function(opt_window) {
  85. var currentWindow = opt_window || window;
  86. var uid = goog.getUid(currentWindow);
  87. return goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] =
  88. goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] ||
  89. new goog.dom.ViewportSizeMonitor(currentWindow);
  90. };
  91. /**
  92. * Removes and disposes a viewport size monitor for the given window if one
  93. * exists.
  94. * @param {Window=} opt_window The window whose monitor should be removed;
  95. * defaults to the window in which this code is executing.
  96. */
  97. goog.dom.ViewportSizeMonitor.removeInstanceForWindow = function(opt_window) {
  98. var uid = goog.getUid(opt_window || window);
  99. goog.dispose(goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid]);
  100. delete goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid];
  101. };
  102. /**
  103. * Map of window hash code to viewport size monitor for that window, if
  104. * created.
  105. * @type {Object<number,goog.dom.ViewportSizeMonitor>}
  106. * @private
  107. */
  108. goog.dom.ViewportSizeMonitor.windowInstanceMap_ = {};
  109. /**
  110. * Returns the most recently recorded size of the viewport, in pixels. May
  111. * return null if no window resize event has been handled yet.
  112. * @return {goog.math.Size} The viewport dimensions, in pixels.
  113. */
  114. goog.dom.ViewportSizeMonitor.prototype.getSize = function() {
  115. // Return a clone instead of the original to preserve encapsulation.
  116. return this.size_ ? this.size_.clone() : null;
  117. };
  118. /** @override */
  119. goog.dom.ViewportSizeMonitor.prototype.disposeInternal = function() {
  120. goog.dom.ViewportSizeMonitor.superClass_.disposeInternal.call(this);
  121. if (this.listenerKey_) {
  122. goog.events.unlistenByKey(this.listenerKey_);
  123. this.listenerKey_ = null;
  124. }
  125. this.window_ = null;
  126. this.size_ = null;
  127. };
  128. /**
  129. * Handles window resize events by measuring the dimensions of the
  130. * viewport and dispatching a {@link goog.events.EventType.RESIZE} event if the
  131. * current dimensions are different from the previous ones.
  132. * @param {goog.events.Event} event The window resize event to handle.
  133. * @private
  134. */
  135. goog.dom.ViewportSizeMonitor.prototype.handleResize_ = function(event) {
  136. var size = goog.dom.getViewportSize(this.window_);
  137. if (!goog.math.Size.equals(size, this.size_)) {
  138. this.size_ = size;
  139. this.dispatchEvent(goog.events.EventType.RESIZE);
  140. }
  141. };