fontsizemonitor.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2005 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 A class that can be used to listen to font size changes.
  16. * @author arv@google.com (Erik Arvidsson)
  17. */
  18. goog.provide('goog.dom.FontSizeMonitor');
  19. goog.provide('goog.dom.FontSizeMonitor.EventType');
  20. goog.require('goog.dom');
  21. goog.require('goog.dom.TagName');
  22. goog.require('goog.events');
  23. goog.require('goog.events.EventTarget');
  24. goog.require('goog.events.EventType');
  25. goog.require('goog.userAgent');
  26. // TODO(arv): Move this to goog.events instead.
  27. /**
  28. * This class can be used to monitor changes in font size. Instances will
  29. * dispatch a {@code goog.dom.FontSizeMonitor.EventType.CHANGE} event.
  30. * Example usage:
  31. * <pre>
  32. * var fms = new goog.dom.FontSizeMonitor();
  33. * goog.events.listen(fms, goog.dom.FontSizeMonitor.EventType.CHANGE,
  34. * function(e) {
  35. * alert('Font size was changed');
  36. * });
  37. * </pre>
  38. * @param {goog.dom.DomHelper=} opt_domHelper DOM helper object that is used to
  39. * determine where to insert the DOM nodes used to determine when the font
  40. * size changes.
  41. * @constructor
  42. * @extends {goog.events.EventTarget}
  43. * @final
  44. */
  45. goog.dom.FontSizeMonitor = function(opt_domHelper) {
  46. goog.events.EventTarget.call(this);
  47. var dom = opt_domHelper || goog.dom.getDomHelper();
  48. /**
  49. * Offscreen iframe which we use to detect resize events.
  50. * @type {HTMLElement}
  51. * @private
  52. */
  53. this.sizeElement_ = /** @type {!HTMLElement} */ (
  54. dom.createDom(
  55. // The size of the iframe is expressed in em, which are font size
  56. // relative
  57. // which will cause the iframe to be resized when the font size
  58. // changes.
  59. // The actual values are not relevant as long as we can ensure that
  60. // the
  61. // iframe has a non zero size and is completely off screen.
  62. goog.userAgent.IE ? goog.dom.TagName.DIV : goog.dom.TagName.IFRAME, {
  63. 'style': 'position:absolute;width:9em;height:9em;top:-99em',
  64. 'tabIndex': -1,
  65. 'aria-hidden': 'true'
  66. }));
  67. var p = dom.getDocument().body;
  68. p.insertBefore(this.sizeElement_, p.firstChild);
  69. /**
  70. * The object that we listen to resize events on.
  71. * @type {Element|Window}
  72. * @private
  73. */
  74. var resizeTarget = this.resizeTarget_ = goog.userAgent.IE ?
  75. this.sizeElement_ :
  76. goog.dom.getFrameContentWindow(
  77. /** @type {HTMLIFrameElement} */ (this.sizeElement_));
  78. // We need to open and close the document to get Firefox 2 to work. We must
  79. // not do this for IE in case we are using HTTPS since accessing the document
  80. // on an about:blank iframe in IE using HTTPS raises a Permission Denied
  81. // error.
  82. if (goog.userAgent.GECKO) {
  83. var doc = resizeTarget.document;
  84. doc.open();
  85. doc.close();
  86. }
  87. // Listen to resize event on the window inside the iframe.
  88. goog.events.listen(
  89. resizeTarget, goog.events.EventType.RESIZE, this.handleResize_, false,
  90. this);
  91. /**
  92. * Last measured width of the iframe element.
  93. * @type {number}
  94. * @private
  95. */
  96. this.lastWidth_ = this.sizeElement_.offsetWidth;
  97. };
  98. goog.inherits(goog.dom.FontSizeMonitor, goog.events.EventTarget);
  99. /**
  100. * The event types that the FontSizeMonitor fires.
  101. * @enum {string}
  102. */
  103. goog.dom.FontSizeMonitor.EventType = {
  104. // TODO(arv): Change value to 'change' after updating the callers.
  105. CHANGE: 'fontsizechange'
  106. };
  107. /**
  108. * Constant for the change event.
  109. * @type {string}
  110. * @deprecated Use {@code goog.dom.FontSizeMonitor.EventType.CHANGE} instead.
  111. */
  112. goog.dom.FontSizeMonitor.CHANGE_EVENT =
  113. goog.dom.FontSizeMonitor.EventType.CHANGE;
  114. /** @override */
  115. goog.dom.FontSizeMonitor.prototype.disposeInternal = function() {
  116. goog.dom.FontSizeMonitor.superClass_.disposeInternal.call(this);
  117. goog.events.unlisten(
  118. this.resizeTarget_, goog.events.EventType.RESIZE, this.handleResize_,
  119. false, this);
  120. this.resizeTarget_ = null;
  121. // Firefox 2 crashes if the iframe is removed during the unload phase.
  122. if (!goog.userAgent.GECKO || goog.userAgent.isVersionOrHigher('1.9')) {
  123. goog.dom.removeNode(this.sizeElement_);
  124. }
  125. delete this.sizeElement_;
  126. };
  127. /**
  128. * Handles the onresize event of the iframe and dispatches a change event in
  129. * case its size really changed.
  130. * @param {goog.events.BrowserEvent} e The event object.
  131. * @private
  132. */
  133. goog.dom.FontSizeMonitor.prototype.handleResize_ = function(e) {
  134. // Only dispatch the event if the size really changed. Some newer browsers do
  135. // not really change the font-size, instead they zoom the whole page. This
  136. // does trigger window resize events on the iframe but the logical pixel size
  137. // remains the same (the device pixel size changes but that is irrelevant).
  138. var currentWidth = this.sizeElement_.offsetWidth;
  139. if (this.lastWidth_ != currentWidth) {
  140. this.lastWidth_ = currentWidth;
  141. this.dispatchEvent(goog.dom.FontSizeMonitor.EventType.CHANGE);
  142. }
  143. };