// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617/**18* @fileoverview IE specific atoms.19*/2021goog.provide('webdriver.ie');2223goog.require('bot.ErrorCode');24goog.require('bot.dom');25goog.require('bot.locators');26goog.require('bot.userAgent');27goog.require('goog.math.Coordinate');28goog.require('goog.style');293031/**32* Find the first element in the DOM matching the mechanism and criteria.33*34* @param {!string} mechanism The mechanism to search by.35* @param {!string} criteria The criteria to search for.36* @param {?(Document|Element)=} opt_root The node from which to start the37* search. If not specified, will use `document` as the root.38* @return {!Object} An object containing the status of the find and39* the result (success will be the first matching element found in40* the DOM, failure will be the associated error message).41*/42webdriver.ie.findElement = function(mechanism, criteria, opt_root) {43var locator = {};44var retval = {};45locator[mechanism] = criteria;46try {47retval = bot.locators.findElement(locator, opt_root);48} catch (e) {49// The normal error case throws bot.Error, which has a 'code'50// property. In the case where the locator mechanism is unknown,51// findElement throws a plain JavaScript Error, which doesn't.52return {53'status': e.code || bot.ErrorCode.JAVASCRIPT_ERROR,54'value': e.message55};56}57if (retval == null) {58return { 'status': bot.ErrorCode.NO_SUCH_ELEMENT, 'value': retval };59}60return { 'status': bot.ErrorCode.SUCCESS, 'value': retval };61};626364/**65* Find all elements in the DOM matching the mechanism and criteria.66*67* @param {!string} mechanism The mechanism to search by.68* @param {!string} criteria The criteria to search for.69* @param {?(Document|Element)=} opt_root The node from which to start the70* search. If not specified, will use `document` as the root.71* @return {!Object} An object containing the status of the find and72* the result (success will be the elements, failure will be the73* associated error message).74*/75webdriver.ie.findElements = function(mechanism, criteria, opt_root) {76// For finding multiple elements by class name in IE, if the document77// mode is below 8 (which includes quirks mode), the findElements atom78// drops into a branch of the Closure library that doesn't validate79// that the class name is valid, and therefore just returns an empty80// array. Thus, we pre-screen the class name in this special case.81// Note: the regex used herein may not be entirely correct; judging82// this to be an acceptable risk due to the (hopefully) limited nature83// of the bug.84if (mechanism == 'className' && bot.userAgent.IE_DOC_PRE8) {85var invalidTokenRegex = /[~!@\$%\^&\*\(\)_\+=,\.\/';:"\?><\[\]\\\{\}\|`#]+/;86if (invalidTokenRegex.test(criteria)) {87return { 'status': bot.ErrorCode.INVALID_SELECTOR_ERROR,88'value': 'Invalid character in class name.' };89}90}91var retval = {};92var locator = {};93locator[mechanism] = criteria;94try {95retval = bot.locators.findElements(locator, opt_root);96} catch (e) {97// The normal error case throws bot.Error, which has a 'code'98// property. In the case where the locator mechanism is unknown,99// findElement throws a plain JavaScript Error, which doesn't.100return {101'status': e.code || bot.ErrorCode.JAVASCRIPT_ERROR,102'value': e.message103};104}105return {'status': bot.ErrorCode.SUCCESS, 'value': retval};106};107108109/**110* Checks whether the element is currently scrolled into the parent's overflow111* region, such that the offset given, relative to the top-left corner of the112* element, is currently in the overflow region.113*114* @param {!Element} element The element to check.115* @param {number} x The horizontal offset from the top-left corner.116* @param {number} y The vertical offset from the top-left corner.117* @return {bot.dom.OverflowState} Whether the coordinates specified, relative to the element,118* are scrolled in the parent overflow.119*/120webdriver.ie.isOffsetInParentOverflow = function (element, x, y) {121var offsetPoint = new goog.math.Coordinate(x, y);122return bot.dom.getOverflowState(element, offsetPoint);123};124125/**126* Checks whether the element is entirely scrolled into the parent's overflow127* region.128*129* @param {!Element} element The element to check.130* @return {bot.dom.OverflowState} Whether the coordinates specified, relative to the element,131* are scrolled in the parent overflow.132*/133webdriver.ie.isElementInParentOverflow = function (element) {134return bot.dom.getOverflowState(element);135};136137/**138* Gets the size and location of an element.139*140* @param {!Element} element The element to get the rect of.141* @return {!Object} An object containing the element rect.142*/143webdriver.ie.getElementRect = function (element) {144// For now, we'll return a custom object. If we need145// more functionality later provided by goog.math.Rect,146// we can upgrade to that when needed.147var size = goog.style.getTransformedSize(element);148var location = goog.style.getPageOffset(element);149return {150'x': location.x, 'y': location.y,151'width': size.width, 'height': size.height152};153};154155156