123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 |
- // Copyright 2006 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 Class to encapsulate an editable field that blends in with
- * the style of the page. The field can be fixed height, grow with its
- * contents, or have a min height after which it grows to its contents.
- * This is a goog.editor.Field, but with blending and sizing capabilities,
- * and avoids using an iframe whenever possible.
- *
- * @author nicksantos@google.com (Nick Santos)
- * @see ../demos/editor/seamlessfield.html
- */
- goog.provide('goog.editor.SeamlessField');
- goog.require('goog.cssom.iframe.style');
- goog.require('goog.dom');
- goog.require('goog.dom.Range');
- goog.require('goog.dom.TagName');
- goog.require('goog.dom.safe');
- goog.require('goog.editor.BrowserFeature');
- goog.require('goog.editor.Field');
- goog.require('goog.editor.icontent');
- goog.require('goog.editor.icontent.FieldFormatInfo');
- goog.require('goog.editor.icontent.FieldStyleInfo');
- goog.require('goog.editor.node');
- goog.require('goog.events');
- goog.require('goog.events.EventType');
- goog.require('goog.html.legacyconversions');
- goog.require('goog.html.uncheckedconversions');
- goog.require('goog.log');
- goog.require('goog.string.Const');
- goog.require('goog.style');
- /**
- * This class encapsulates an editable field that blends in with the
- * surrounding page.
- * To see events fired by this object, please see the base class.
- *
- * @param {string} id An identifer for the field. This is used to find the
- * field and the element associated with this field.
- * @param {Document=} opt_doc The document that the element with the given
- * id can be found it.
- * @constructor
- * @extends {goog.editor.Field}
- */
- goog.editor.SeamlessField = function(id, opt_doc) {
- goog.editor.Field.call(this, id, opt_doc);
- };
- goog.inherits(goog.editor.SeamlessField, goog.editor.Field);
- /**
- * @override
- */
- goog.editor.SeamlessField.prototype.logger =
- goog.log.getLogger('goog.editor.SeamlessField');
- // Functions dealing with field sizing.
- /**
- * The key used for listening for the "dragover" event.
- * @type {goog.events.Key}
- * @private
- */
- goog.editor.SeamlessField.prototype.listenForDragOverEventKey_;
- /**
- * The key used for listening for the iframe "load" event.
- * @type {goog.events.Key}
- * @private
- */
- goog.editor.SeamlessField.prototype.listenForIframeLoadEventKey_;
- /**
- * Sets the min height of this editable field's iframe. Only used in growing
- * mode when an iframe is used. This will cause an immediate field sizing to
- * update the field if necessary based on the new min height.
- * @param {number} height The min height specified as a number of pixels,
- * e.g., 75.
- */
- goog.editor.SeamlessField.prototype.setMinHeight = function(height) {
- if (height == this.minHeight_) {
- // Do nothing if the min height isn't changing.
- return;
- }
- this.minHeight_ = height;
- if (this.usesIframe()) {
- this.doFieldSizingGecko();
- }
- };
- /**
- * Whether the field should be rendered with a fixed height, or should expand
- * to fit its contents.
- * @type {boolean}
- * @private
- */
- goog.editor.SeamlessField.prototype.isFixedHeight_ = false;
- /**
- * Whether the fixed-height handling has been overridden manually.
- * @type {boolean}
- * @private
- */
- goog.editor.SeamlessField.prototype.isFixedHeightOverridden_ = false;
- /**
- * @return {boolean} Whether the field should be rendered with a fixed
- * height, or should expand to fit its contents.
- * @override
- */
- goog.editor.SeamlessField.prototype.isFixedHeight = function() {
- return this.isFixedHeight_;
- };
- /**
- * @param {boolean} newVal Explicitly set whether the field should be
- * of a fixed-height. This overrides auto-detection.
- */
- goog.editor.SeamlessField.prototype.overrideFixedHeight = function(newVal) {
- this.isFixedHeight_ = newVal;
- this.isFixedHeightOverridden_ = true;
- };
- /**
- * Auto-detect whether the current field should have a fixed height.
- * @private
- */
- goog.editor.SeamlessField.prototype.autoDetectFixedHeight_ = function() {
- if (!this.isFixedHeightOverridden_) {
- var originalElement = this.getOriginalElement();
- if (originalElement) {
- this.isFixedHeight_ =
- goog.style.getComputedOverflowY(originalElement) == 'auto';
- }
- }
- };
- /**
- * Resize the iframe in response to the wrapper div changing size.
- * @private
- */
- goog.editor.SeamlessField.prototype.handleOuterDocChange_ = function() {
- if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
- return;
- }
- this.sizeIframeToWrapperGecko_();
- };
- /**
- * Sizes the iframe to its body's height.
- * @private
- */
- goog.editor.SeamlessField.prototype.sizeIframeToBodyHeightGecko_ = function() {
- if (this.acquireSizeIframeLockGecko_()) {
- var resized = false;
- var ifr = this.getEditableIframe();
- if (ifr) {
- var fieldHeight = this.getIframeBodyHeightGecko_();
- if (this.minHeight_) {
- fieldHeight = Math.max(fieldHeight, this.minHeight_);
- }
- if (parseInt(goog.style.getStyle(ifr, 'height'), 10) != fieldHeight) {
- ifr.style.height = fieldHeight + 'px';
- resized = true;
- }
- }
- this.releaseSizeIframeLockGecko_();
- if (resized) {
- this.dispatchEvent(goog.editor.Field.EventType.IFRAME_RESIZED);
- }
- }
- };
- /**
- * @return {number} The height of the editable iframe's body.
- * @private
- */
- goog.editor.SeamlessField.prototype.getIframeBodyHeightGecko_ = function() {
- var ifr = this.getEditableIframe();
- var body = ifr.contentDocument.body;
- var htmlElement = /** @type {!HTMLElement} */ (body.parentNode);
- // If the iframe's height is 0, then the offsetHeight/scrollHeight of the
- // HTML element in the iframe can be totally wack (i.e. too large
- // by 50-500px). Also, in standard's mode the clientHeight is 0.
- if (parseInt(goog.style.getStyle(ifr, 'height'), 10) === 0) {
- goog.style.setStyle(ifr, 'height', 1 + 'px');
- }
- var fieldHeight;
- if (goog.editor.node.isStandardsMode(body)) {
- // If in standards-mode,
- // grab the HTML element as it will contain all the field's
- // contents. The body's height, for example, will not include that of
- // floated images at the bottom in standards mode.
- // Note that this value include all scrollbars *except* for scrollbars
- // on the HTML element itself.
- fieldHeight = htmlElement.offsetHeight;
- } else {
- // In quirks-mode, the body-element always seems
- // to size to the containing window. The html-element however,
- // sizes to the content, and can thus end up with a value smaller
- // than its child body-element if the content is shrinking.
- // We want to make the iframe shrink too when the content shrinks,
- // so rather than size the iframe to the body-element, size it to
- // the html-element.
- fieldHeight = htmlElement.scrollHeight;
- // If there is a horizontal scroll, add in the thickness of the
- // scrollbar.
- if (htmlElement.clientHeight != htmlElement.offsetHeight) {
- fieldHeight += goog.editor.SeamlessField.getScrollbarWidth_();
- }
- }
- return fieldHeight;
- };
- /**
- * Grabs the width of a scrollbar from the browser and caches the result.
- * @return {number} The scrollbar width in pixels.
- * @private
- */
- goog.editor.SeamlessField.getScrollbarWidth_ = function() {
- return goog.editor.SeamlessField.scrollbarWidth_ ||
- (goog.editor.SeamlessField.scrollbarWidth_ =
- goog.style.getScrollbarWidth());
- };
- /**
- * Sizes the iframe to its container div's width. The width of the div
- * is controlled by its containing context, not by its contents.
- * if it extends outside of it's contents, then it gets a horizontal scroll.
- * @private
- */
- goog.editor.SeamlessField.prototype.sizeIframeToWrapperGecko_ = function() {
- if (this.acquireSizeIframeLockGecko_()) {
- var ifr = this.getEditableIframe();
- var field = this.getElement();
- var resized = false;
- if (ifr && field) {
- var fieldPaddingBox;
- var widthDiv = /** @type {!HTMLElement} */ (ifr.parentNode);
- var width = widthDiv.offsetWidth;
- if (parseInt(goog.style.getStyle(ifr, 'width'), 10) != width) {
- fieldPaddingBox = goog.style.getPaddingBox(field);
- ifr.style.width = width + 'px';
- field.style.width =
- width - fieldPaddingBox.left - fieldPaddingBox.right + 'px';
- resized = true;
- }
- var height = widthDiv.offsetHeight;
- if (this.isFixedHeight() &&
- parseInt(goog.style.getStyle(ifr, 'height'), 10) != height) {
- if (!fieldPaddingBox) {
- fieldPaddingBox = goog.style.getPaddingBox(field);
- }
- ifr.style.height = height + 'px';
- field.style.height =
- height - fieldPaddingBox.top - fieldPaddingBox.bottom + 'px';
- resized = true;
- }
- }
- this.releaseSizeIframeLockGecko_();
- if (resized) {
- this.dispatchEvent(goog.editor.Field.EventType.IFRAME_RESIZED);
- }
- }
- };
- /**
- * Perform all the sizing immediately.
- */
- goog.editor.SeamlessField.prototype.doFieldSizingGecko = function() {
- // Because doFieldSizingGecko can be called after a setTimeout
- // it is possible that the field has been destroyed before this call
- // to do the sizing is executed. Check for field existence and do nothing
- // if it has already been destroyed.
- if (this.getElement()) {
- // The order of operations is important here. Sizing the iframe to the
- // wrapper could cause the width to change, which could change the line
- // wrapping, which could change the body height. So we need to do that
- // first, then size the iframe to fit the body height.
- this.sizeIframeToWrapperGecko_();
- if (!this.isFixedHeight()) {
- this.sizeIframeToBodyHeightGecko_();
- }
- }
- };
- /**
- * Acquires a lock on resizing the field iframe. This is used to ensure that
- * modifications we make while in a mutation event handler don't cause
- * infinite loops.
- * @return {boolean} False if the lock is already acquired.
- * @private
- */
- goog.editor.SeamlessField.prototype.acquireSizeIframeLockGecko_ = function() {
- if (this.sizeIframeLock_) {
- return false;
- }
- return this.sizeIframeLock_ = true;
- };
- /**
- * Releases a lock on resizing the field iframe. This is used to ensure that
- * modifications we make while in a mutation event handler don't cause
- * infinite loops.
- * @private
- */
- goog.editor.SeamlessField.prototype.releaseSizeIframeLockGecko_ = function() {
- this.sizeIframeLock_ = false;
- };
- // Functions dealing with blending in with the surrounding page.
- /**
- * String containing the css rules that, if applied to a document's body,
- * would style that body as if it were the original element we made editable.
- * See goog.cssom.iframe.style.getElementContext for more details.
- * @type {string}
- * @private
- */
- goog.editor.SeamlessField.prototype.iframeableCss_ = '';
- /**
- * Gets the css rules that should be used to style an iframe's body as if it
- * were the original element that we made editable.
- * @param {boolean=} opt_forceRegeneration Set to true to not read the cached
- * copy and instead completely regenerate the css rules.
- * @return {string} The string containing the css rules to use.
- */
- goog.editor.SeamlessField.prototype.getIframeableCss = function(
- opt_forceRegeneration) {
- if (!this.iframeableCss_ || opt_forceRegeneration) {
- var originalElement = this.getOriginalElement();
- if (originalElement) {
- this.iframeableCss_ = goog.cssom.iframe.style.getElementContext(
- originalElement, opt_forceRegeneration);
- }
- }
- return this.iframeableCss_;
- };
- /**
- * Sets the css rules that should be used inside the editable iframe.
- * Note: to clear the css cache between makeNotEditable/makeEditable,
- * call this with "" as iframeableCss.
- * TODO(user): Unify all these css setting methods + Nick's open
- * CL. This is getting ridiculous.
- * @param {string} iframeableCss String containing the css rules to use.
- */
- goog.editor.SeamlessField.prototype.setIframeableCss = function(iframeableCss) {
- this.iframeableCss_ = iframeableCss;
- };
- /**
- * Used to ensure that CSS stylings are only installed once for none
- * iframe seamless mode.
- * TODO(user): Make it a formal part of the API that you can only
- * set one set of styles globally.
- * In seamless, non-iframe mode, all the stylings would go in the
- * same document and conflict.
- * @type {boolean}
- * @private
- */
- goog.editor.SeamlessField.haveInstalledCss_ = false;
- /**
- * Applies CSS from the wrapper-div to the field iframe.
- */
- goog.editor.SeamlessField.prototype.inheritBlendedCSS = function() {
- // No-op if the field isn't using an iframe.
- if (!this.usesIframe()) {
- return;
- }
- var field = this.getElement();
- var head = goog.dom.getDomHelper(field).getElementsByTagNameAndClass(
- goog.dom.TagName.HEAD)[0];
- if (head) {
- // We created this <head>, and we know the only thing we put in there
- // is a <style> block. So it's safe to blow away all the children
- // as part of rewriting the styles.
- goog.dom.removeChildren(head);
- }
- // Force a cache-clearing in CssUtil - this function was called because
- // we're applying the 'blend' for the first time, or because we
- // *need* to recompute the blend.
- var newCSS = this.getIframeableCss(true);
- goog.style.installSafeStyleSheet(
- goog.html.legacyconversions.safeStyleSheetFromString(newCSS), field);
- };
- // Overridden methods.
- /** @override */
- goog.editor.SeamlessField.prototype.usesIframe = function() {
- // TODO(user): Switch Firefox to using contentEditable
- // rather than designMode iframe once contentEditable support
- // is less buggy.
- return !goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE;
- };
- /** @override */
- goog.editor.SeamlessField.prototype.setupMutationEventHandlersGecko =
- function() {
- goog.editor.SeamlessField.superClass_.setupMutationEventHandlersGecko.call(
- this);
- if (this.usesIframe()) {
- var iframe = this.getEditableIframe();
- var outerDoc = iframe.ownerDocument;
- this.eventRegister.listen(
- outerDoc, goog.editor.Field.MUTATION_EVENTS_GECKO,
- this.handleOuterDocChange_, true);
- // If the images load after we do the initial sizing, then this will
- // force a field resize.
- this.listenForIframeLoadEventKey_ = goog.events.listenOnce(
- this.getEditableDomHelper().getWindow(), goog.events.EventType.LOAD,
- this.sizeIframeToBodyHeightGecko_, true, this);
- this.eventRegister.listen(
- outerDoc, 'DOMAttrModified',
- goog.bind(this.handleDomAttrChange, this, this.handleOuterDocChange_),
- true);
- }
- };
- /** @override */
- goog.editor.SeamlessField.prototype.handleChange = function() {
- if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
- return;
- }
- goog.editor.SeamlessField.superClass_.handleChange.call(this);
- if (this.usesIframe()) {
- this.sizeIframeToBodyHeightGecko_();
- }
- };
- /** @override */
- goog.editor.SeamlessField.prototype.dispatchBlur = function() {
- if (this.isEventStopped(goog.editor.Field.EventType.BLUR)) {
- return;
- }
- goog.editor.SeamlessField.superClass_.dispatchBlur.call(this);
- // Clear the selection and restore the current range back after collapsing
- // it. The ideal solution would have been to just leave the range intact; but
- // when there are multiple fields present on the page, its important that
- // the selection isn't retained when we switch between the fields. We also
- // have to make sure that the cursor position is retained when we tab in and
- // out of a field and our approach addresses both these issues.
- // Another point to note is that we do it on a setTimeout to allow for
- // DOM modifications on blur. Otherwise, something like setLoremIpsum will
- // leave a blinking cursor in the field even though it's blurred.
- if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE &&
- !goog.editor.BrowserFeature.CLEARS_SELECTION_WHEN_FOCUS_LEAVES) {
- var win = this.getEditableDomHelper().getWindow();
- var dragging = false;
- goog.events.unlistenByKey(this.listenForDragOverEventKey_);
- this.listenForDragOverEventKey_ = goog.events.listenOnce(
- win.document.body, 'dragover', function() { dragging = true; });
- goog.global.setTimeout(goog.bind(function() {
- // Do not clear the selection if we're only dragging text.
- // This addresses a bug on FF1.5/linux where dragging fires a blur,
- // but clearing the selection confuses Firefox's drag-and-drop
- // implementation. For more info, see http://b/1061064
- if (!dragging) {
- if (this.editableDomHelper) {
- var rng = this.getRange();
- // If there are multiple fields on a page, we need to make sure that
- // the selection isn't retained when we switch between fields. We
- // could have collapsed the range but there is a bug in GECKO where
- // the selection stays highlighted even though its backing range is
- // collapsed (http://b/1390115). To get around this, we clear the
- // selection and restore the collapsed range back in. Restoring the
- // range is important so that the cursor stays intact when we tab out
- // and into a field (See http://b/1790301 for additional details on
- // this).
- var iframeWindow = this.editableDomHelper.getWindow();
- goog.dom.Range.clearSelection(iframeWindow);
- if (rng) {
- rng.collapse(true);
- rng.select();
- }
- }
- }
- }, this), 0);
- }
- };
- /** @override */
- goog.editor.SeamlessField.prototype.turnOnDesignModeGecko = function() {
- goog.editor.SeamlessField.superClass_.turnOnDesignModeGecko.call(this);
- var doc = this.getEditableDomHelper().getDocument();
- doc.execCommand('enableInlineTableEditing', false, 'false');
- doc.execCommand('enableObjectResizing', false, 'false');
- };
- /** @override */
- goog.editor.SeamlessField.prototype.installStyles = function() {
- if (!this.usesIframe()) {
- if (!goog.editor.SeamlessField.haveInstalledCss_) {
- if (this.cssStyles) {
- goog.style.installSafeStyleSheet(
- goog.html.legacyconversions.safeStyleSheetFromString(
- this.cssStyles),
- this.getElement());
- }
- // TODO(user): this should be reset to false when the editor is quit.
- // In non-iframe mode, CSS styles should only be instaled once.
- goog.editor.SeamlessField.haveInstalledCss_ = true;
- }
- }
- };
- /** @override */
- goog.editor.SeamlessField.prototype.makeEditableInternal = function(
- opt_iframeSrc) {
- if (this.usesIframe()) {
- goog.editor.SeamlessField.superClass_.makeEditableInternal.call(
- this, opt_iframeSrc);
- } else {
- var field = this.getOriginalElement();
- if (field) {
- this.setupFieldObject(field);
- field.contentEditable = true;
- this.injectContents(field.innerHTML, field);
- this.handleFieldLoad();
- }
- }
- };
- /** @override */
- goog.editor.SeamlessField.prototype.handleFieldLoad = function() {
- if (this.usesIframe()) {
- // If the CSS inheriting code screws up (e.g. makes fonts too large) and
- // the field is sized off in goog.editor.Field.makeIframeField, then we need
- // to size it correctly, but it needs to be visible for the browser
- // to have fully rendered it. We need to put this on a timeout to give
- // the browser time to render.
- var self = this;
- goog.global.setTimeout(function() { self.doFieldSizingGecko(); }, 0);
- }
- goog.editor.SeamlessField.superClass_.handleFieldLoad.call(this);
- };
- /** @override */
- goog.editor.SeamlessField.prototype.getIframeAttributes = function() {
- return {'frameBorder': 0, 'style': 'padding:0;'};
- };
- /** @override */
- goog.editor.SeamlessField.prototype.attachIframe = function(iframe) {
- this.autoDetectFixedHeight_();
- var field = this.getOriginalElement();
- var dh = goog.dom.getDomHelper(field);
- // Grab the width/height values of the field before modifying any CSS
- // as some of the modifications affect its size (e.g. innerHTML='')
- // Here, we set the size of the field to fixed so there's not too much
- // jiggling when we set the innerHTML of the field.
- var oldWidth = field.style.width;
- var oldHeight = field.style.height;
- goog.style.setStyle(field, 'visibility', 'hidden');
- // If there is a floated element at the bottom of the field,
- // then it needs a clearing div at the end to cause the clientHeight
- // to contain the entire field.
- // Also, with css re-writing, the margins of the first/last
- // paragraph don't seem to get included in the clientHeight. Specifically,
- // the extra divs below force the field's clientHeight to include the
- // margins on the first and last elements contained within it.
- var startDiv = dh.createDom(
- goog.dom.TagName.DIV,
- {'style': 'height:0;clear:both', 'innerHTML': ' '});
- var endDiv = startDiv.cloneNode(true);
- field.insertBefore(startDiv, field.firstChild);
- goog.dom.appendChild(field, endDiv);
- var contentBox = goog.style.getContentBoxSize(field);
- var width = contentBox.width;
- var height = contentBox.height;
- var html = '';
- if (this.isFixedHeight()) {
- html = ' ';
- goog.style.setStyle(field, 'position', 'relative');
- goog.style.setStyle(field, 'overflow', 'visible');
- goog.style.setStyle(iframe, 'position', 'absolute');
- goog.style.setStyle(iframe, 'top', '0');
- goog.style.setStyle(iframe, 'left', '0');
- }
- goog.style.setSize(field, width, height);
- // In strict mode, browsers put blank space at the bottom and right
- // if a field when it has an iframe child, to fill up the remaining line
- // height. So make the line height = 0.
- if (goog.editor.node.isStandardsMode(field)) {
- this.originalFieldLineHeight_ = field.style.lineHeight;
- goog.style.setStyle(field, 'lineHeight', '0');
- }
- goog.editor.node.replaceInnerHtml(field, html);
- // Set the initial size
- goog.style.setSize(iframe, width, height);
- goog.style.setSize(field, oldWidth, oldHeight);
- goog.style.setStyle(field, 'visibility', '');
- goog.dom.appendChild(field, iframe);
- // Only write if its not IE HTTPS in which case we're waiting for load.
- if (!this.shouldLoadAsynchronously()) {
- var doc = iframe.contentWindow.document;
- if (goog.editor.node.isStandardsMode(iframe.ownerDocument)) {
- doc.open();
- var emptyHtml =
- goog.html.uncheckedconversions
- .safeHtmlFromStringKnownToSatisfyTypeContract(
- goog.string.Const.from('HTML from constant string'),
- '<!DOCTYPE HTML><html></html>');
- goog.dom.safe.documentWrite(doc, emptyHtml);
- doc.close();
- }
- }
- };
- /** @override */
- goog.editor.SeamlessField.prototype.getFieldFormatInfo = function(extraStyles) {
- var originalElement = this.getOriginalElement();
- if (originalElement) {
- return new goog.editor.icontent.FieldFormatInfo(
- this.id, goog.editor.node.isStandardsMode(originalElement), true,
- this.isFixedHeight(), extraStyles);
- }
- throw Error('no field');
- };
- /** @override */
- goog.editor.SeamlessField.prototype.writeIframeContent = function(
- iframe, innerHtml, extraStyles) {
- // For seamless iframes, hide the iframe while we're laying it out to
- // prevent the flicker.
- goog.style.setStyle(iframe, 'visibility', 'hidden');
- var formatInfo = this.getFieldFormatInfo(extraStyles);
- var styleInfo = new goog.editor.icontent.FieldStyleInfo(
- this.getOriginalElement(), this.cssStyles + this.getIframeableCss());
- goog.editor.icontent.writeNormalInitialBlendedIframe(
- formatInfo, innerHtml, styleInfo, iframe);
- this.doFieldSizingGecko();
- goog.style.setStyle(iframe, 'visibility', 'visible');
- };
- /** @override */
- goog.editor.SeamlessField.prototype.restoreDom = function() {
- // TODO(user): Consider only removing the iframe if we are
- // restoring the original node.
- if (this.usesIframe()) {
- goog.dom.removeNode(this.getEditableIframe());
- }
- };
- /** @override */
- goog.editor.SeamlessField.prototype.clearListeners = function() {
- goog.events.unlistenByKey(this.listenForDragOverEventKey_);
- goog.events.unlistenByKey(this.listenForIframeLoadEventKey_);
- goog.editor.SeamlessField.base(this, 'clearListeners');
- };
|