| Index: third_party/google_input_tools/src/chrome/os/inputview/dom.js
|
| diff --git a/third_party/google_input_tools/src/chrome/os/inputview/dom.js b/third_party/google_input_tools/src/chrome/os/inputview/dom.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..69ab55ebed05b4fb8f1ee7152c0b8fefd228de73
|
| --- /dev/null
|
| +++ b/third_party/google_input_tools/src/chrome/os/inputview/dom.js
|
| @@ -0,0 +1,229 @@
|
| +// Copyright 2014 The Cloud Input Tools 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 Provides common operation of dom for input tools.
|
| + */
|
| +
|
| +
|
| +goog.provide('i18n.input.common.dom');
|
| +
|
| +goog.require('goog.array');
|
| +goog.require('goog.dom');
|
| +goog.require('goog.dom.TagName');
|
| +goog.require('goog.dom.classlist');
|
| +goog.require('goog.style');
|
| +goog.require('goog.uri.utils');
|
| +goog.require('i18n.input.common.GlobalSettings');
|
| +
|
| +
|
| +/**
|
| + * When detects whether the same domain iframe, browser will throw
|
| + * exceptions on accessing the cross domain iframe. Stores result to avoid to
|
| + * throws exception twice.
|
| + * Key is document uid, value is object. ifrmae uid : true/false
|
| + *
|
| + * @type {!Object.<number, !Object.<number, boolean>>}
|
| + * @private
|
| + */
|
| +i18n.input.common.dom.sameDomainIframes_ = {};
|
| +
|
| +
|
| +/**
|
| + * Checks the given element whether is editable.
|
| + *
|
| + * @param {!Element} element The element.
|
| + * @return {boolean} Whether the give element is editable.
|
| + */
|
| +i18n.input.common.dom.isEditable = function(element) {
|
| + if (!element.tagName) {
|
| + return false;
|
| + }
|
| +
|
| + if (element.readOnly) {
|
| + return false;
|
| + }
|
| +
|
| + switch (element.tagName.toUpperCase()) {
|
| + case 'TEXTAREA':
|
| + return true;
|
| + case 'INPUT':
|
| + return (element.type.toUpperCase() == 'TEXT' ||
|
| + element.type.toUpperCase() == 'SEARCH');
|
| + case 'DIV':
|
| + return element.isContentEditable;
|
| + case 'IFRAME':
|
| + // Accessing iframe's contents or properties throws exception when the
|
| + // iframe is not hosted on the same domain.
|
| + // When it happens, ignore it and consider this iframe isn't editable.
|
| + /** @preserveTry */
|
| + try {
|
| + var ifdoc = i18n.input.common.dom.getSameDomainFrameDoc(element);
|
| + return !!ifdoc && (ifdoc.designMode &&
|
| + ifdoc.designMode.toUpperCase() == 'ON' ||
|
| + ifdoc.body && ifdoc.body.isContentEditable);
|
| + } catch (e) {
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Sets class names to an element.
|
| + *
|
| + * @param {Element} elem Element to set class names.
|
| + * @param {Array.<string>} classes Class names.
|
| + */
|
| +i18n.input.common.dom.setClasses = function(elem, classes) {
|
| + if (elem) {
|
| + for (var i = 0; i < classes.length; i++) {
|
| + if (i == 0) {
|
| + goog.dom.classlist.set(elem, classes[0]);
|
| + } else {
|
| + goog.dom.classlist.add(elem, classes[i]);
|
| + }
|
| + }
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Check the iframe whether is the same domain as the current domain.
|
| + * Returns the iframe content document when it's the same domain,
|
| + * otherwise return null.
|
| + *
|
| + * @param {!Element} element The iframe element.
|
| + * @return {Document} The iframe content document.
|
| + */
|
| +i18n.input.common.dom.getSameDomainFrameDoc = function(element) {
|
| + var uid = goog.getUid(document);
|
| + var frameUid = goog.getUid(element);
|
| + var states = i18n.input.common.dom.sameDomainIframes_[uid];
|
| + if (!states) {
|
| + states = i18n.input.common.dom.sameDomainIframes_[uid] = {};
|
| + }
|
| + /** @preserveTry */
|
| + try {
|
| + var url = window.location.href || '';
|
| + //Note: cross-domain IFRAME's src can be:
|
| + // http://www...
|
| + // https://www....
|
| + // //www.
|
| + // Non-cross-domain IFRAME's src can be:
|
| + // javascript:...
|
| + // javascript://...
|
| + // abc:...
|
| + // abc://...
|
| + // abc//...
|
| + // path/index.html
|
| + if (!(frameUid in states)) {
|
| + if (element.src) {
|
| + var pos = element.src.indexOf('//');
|
| + var protocol = pos < 0 ? 'N/A' : element.src.slice(0, pos);
|
| + states[frameUid] = (protocol != '' &&
|
| + protocol != 'http:' &&
|
| + protocol != 'https:' ||
|
| + goog.uri.utils.haveSameDomain(element.src, url));
|
| + } else {
|
| + states[frameUid] = true;
|
| + }
|
| + }
|
| + return states[frameUid] ? goog.dom.getFrameContentDocument(element) : null;
|
| + } catch (e) {
|
| + states[frameUid] = false;
|
| + return null;
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Gets the same domain iframe or frame document in given document, default
|
| + * given document is current document.
|
| + *
|
| + * @param {Document=} opt_doc The given document.
|
| + * @return {Array.<!Document>} The same domain iframe document.
|
| + */
|
| +i18n.input.common.dom.getSameDomainDocuments = function(opt_doc) {
|
| + var doc = opt_doc || document;
|
| + var iframes = [];
|
| + var rets = [];
|
| + goog.array.extend(iframes,
|
| + doc.getElementsByTagName(goog.dom.TagName.IFRAME),
|
| + doc.getElementsByTagName(goog.dom.TagName.FRAME));
|
| + goog.array.forEach(iframes, function(frame) {
|
| + var frameDoc = i18n.input.common.dom.getSameDomainFrameDoc(frame);
|
| + frameDoc && rets.push(frameDoc);
|
| + });
|
| + return rets;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Create the iframe in given document or default document. Then the input tool
|
| + * UI element will be create inside the iframe document to avoid CSS conflict.
|
| + *
|
| + * @param {Document=} opt_doc The given document.
|
| + * @return {!Element} The iframe element.
|
| + */
|
| +i18n.input.common.dom.createIframeWrapper = function(opt_doc) {
|
| + var doc = opt_doc || document;
|
| + var dom = goog.dom.getDomHelper();
|
| + var frame = dom.createDom(goog.dom.TagName.IFRAME, {
|
| + 'frameborder': '0',
|
| + 'scrolling': 'no',
|
| + 'style': 'background-color:transparent;border:0;display:none;'
|
| + });
|
| + dom.append(/** @type {!Element} */ (doc.body), frame);
|
| + var frameDoc = dom.getFrameContentDocument(frame);
|
| +
|
| + var css = i18n.input.common.GlobalSettings.alternativeImageUrl ?
|
| + i18n.input.common.GlobalSettings.css.replace(
|
| + /\/\/ssl.gstatic.com\/inputtools\/images/g,
|
| + i18n.input.common.GlobalSettings.alternativeImageUrl) :
|
| + i18n.input.common.GlobalSettings.css;
|
| + goog.style.installStyles(
|
| + 'html body{border:0;margin:0;padding:0} html,body{overflow:hidden}' +
|
| + css, /** @type {!Element} */(frameDoc.body));
|
| + return frame;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * The property need to be copied from original element to its iframe wrapper.
|
| + *
|
| + * @type {!Array.<string>}
|
| + * @private
|
| + */
|
| +i18n.input.common.dom.iframeWrapperProperty_ = ['box-shadow', 'z-index',
|
| + 'margin', 'position', 'display'];
|
| +
|
| +
|
| +/**
|
| + * Copies the necessary properties value from original element to its iframe
|
| + * wrapper element.
|
| + *
|
| + * @param {Element} element .
|
| + * @param {Element} iframe The iframe wrapper element.
|
| + */
|
| +i18n.input.common.dom.copyNecessaryStyle = function(element, iframe) {
|
| + goog.style.setContentBoxSize(iframe, goog.style.getSize(element));
|
| + goog.array.forEach(i18n.input.common.dom.iframeWrapperProperty_,
|
| + function(property) {
|
| + goog.style.setStyle(iframe, property,
|
| + goog.style.getComputedStyle(element, property));
|
| + });
|
| +};
|
|
|