blob: 31fc783196a3894f9906a36512c5962b54e2af17 [file] [log] [blame]
// Copyright 2005 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview A class that can be used to listen to font size changes.
* @author arv@google.com (Erik Arvidsson)
*/
goog.provide('goog.dom.FontSizeMonitor');
goog.provide('goog.dom.FontSizeMonitor.EventType');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.userAgent');
// TODO(arv): Move this to goog.events instead.
/**
* This class can be used to monitor changes in font size. Instances will
* dispatch a {@code goog.dom.FontSizeMonitor.EventType.CHANGE} event.
* Example usage:
* <pre>
* var fms = new goog.dom.FontSizeMonitor();
* goog.events.listen(fms, goog.dom.FontSizeMonitor.EventType.CHANGE,
* function(e) {
* alert('Font size was changed');
* });
* </pre>
* @param {goog.dom.DomHelper=} opt_domHelper DOM helper object that is used to
* determine where to insert the DOM nodes used to determine when the font
* size changes.
* @constructor
* @extends {goog.events.EventTarget}
* @final
*/
goog.dom.FontSizeMonitor = function(opt_domHelper) {
goog.events.EventTarget.call(this);
var dom = opt_domHelper || goog.dom.getDomHelper();
/**
* Offscreen iframe which we use to detect resize events.
* @type {Element}
* @private
*/
this.sizeElement_ = dom.createDom(
// The size of the iframe is expressed in em, which are font size relative
// which will cause the iframe to be resized when the font size changes.
// The actual values are not relevant as long as we can ensure that the
// iframe has a non zero size and is completely off screen.
goog.userAgent.IE ? 'div' : 'iframe', {
'style': 'position:absolute;width:9em;height:9em;top:-99em',
'tabIndex': -1,
'aria-hidden': 'true'
});
var p = dom.getDocument().body;
p.insertBefore(this.sizeElement_, p.firstChild);
/**
* The object that we listen to resize events on.
* @type {Element|Window}
* @private
*/
var resizeTarget = this.resizeTarget_ =
goog.userAgent.IE ? this.sizeElement_ :
goog.dom.getFrameContentWindow(
/** @type {HTMLIFrameElement} */ (this.sizeElement_));
// We need to open and close the document to get Firefox 2 to work. We must
// not do this for IE in case we are using HTTPS since accessing the document
// on an about:blank iframe in IE using HTTPS raises a Permission Denied
// error.
if (goog.userAgent.GECKO) {
var doc = resizeTarget.document;
doc.open();
doc.close();
}
// Listen to resize event on the window inside the iframe.
goog.events.listen(resizeTarget, goog.events.EventType.RESIZE,
this.handleResize_, false, this);
/**
* Last measured width of the iframe element.
* @type {number}
* @private
*/
this.lastWidth_ = this.sizeElement_.offsetWidth;
};
goog.inherits(goog.dom.FontSizeMonitor, goog.events.EventTarget);
/**
* The event types that the FontSizeMonitor fires.
* @enum {string}
*/
goog.dom.FontSizeMonitor.EventType = {
// TODO(arv): Change value to 'change' after updating the callers.
CHANGE: 'fontsizechange'
};
/**
* Constant for the change event.
* @type {string}
* @deprecated Use {@code goog.dom.FontSizeMonitor.EventType.CHANGE} instead.
*/
goog.dom.FontSizeMonitor.CHANGE_EVENT =
goog.dom.FontSizeMonitor.EventType.CHANGE;
/** @override */
goog.dom.FontSizeMonitor.prototype.disposeInternal = function() {
goog.dom.FontSizeMonitor.superClass_.disposeInternal.call(this);
goog.events.unlisten(this.resizeTarget_, goog.events.EventType.RESIZE,
this.handleResize_, false, this);
this.resizeTarget_ = null;
// Firefox 2 crashes if the iframe is removed during the unload phase.
if (!goog.userAgent.GECKO ||
goog.userAgent.isVersionOrHigher('1.9')) {
goog.dom.removeNode(this.sizeElement_);
}
delete this.sizeElement_;
};
/**
* Handles the onresize event of the iframe and dispatches a change event in
* case its size really changed.
* @param {goog.events.BrowserEvent} e The event object.
* @private
*/
goog.dom.FontSizeMonitor.prototype.handleResize_ = function(e) {
// Only dispatch the event if the size really changed. Some newer browsers do
// not really change the font-size, instead they zoom the whole page. This
// does trigger window resize events on the iframe but the logical pixel size
// remains the same (the device pixel size changes but that is irrelevant).
var currentWidth = this.sizeElement_.offsetWidth;
if (this.lastWidth_ != currentWidth) {
this.lastWidth_ = currentWidth;
this.dispatchEvent(goog.dom.FontSizeMonitor.EventType.CHANGE);
}
};