blob: 19f19a0783bf90f74a18799c4e918d72f544c49d [file] [log] [blame] [edit]
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you 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 IE specific atoms.
*/
goog.provide('webdriver.ie');
goog.require('bot.ErrorCode');
goog.require('bot.dom');
goog.require('bot.locators');
goog.require('bot.userAgent');
goog.require('goog.math.Coordinate');
goog.require('goog.style');
/**
* Find the first element in the DOM matching the mechanism and criteria.
*
* @param {!string} mechanism The mechanism to search by.
* @param {!string} criteria The criteria to search for.
* @param {?(Document|Element)=} opt_root The node from which to start the
* search. If not specified, will use `document` as the root.
* @return {!Object} An object containing the status of the find and
* the result (success will be the first matching element found in
* the DOM, failure will be the associated error message).
*/
webdriver.ie.findElement = function(mechanism, criteria, opt_root) {
var locator = {};
var retval = {};
locator[mechanism] = criteria;
try {
retval = bot.locators.findElement(locator, opt_root);
} catch (e) {
// The normal error case throws bot.Error, which has a 'code'
// property. In the case where the locator mechanism is unknown,
// findElement throws a plain JavaScript Error, which doesn't.
return {
'status': e.code || bot.ErrorCode.JAVASCRIPT_ERROR,
'value': e.message
};
}
if (retval == null) {
return { 'status': bot.ErrorCode.NO_SUCH_ELEMENT, 'value': retval };
}
return { 'status': bot.ErrorCode.SUCCESS, 'value': retval };
};
/**
* Find all elements in the DOM matching the mechanism and criteria.
*
* @param {!string} mechanism The mechanism to search by.
* @param {!string} criteria The criteria to search for.
* @param {?(Document|Element)=} opt_root The node from which to start the
* search. If not specified, will use `document` as the root.
* @return {!Object} An object containing the status of the find and
* the result (success will be the elements, failure will be the
* associated error message).
*/
webdriver.ie.findElements = function(mechanism, criteria, opt_root) {
// For finding multiple elements by class name in IE, if the document
// mode is below 8 (which includes quirks mode), the findElements atom
// drops into a branch of the Closure library that doesn't validate
// that the class name is valid, and therefore just returns an empty
// array. Thus, we pre-screen the class name in this special case.
// Note: the regex used herein may not be entirely correct; judging
// this to be an acceptable risk due to the (hopefully) limited nature
// of the bug.
if (mechanism == 'className' && bot.userAgent.IE_DOC_PRE8) {
var invalidTokenRegex = /[~!@\$%\^&\*\(\)_\+=,\.\/';:"\?><\[\]\\\{\}\|`#]+/;
if (invalidTokenRegex.test(criteria)) {
return { 'status': bot.ErrorCode.INVALID_SELECTOR_ERROR,
'value': 'Invalid character in class name.' };
}
}
var retval = {};
var locator = {};
locator[mechanism] = criteria;
try {
retval = bot.locators.findElements(locator, opt_root);
} catch (e) {
// The normal error case throws bot.Error, which has a 'code'
// property. In the case where the locator mechanism is unknown,
// findElement throws a plain JavaScript Error, which doesn't.
return {
'status': e.code || bot.ErrorCode.JAVASCRIPT_ERROR,
'value': e.message
};
}
return {'status': bot.ErrorCode.SUCCESS, 'value': retval};
};
/**
* Checks whether the element is currently scrolled into the parent's overflow
* region, such that the offset given, relative to the top-left corner of the
* element, is currently in the overflow region.
*
* @param {!Element} element The element to check.
* @param {number} x The horizontal offset from the top-left corner.
* @param {number} y The vertical offset from the top-left corner.
* @return {bot.dom.OverflowState} Whether the coordinates specified, relative to the element,
* are scrolled in the parent overflow.
*/
webdriver.ie.isOffsetInParentOverflow = function (element, x, y) {
var offsetPoint = new goog.math.Coordinate(x, y);
return bot.dom.getOverflowState(element, offsetPoint);
};
/**
* Checks whether the element is entirely scrolled into the parent's overflow
* region.
*
* @param {!Element} element The element to check.
* @return {bot.dom.OverflowState} Whether the coordinates specified, relative to the element,
* are scrolled in the parent overflow.
*/
webdriver.ie.isElementInParentOverflow = function (element) {
return bot.dom.getOverflowState(element);
};
/**
* Gets the size and location of an element.
*
* @param {!Element} element The element to get the rect of.
* @return {!Object} An object containing the element rect.
*/
webdriver.ie.getElementRect = function (element) {
// For now, we'll return a custom object. If we need
// more functionality later provided by goog.math.Rect,
// we can upgrade to that when needed.
var size = goog.style.getTransformedSize(element);
var location = goog.style.getPageOffset(element);
return {
'x': location.x, 'y': location.y,
'width': size.width, 'height': size.height
};
};