cp
diff --git a/javascript/atoms/dom.js b/javascript/atoms/dom.js index 1f521f0..c02a6c3 100644 --- a/javascript/atoms/dom.js +++ b/javascript/atoms/dom.js
@@ -52,16 +52,9 @@ * the active element for. * @return {?Element} The active element, if any. */ -bot.dom.getActiveElement = function(nodeOrWindow) { +bot.dom.getActiveElement = function (nodeOrWindow) { var active = goog.dom.getActiveElement( - goog.dom.getOwnerDocument(nodeOrWindow)); - // IE has the habit of returning an empty object from - // goog.dom.getActiveElement instead of null. - if (goog.userAgent.IE && - active && - typeof active.nodeType === 'undefined') { - return null; - } + goog.dom.getOwnerDocument(nodeOrWindow)); return active; }; @@ -81,10 +74,10 @@ * @see bot.dom.isShown. * @see bot.dom.isEnabled */ -bot.dom.isInteractable = function(element) { +bot.dom.isInteractable = function (element) { return bot.dom.isShown(element, /*ignoreOpacity=*/true) && - bot.dom.isEnabled(element) && - !bot.dom.hasPointerEventsDisabled_(element); + bot.dom.isEnabled(element) && + !bot.dom.hasPointerEventsDisabled_(element); }; @@ -94,9 +87,8 @@ * not to be interactable. * @private */ -bot.dom.hasPointerEventsDisabled_ = function(element) { - if (goog.userAgent.IE || - (goog.userAgent.GECKO && !bot.userAgent.isEngineVersion('1.9.2'))) { +bot.dom.hasPointerEventsDisabled_ = function (element) { + if (goog.userAgent.GECKO && !bot.userAgent.isEngineVersion('1.9.2')) { // Don't support pointer events return false; } @@ -139,11 +131,11 @@ * @param {!Element} element The node to test. * @return {boolean} Whether the node is focusable. */ -bot.dom.isFocusable = function(element) { +bot.dom.isFocusable = function (element) { return goog.array.some(bot.dom.FOCUSABLE_FORM_FIELDS_, tagNameMatches) || - (bot.dom.getAttribute(element, 'tabindex') != null && - Number(bot.dom.getProperty(element, 'tabIndex')) >= 0) || - bot.dom.isEditable(element); + (bot.dom.getAttribute(element, 'tabindex') != null && + Number(bot.dom.getProperty(element, 'tabIndex')) >= 0) || + bot.dom.isEditable(element); function tagNameMatches(tagName) { return bot.dom.isElement(element, tagName); @@ -186,10 +178,10 @@ * @param {!Element} el The element to test. * @return {boolean} Whether the element is enabled. */ -bot.dom.isEnabled = function(el) { +bot.dom.isEnabled = function (el) { var isSupported = goog.array.some( - bot.dom.DISABLED_ATTRIBUTE_SUPPORTED_, - function(tagName) { return bot.dom.isElement(el, tagName); }); + bot.dom.DISABLED_ATTRIBUTE_SUPPORTED_, + function (tagName) { return bot.dom.isElement(el, tagName); }); if (!isSupported) { return true; } @@ -201,22 +193,22 @@ // The element is not explicitly disabled, but if it is an OPTION or OPTGROUP, // we must test if it inherits its state from a parent. if (el.parentNode && - el.parentNode.nodeType == goog.dom.NodeType.ELEMENT && - bot.dom.isElement(el, goog.dom.TagName.OPTGROUP) || - bot.dom.isElement(el, goog.dom.TagName.OPTION)) { - return bot.dom.isEnabled(/**@type{!Element}*/ (el.parentNode)); + el.parentNode.nodeType == goog.dom.NodeType.ELEMENT && + bot.dom.isElement(el, goog.dom.TagName.OPTGROUP) || + bot.dom.isElement(el, goog.dom.TagName.OPTION)) { + return bot.dom.isEnabled(/**@type{!Element}*/(el.parentNode)); } // Is there an ancestor of the current element that is a disabled fieldset // and whose child is also an ancestor-or-self of the current element but is // not the first legend child of the fieldset. If so then the element is // disabled. - return !goog.dom.getAncestor(el, function(e) { + return !goog.dom.getAncestor(el, function (e) { var parent = e.parentNode; if (parent && - bot.dom.isElement(parent, goog.dom.TagName.FIELDSET) && - bot.dom.getProperty(/** @type {!Element} */ (parent), 'disabled')) { + bot.dom.isElement(parent, goog.dom.TagName.FIELDSET) && + bot.dom.getProperty(/** @type {!Element} */(parent), 'disabled')) { if (!bot.dom.isElement(e, goog.dom.TagName.LEGEND)) { return true; } @@ -258,7 +250,7 @@ * @param {!Element} element The element to check. * @return {boolean} Whether the element accepts user-typed text. */ -bot.dom.isTextual = function(element) { +bot.dom.isTextual = function (element) { if (bot.dom.isElement(element, goog.dom.TagName.TEXTAREA)) { return true; } @@ -280,7 +272,7 @@ * @param {!Element} element The element to check. * @return {boolean} Whether the element is a file input. */ -bot.dom.isFileInput = function(element) { +bot.dom.isFileInput = function (element) { if (bot.dom.isElement(element, goog.dom.TagName.INPUT)) { var type = element.type.toLowerCase(); return type == 'file'; @@ -295,7 +287,7 @@ * @param {string} inputType The type of input to check. * @return {boolean} Whether the element is an input with specified type. */ -bot.dom.isInputType = function(element, inputType) { +bot.dom.isInputType = function (element, inputType) { if (bot.dom.isElement(element, goog.dom.TagName.INPUT)) { var type = element.type.toLowerCase(); return type == inputType; @@ -309,15 +301,14 @@ * @param {!Element} element The element to check. * @return {boolean} Whether the element is contentEditable. */ -bot.dom.isContentEditable = function(element) { +bot.dom.isContentEditable = function (element) { // Check if browser supports contentEditable. if (!goog.isDef(element['contentEditable'])) { return false; } - // Checking the element's isContentEditable property is preferred except for - // IE where that property is not reliable on IE versions 7, 8, and 9. - if (!goog.userAgent.IE && goog.isDef(element['isContentEditable'])) { + // Checking the element's isContentEditable property is preferred + if (goog.isDef(element['isContentEditable'])) { return element.isContentEditable; } @@ -345,17 +336,17 @@ * @param {!Element} element The element to check. * @return {boolean} Whether the element accepts user-typed text. */ -bot.dom.isEditable = function(element) { +bot.dom.isEditable = function (element) { return (bot.dom.isTextual(element) || - bot.dom.isFileInput(element) || - bot.dom.isInputType(element, 'range') || - bot.dom.isInputType(element, 'date') || - bot.dom.isInputType(element, 'month') || - bot.dom.isInputType(element, 'week') || - bot.dom.isInputType(element, 'time') || - bot.dom.isInputType(element, 'datetime-local') || - bot.dom.isInputType(element, 'color')) && - !bot.dom.getProperty(element, 'readOnly'); + bot.dom.isFileInput(element) || + bot.dom.isInputType(element, 'range') || + bot.dom.isInputType(element, 'date') || + bot.dom.isInputType(element, 'month') || + bot.dom.isInputType(element, 'week') || + bot.dom.isInputType(element, 'time') || + bot.dom.isInputType(element, 'datetime-local') || + bot.dom.isInputType(element, 'color')) && + !bot.dom.getProperty(element, 'readOnly'); }; @@ -366,13 +357,13 @@ * @param {!Node} node The node who's parent is desired. * @return {Element} The parent element, if available, null otherwise. */ -bot.dom.getParentElement = function(node) { +bot.dom.getParentElement = function (node) { var elem = node.parentNode; while (elem && - elem.nodeType != goog.dom.NodeType.ELEMENT && - elem.nodeType != goog.dom.NodeType.DOCUMENT && - elem.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) { + elem.nodeType != goog.dom.NodeType.ELEMENT && + elem.nodeType != goog.dom.NodeType.DOCUMENT && + elem.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) { elem = elem.parentNode; } return /** @type {Element} */ (bot.dom.isElement(elem) ? elem : null); @@ -388,7 +379,7 @@ * @param {string} styleName Name of the style property in selector-case. * @return {string} The value of the style property. */ -bot.dom.getInlineStyle = function(elem, styleName) { +bot.dom.getInlineStyle = function (elem, styleName) { return goog.style.getStyle(elem, styleName); }; @@ -406,15 +397,15 @@ * @param {string} propertyName Name of the CSS property. * @return {?string} The value of the style property, or null. */ -bot.dom.getEffectiveStyle = function(elem, propertyName) { +bot.dom.getEffectiveStyle = function (elem, propertyName) { var styleName = goog.string.toCamelCase(propertyName); if (styleName == 'float' || - styleName == 'cssFloat' || - styleName == 'styleFloat') { - styleName = bot.userAgent.IE_DOC_PRE9 ? 'styleFloat' : 'cssFloat'; + styleName == 'cssFloat' || + styleName == 'styleFloat') { + styleName = 'cssFloat'; } var style = goog.style.getComputedStyle(elem, styleName) || - bot.dom.getCascadedStyle_(elem, styleName); + bot.dom.getCascadedStyle_(elem, styleName); if (style === null) { return null; } @@ -431,7 +422,7 @@ * @return {?string} The value of the style property, or null. * @private */ -bot.dom.getCascadedStyle_ = function(elem, styleName) { +bot.dom.getCascadedStyle_ = function (elem, styleName) { var style = elem.currentStyle || elem.style; var value = style[styleName]; if (!goog.isDef(value) && goog.isFunction(style.getPropertyValue)) { @@ -457,7 +448,7 @@ * @return {boolean} Whether or not the element is visible. * @private */ -bot.dom.isShown_ = function(elem, ignoreOpacity, parentsDisplayedFn) { +bot.dom.isShown_ = function (elem, ignoreOpacity, parentsDisplayedFn) { if (!bot.dom.isElement(elem)) { throw new Error('Argument to isShown must be of type Element'); } @@ -472,8 +463,8 @@ // Option or optgroup is shown iff enclosing select is shown (ignoring the // select's opacity). if (bot.dom.isElement(elem, goog.dom.TagName.OPTION) || - bot.dom.isElement(elem, goog.dom.TagName.OPTGROUP)) { - var select = /**@type {Element}*/ (goog.dom.getAncestor(elem, function(e) { + bot.dom.isElement(elem, goog.dom.TagName.OPTGROUP)) { + var select = /**@type {Element}*/ (goog.dom.getAncestor(elem, function (e) { return bot.dom.isElement(e, goog.dom.TagName.SELECT); })); return !!select && bot.dom.isShown_(select, true, parentsDisplayedFn); @@ -484,14 +475,14 @@ var imageMap = bot.dom.maybeFindImageMap_(elem); if (imageMap) { return !!imageMap.image && - imageMap.rect.width > 0 && imageMap.rect.height > 0 && - bot.dom.isShown_( - imageMap.image, ignoreOpacity, parentsDisplayedFn); + imageMap.rect.width > 0 && imageMap.rect.height > 0 && + bot.dom.isShown_( + imageMap.image, ignoreOpacity, parentsDisplayedFn); } // Any hidden input is not shown. if (bot.dom.isElement(elem, goog.dom.TagName.INPUT) && - elem.type.toLowerCase() == 'hidden') { + elem.type.toLowerCase() == 'hidden') { return false; } @@ -531,10 +522,10 @@ // if they have a child element or text node with positive size, unless // the element has an 'overflow' style of 'hidden'. return bot.dom.getEffectiveStyle(e, 'overflow') != 'hidden' && - goog.array.some(e.childNodes, function(n) { - return n.nodeType == goog.dom.NodeType.TEXT || - (bot.dom.isElement(n) && positiveSize(n)); - }); + goog.array.some(e.childNodes, function (n) { + return n.nodeType == goog.dom.NodeType.TEXT || + (bot.dom.isElement(n) && positiveSize(n)); + }); } if (!positiveSize(elem)) { return false; @@ -543,10 +534,10 @@ // Elements that are hidden by overflow are not shown. function hiddenByOverflow(e) { return bot.dom.getOverflowState(e) == bot.dom.OverflowState.HIDDEN && - goog.array.every(e.childNodes, function(n) { - return !bot.dom.isElement(n) || hiddenByOverflow(n) || - !positiveSize(n); - }); + goog.array.every(e.childNodes, function (n) { + return !bot.dom.isElement(n) || hiddenByOverflow(n) || + !positiveSize(n); + }); } return !hiddenByOverflow(elem); }; @@ -570,7 +561,7 @@ * when determining whether it is shown; defaults to false. * @return {boolean} Whether or not the element is visible. */ -bot.dom.isShown = function(elem, opt_ignoreOpacity) { +bot.dom.isShown = function (elem, opt_ignoreOpacity) { /** * Determines whether an element or its parents have `display: none` set * @param {!Node} e the element @@ -598,14 +589,14 @@ } if (parent && (parent.nodeType == goog.dom.NodeType.DOCUMENT || - parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT)) { + parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT)) { return true; } // Child of DETAILS element is not shown unless the DETAILS element is open // or the child is a SUMMARY element. if (parent && bot.dom.isElement(parent, goog.dom.TagName.DETAILS) && - !parent.open && !bot.dom.isElement(e, goog.dom.TagName.SUMMARY)) { + !parent.open && !bot.dom.isElement(e, goog.dom.TagName.SUMMARY)) { return false; } @@ -642,7 +633,7 @@ * Coordinate or rectangle relative to the top-left corner of the element. * @return {bot.dom.OverflowState} Overflow state of the element. */ -bot.dom.getOverflowState = function(elem, opt_region) { +bot.dom.getOverflowState = function (elem, opt_region) { var region = bot.dom.getClientRegion(elem, opt_region); var ownerDoc = goog.dom.getOwnerDocument(elem); var htmlElem = ownerDoc.documentElement; @@ -672,14 +663,14 @@ } // An element cannot overflow an element with an inline or contents display style. var containerDisplay = /** @type {string} */ ( - bot.dom.getEffectiveStyle(container, 'display')); + bot.dom.getEffectiveStyle(container, 'display')); if (goog.string.startsWith(containerDisplay, 'inline') || - (containerDisplay == 'contents')) { + (containerDisplay == 'contents')) { return false; } // An absolute-positioned element cannot overflow a static-positioned one. if (position == 'absolute' && - bot.dom.getEffectiveStyle(container, 'position') == 'static') { + bot.dom.getEffectiveStyle(container, 'position') == 'static') { return false; } return true; @@ -696,7 +687,7 @@ if (e == htmlElem && bodyElem) { overflowElem = bodyElem; } else if (e == bodyElem) { - return {x: 'visible', y: 'visible'}; + return { x: 'visible', y: 'visible' }; } } var overflow = { @@ -723,8 +714,8 @@ // Check if the element overflows any ancestor element. for (var container = getOverflowParent(elem); - !!container; - container = getOverflowParent(container)) { + !!container; + container = getOverflowParent(container)) { var containerOverflow = getOverflowStyles(container); // If the container has overflow:visible, the element cannot overflow it. @@ -743,10 +734,10 @@ var underflowsX = region.right < containerRect.left; var underflowsY = region.bottom < containerRect.top; if ((underflowsX && containerOverflow.x == 'hidden') || - (underflowsY && containerOverflow.y == 'hidden')) { + (underflowsY && containerOverflow.y == 'hidden')) { return bot.dom.OverflowState.HIDDEN; } else if ((underflowsX && containerOverflow.x != 'visible') || - (underflowsY && containerOverflow.y != 'visible')) { + (underflowsY && containerOverflow.y != 'visible')) { // When the element is positioned to the left or above a container, we // have to distinguish between the element being completely outside the // container and merely scrolled out of view within the container. @@ -754,28 +745,28 @@ var unscrollableX = region.right < containerRect.left - containerScroll.x; var unscrollableY = region.bottom < containerRect.top - containerScroll.y; if ((unscrollableX && containerOverflow.x != 'visible') || - (unscrollableY && containerOverflow.x != 'visible')) { + (unscrollableY && containerOverflow.x != 'visible')) { return bot.dom.OverflowState.HIDDEN; } var containerState = bot.dom.getOverflowState(container); return containerState == bot.dom.OverflowState.HIDDEN ? - bot.dom.OverflowState.HIDDEN : bot.dom.OverflowState.SCROLL; + bot.dom.OverflowState.HIDDEN : bot.dom.OverflowState.SCROLL; } // Check "overflow": if an element is to the right or below a container var overflowsX = region.left >= containerRect.left + containerRect.width; var overflowsY = region.top >= containerRect.top + containerRect.height; if ((overflowsX && containerOverflow.x == 'hidden') || - (overflowsY && containerOverflow.y == 'hidden')) { + (overflowsY && containerOverflow.y == 'hidden')) { return bot.dom.OverflowState.HIDDEN; } else if ((overflowsX && containerOverflow.x != 'visible') || - (overflowsY && containerOverflow.y != 'visible')) { + (overflowsY && containerOverflow.y != 'visible')) { // If the element has fixed position and falls outside the scrollable area // of the document, then it is hidden. if (treatAsFixedPosition) { var docScroll = getScroll(container); if ((region.left >= htmlElem.scrollWidth - docScroll.x) || - (region.right >= htmlElem.scrollHeight - docScroll.y)) { + (region.right >= htmlElem.scrollHeight - docScroll.y)) { return bot.dom.OverflowState.HIDDEN; } } @@ -784,7 +775,7 @@ // which it is also hidden by overflow. var containerState = bot.dom.getOverflowState(container); return containerState == bot.dom.OverflowState.HIDDEN ? - bot.dom.OverflowState.HIDDEN : bot.dom.OverflowState.SCROLL; + bot.dom.OverflowState.HIDDEN : bot.dom.OverflowState.SCROLL; } } @@ -799,9 +790,9 @@ * @const */ bot.dom.CSS_TRANSFORM_MATRIX_REGEX_ = - new RegExp('matrix\\(([\\d\\.\\-]+), ([\\d\\.\\-]+), ' + - '([\\d\\.\\-]+), ([\\d\\.\\-]+), ' + - '([\\d\\.\\-]+)(?:px)?, ([\\d\\.\\-]+)(?:px)?\\)'); + new RegExp('matrix\\(([\\d\\.\\-]+), ([\\d\\.\\-]+), ' + + '([\\d\\.\\-]+), ([\\d\\.\\-]+), ' + + '([\\d\\.\\-]+)(?:px)?, ([\\d\\.\\-]+)(?:px)?\\)'); /** @@ -815,7 +806,7 @@ * @param {!Element} elem The element to use. * @return {!goog.math.Rect} The interaction box of the element. */ -bot.dom.getClientRect = function(elem) { +bot.dom.getClientRect = function (elem) { var imageMap = bot.dom.maybeFindImageMap_(elem); if (imageMap) { return imageMap.rect; @@ -837,15 +828,7 @@ } var rect = new goog.math.Rect(nativeRect.left, nativeRect.top, - nativeRect.right - nativeRect.left, nativeRect.bottom - nativeRect.top); - - // In IE, the element can additionally be offset by a border around the - // documentElement or body element that we have to subtract. - if (goog.userAgent.IE && elem.ownerDocument.body) { - var doc = goog.dom.getOwnerDocument(elem); - rect.left -= doc.documentElement.clientLeft + doc.body.clientLeft; - rect.top -= doc.documentElement.clientTop + doc.body.clientTop; - } + nativeRect.right - nativeRect.left, nativeRect.bottom - nativeRect.top); return rect; } @@ -862,7 +845,7 @@ * @return {?{image: Element, rect: !goog.math.Rect}} Image and rectangle. * @private */ -bot.dom.maybeFindImageMap_ = function(elem) { +bot.dom.maybeFindImageMap_ = function (elem) { // If not a <map> or <area>, return null indicating so. var isMap = bot.dom.isElement(elem, goog.dom.TagName.MAP); if (!isMap && !bot.dom.isElement(elem, goog.dom.TagName.AREA)) { @@ -871,8 +854,8 @@ // Get the <map> associated with this element, or null if none. var map = isMap ? elem : - (bot.dom.isElement(elem.parentNode, goog.dom.TagName.MAP) ? - elem.parentNode : null); + (bot.dom.isElement(elem.parentNode, goog.dom.TagName.MAP) ? + elem.parentNode : null); var image = null, rect = null; if (map && map.name) { @@ -899,7 +882,7 @@ } } - return {image: image, rect: rect || new goog.math.Rect(0, 0, 0, 0)}; + return { image: image, rect: rect || new goog.math.Rect(0, 0, 0, 0) }; }; @@ -911,7 +894,7 @@ * @return {!goog.math.Rect} Bounding box of the area element. * @private */ -bot.dom.getAreaRelativeRect_ = function(area) { +bot.dom.getAreaRelativeRect_ = function (area) { var shape = area.shape.toLowerCase(); var coords = area.coords.split(','); if (shape == 'rect' && coords.length == 4) { @@ -920,7 +903,7 @@ } else if (shape == 'circle' && coords.length == 3) { var centerX = coords[0], centerY = coords[1], radius = coords[2]; return new goog.math.Rect(centerX - radius, centerY - radius, - 2 * radius, 2 * radius); + 2 * radius, 2 * radius); } else if (shape == 'poly' && coords.length > 2) { var minX = coords[0], minY = coords[1], maxX = minX, maxY = minY; for (var i = 2; i + 1 < coords.length; i += 2) { @@ -945,20 +928,20 @@ * Coordinate or rectangle relative to the top-left corner of the element. * @return {!goog.math.Box} The client region box. */ -bot.dom.getClientRegion = function(elem, opt_region) { +bot.dom.getClientRegion = function (elem, opt_region) { var region = bot.dom.getClientRect(elem).toBox(); if (opt_region) { var rect = opt_region instanceof goog.math.Rect ? opt_region : - new goog.math.Rect(opt_region.x, opt_region.y, 1, 1); + new goog.math.Rect(opt_region.x, opt_region.y, 1, 1); region.left = goog.math.clamp( - region.left + rect.left, region.left, region.right); + region.left + rect.left, region.left, region.right); region.top = goog.math.clamp( - region.top + rect.top, region.top, region.bottom); + region.top + rect.top, region.top, region.bottom); region.right = goog.math.clamp( - region.left + rect.width, region.left, region.right); + region.left + rect.width, region.left, region.right); region.bottom = goog.math.clamp( - region.top + rect.height, region.top, region.bottom); + region.top + rect.height, region.top, region.bottom); } return region; @@ -974,7 +957,7 @@ * except non-breaking spaces. * @private */ -bot.dom.trimExcludingNonBreakingSpaceCharacters_ = function(str) { +bot.dom.trimExcludingNonBreakingSpaceCharacters_ = function (str) { return str.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g, ''); }; @@ -985,7 +968,7 @@ * @return {string} cleaned up concatenated lines * @private */ -bot.dom.concatenateCleanedLines_ = function(lines) { +bot.dom.concatenateCleanedLines_ = function (lines) { lines = goog.array.map( lines, bot.dom.trimExcludingNonBreakingSpaceCharacters_); @@ -1001,7 +984,7 @@ * @param {!Element} elem The element to consider. * @return {string} visible text. */ -bot.dom.getVisibleText = function(elem) { +bot.dom.getVisibleText = function (elem) { var lines = []; if (bot.dom.IS_SHADOW_DOM_ENABLED) { @@ -1024,8 +1007,8 @@ * childNodeFn function to call to append lines from any child nodes * @private */ -bot.dom.appendVisibleTextLinesFromElementCommon_ = function( - elem, lines, isShownFn, childNodeFn) { +bot.dom.appendVisibleTextLinesFromElementCommon_ = function ( + elem, lines, isShownFn, childNodeFn) { function currLine() { return /** @type {string|undefined} */ (goog.array.peek(lines)) || ''; } @@ -1039,7 +1022,7 @@ var display = bot.dom.getEffectiveStyle(elem, 'display'); // On some browsers, table cells incorrectly show up with block styles. var isBlock = !isTD && - !goog.array.contains(bot.dom.INLINE_DISPLAY_BOXES_, display); + !goog.array.contains(bot.dom.INLINE_DISPLAY_BOXES_, display); // Add a newline before block elems when there is text on the current line, // except when the previous sibling has a display: run-in. @@ -1047,14 +1030,14 @@ var previousElementSibling = goog.dom.getPreviousElementSibling(elem); var prevDisplay = (previousElementSibling) ? - bot.dom.getEffectiveStyle(previousElementSibling, 'display') : ''; + bot.dom.getEffectiveStyle(previousElementSibling, 'display') : ''; // TODO: getEffectiveStyle should mask this for us var thisFloat = bot.dom.getEffectiveStyle(elem, 'float') || - bot.dom.getEffectiveStyle(elem, 'cssFloat') || - bot.dom.getEffectiveStyle(elem, 'styleFloat'); + bot.dom.getEffectiveStyle(elem, 'cssFloat') || + bot.dom.getEffectiveStyle(elem, 'styleFloat'); var runIntoThis = prevDisplay == 'run-in' && thisFloat == 'none'; if (isBlock && !runIntoThis && - !goog.string.isEmptyOrWhitespace(currLine())) { + !goog.string.isEmptyOrWhitespace(currLine())) { lines.push(''); } @@ -1073,7 +1056,7 @@ textTransform = bot.dom.getEffectiveStyle(elem, 'text-transform'); } - goog.array.forEach(elem.childNodes, function(node) { + goog.array.forEach(elem.childNodes, function (node) { childNodeFn(node, lines, shown, whitespace, textTransform); }); @@ -1083,14 +1066,14 @@ // such a thing). Usually, table cells are separated by a tab, but we // normalize tabs into single spaces. if ((isTD || display == 'table-cell') && line && - !goog.string.endsWith(line, ' ')) { + !goog.string.endsWith(line, ' ')) { lines[lines.length - 1] += ' '; } // Add a newline after block elems when there is text on the current line, // and the current element isn't marked as run-in. if (isBlock && display != 'run-in' && - !goog.string.isEmptyOrWhitespace(line)) { + !goog.string.isEmptyOrWhitespace(line)) { lines.push(''); } } @@ -1102,19 +1085,19 @@ * @param {!Array.<string>} lines Accumulated visible lines of text. * @private */ -bot.dom.appendVisibleTextLinesFromElement_ = function(elem, lines) { - bot.dom.appendVisibleTextLinesFromElementCommon_( - elem, lines, bot.dom.isShown, - function(node, lines, shown, whitespace, textTransform) { - if (node.nodeType == goog.dom.NodeType.TEXT && shown) { - var textNode = /** @type {!Text} */ (node); - bot.dom.appendVisibleTextLinesFromTextNode_(textNode, lines, - whitespace, textTransform); - } else if (bot.dom.isElement(node)) { - var castElem = /** @type {!Element} */ (node); - bot.dom.appendVisibleTextLinesFromElement_(castElem, lines); - } - }); +bot.dom.appendVisibleTextLinesFromElement_ = function (elem, lines) { + bot.dom.appendVisibleTextLinesFromElementCommon_( + elem, lines, bot.dom.isShown, + function (node, lines, shown, whitespace, textTransform) { + if (node.nodeType == goog.dom.NodeType.TEXT && shown) { + var textNode = /** @type {!Text} */ (node); + bot.dom.appendVisibleTextLinesFromTextNode_(textNode, lines, + whitespace, textTransform); + } else if (bot.dom.isElement(node)) { + var castElem = /** @type {!Element} */ (node); + bot.dom.appendVisibleTextLinesFromElement_(castElem, lines); + } + }); }; @@ -1142,8 +1125,8 @@ * @param {?string} textTransform Parent element's "text-transform" style. * @private */ -bot.dom.appendVisibleTextLinesFromTextNode_ = function(textNode, lines, - whitespace, textTransform) { +bot.dom.appendVisibleTextLinesFromTextNode_ = function (textNode, lines, + whitespace, textTransform) { // First, remove zero-width characters. Do this before regularizing spaces as // the zero-width space is both zero-width and a space, but we do not want to @@ -1172,9 +1155,8 @@ } if (textTransform == 'capitalize') { - // the unicode regex ending with /gu does not work in IE - var re = goog.userAgent.IE ? /(^|\s|\b)(\S)/g : /(^|\s|\b)(\S)/gu; - text = text.replace(re, function() { + var re = /(^|\s|\b)(\S)/gu; + text = text.replace(re, function () { return arguments[1] + arguments[2].toUpperCase(); }); } else if (textTransform == 'uppercase') { @@ -1185,7 +1167,7 @@ var currLine = lines.pop() || ''; if (goog.string.endsWith(currLine, ' ') && - goog.string.startsWith(text, ' ')) { + goog.string.startsWith(text, ' ')) { text = text.substr(1); } lines.push(currLine + text); @@ -1200,27 +1182,9 @@ * @param {!Element} elem Element whose opacity has to be found. * @return {number} Opacity between 0 and 1. */ -bot.dom.getOpacity = function(elem) { +bot.dom.getOpacity = function (elem) { // TODO: Does this need to deal with rgba colors? - if (!bot.userAgent.IE_DOC_PRE9) { - return bot.dom.getOpacityNonIE_(elem); - } else { - if (bot.dom.getEffectiveStyle(elem, 'position') == 'relative') { - // Filter does not apply to non positioned elements. - return 1; - } - - var opacityStyle = bot.dom.getEffectiveStyle(elem, 'filter'); - var groups = opacityStyle.match(/^alpha\(opacity=(\d*)\)/) || - opacityStyle.match( - /^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/); - - if (groups) { - return Number(groups[1]) / 100; - } else { - return 1; // Opaque. - } - } + return bot.dom.getOpacityNonIE_(elem); }; @@ -1232,7 +1196,7 @@ * @return {number} Opacity between 0 and 1. * @private */ -bot.dom.getOpacityNonIE_ = function(elem) { +bot.dom.getOpacityNonIE_ = function (elem) { // By default the element is opaque. var elemOpacity = 1; @@ -1266,7 +1230,7 @@ * @param {!Node} node The node whose parent is desired. * @return {Node} The parent node, if available, null otherwise. */ -bot.dom.getParentNodeInComposedDom = function(node) { +bot.dom.getParentNodeInComposedDom = function (node) { var /**@type {Node}*/ parent = node.parentNode; // Shadow DOM v1 @@ -1297,13 +1261,13 @@ * @private * @suppress {missingProperties} */ -bot.dom.appendVisibleTextLinesFromNodeInComposedDom_ = function( - node, lines, shown, whitespace, textTransform) { +bot.dom.appendVisibleTextLinesFromNodeInComposedDom_ = function ( + node, lines, shown, whitespace, textTransform) { if (node.nodeType == goog.dom.NodeType.TEXT && shown) { var textNode = /** @type {!Text} */ (node); bot.dom.appendVisibleTextLinesFromTextNode_(textNode, lines, - whitespace, textTransform); + whitespace, textTransform); } else if (bot.dom.isElement(node)) { var castElem = /** @type {!Element} */ (node); @@ -1326,7 +1290,7 @@ shadowChildren.length > 0 ? shadowChildren : contentElem.childNodes; goog.array.forEach(childrenToTraverse, function (node) { bot.dom.appendVisibleTextLinesFromNodeInComposedDom_( - node, lines, shown, whitespace, textTransform); + node, lines, shown, whitespace, textTransform); }); } else { // if we're not inside a shadow DOM, then we just treat <content> @@ -1348,10 +1312,10 @@ var olderShadowRoot = thisShadowRoot.olderShadowRoot; while (olderShadowRoot) { goog.array.forEach( - olderShadowRoot.childNodes, function(childNode) { - bot.dom.appendVisibleTextLinesFromNodeInComposedDom_( + olderShadowRoot.childNodes, function (childNode) { + bot.dom.appendVisibleTextLinesFromNodeInComposedDom_( childNode, lines, shown, whitespace, textTransform); - }); + }); olderShadowRoot = olderShadowRoot.olderShadowRoot; } } @@ -1371,7 +1335,7 @@ * @param {!Node} node The node to check * @return {boolean} True if the node has been distributed. */ -bot.dom.isNodeDistributedIntoShadowDom = function(node) { +bot.dom.isNodeDistributedIntoShadowDom = function (node) { var elemOrText = null; if (node.nodeType == goog.dom.NodeType.ELEMENT) { elemOrText = /** @type {!Element} */ (node); @@ -1379,10 +1343,10 @@ elemOrText = /** @type {!Text} */ (node); } return elemOrText != null && - (elemOrText.assignedSlot != null || - (elemOrText.getDestinationInsertionPoints && + (elemOrText.assignedSlot != null || + (elemOrText.getDestinationInsertionPoints && elemOrText.getDestinationInsertionPoints().length > 0) - ); + ); }; @@ -1391,24 +1355,24 @@ * @param {!Array.<string>} lines Accumulated visible lines of text. * @private */ -bot.dom.appendVisibleTextLinesFromElementInComposedDom_ = function( - elem, lines) { +bot.dom.appendVisibleTextLinesFromElementInComposedDom_ = function ( + elem, lines) { if (elem.shadowRoot) { - goog.array.forEach(elem.shadowRoot.childNodes, function(node) { - bot.dom.appendVisibleTextLinesFromNodeInComposedDom_( - node, lines, true, null, null); - }); + goog.array.forEach(elem.shadowRoot.childNodes, function (node) { + bot.dom.appendVisibleTextLinesFromNodeInComposedDom_( + node, lines, true, null, null); + }); } bot.dom.appendVisibleTextLinesFromElementCommon_( elem, lines, bot.dom.isShown, - function(node, lines, shown, whitespace, textTransform) { + function (node, lines, shown, whitespace, textTransform) { // If the node has been distributed into a shadowDom element // to be displayed elsewhere, then we shouldn't append // its contents here). if (!bot.dom.isNodeDistributedIntoShadowDom(node)) { bot.dom.appendVisibleTextLinesFromNodeInComposedDom_( - node, lines, shown, whitespace, textTransform); + node, lines, shown, whitespace, textTransform); } }); };
diff --git a/javascript/atoms/events.js b/javascript/atoms/events.js index dad4a29..37316e1 100644 --- a/javascript/atoms/events.js +++ b/javascript/atoms/events.js
@@ -71,8 +71,7 @@ * @const * @type {boolean} */ -bot.events.SUPPORTS_MSPOINTER_EVENTS = - goog.userAgent.IE && bot.getWindow().navigator.msPointerEnabled; +bot.events.SUPPORTS_MSPOINTER_EVENTS = false; /**
diff --git a/javascript/atoms/json.js b/javascript/atoms/json.js index 77c871f..bf9b976 100644 --- a/javascript/atoms/json.js +++ b/javascript/atoms/json.js
@@ -24,7 +24,6 @@ goog.require('bot.userAgent'); goog.require('goog.json'); -goog.require('goog.userAgent'); /** @@ -48,14 +47,7 @@ * @see http://caniuse.com/#search=JSON * @private {boolean} */ -bot.json.SUPPORTS_NATIVE_JSON_ = - // List WebKit first since every supported version supports - // native JSON (and we can compile away large chunks of code for - // individual fragments by setting the appropriate compiler flags). - goog.userAgent.WEBKIT || - (goog.userAgent.GECKO && bot.userAgent.isEngineVersion(3.5)) || - (goog.userAgent.IE && bot.userAgent.isEngineVersion(8)); - +bot.json.SUPPORTS_NATIVE_JSON_ = true; /** * Converts a JSON object to its string representation.
diff --git a/javascript/atoms/keyboard.js b/javascript/atoms/keyboard.js index 02d1590..68ca126 100644 --- a/javascript/atoms/keyboard.js +++ b/javascript/atoms/keyboard.js
@@ -400,7 +400,7 @@ * @private {string} * @const */ -bot.Keyboard.NEW_LINE_ = goog.userAgent.IE ? '\r\n' : '\n'; +bot.Keyboard.NEW_LINE_ = '\n'; /** @@ -465,8 +465,6 @@ return true; } else if (goog.userAgent.WEBKIT || goog.userAgent.EDGE) { return false; - } else if (goog.userAgent.IE) { - return key == bot.Keyboard.Keys.ESC; } else { // Gecko switch (key) { case bot.Keyboard.Keys.SHIFT: @@ -641,9 +639,7 @@ } else { this.getElement().value += bot.Keyboard.NEW_LINE_; } - if (!goog.userAgent.IE) { - this.fireHtmlEvent(bot.events.EventType.INPUT); - } + this.fireHtmlEvent(bot.events.EventType.INPUT); this.updateCurrentPos_(newPos); } }; @@ -679,15 +675,7 @@ endpoints[1] == 0); goog.dom.selection.setText(this.getElement(), ''); - // Except for IE and GECKO, we need to fire the input event manually, but - // only if the text was actually changed. - // Note: Gecko has some strange behavior with the input event. In a - // textarea, backspace always sends an input event, while delete only - // sends one if you actually change the text. - // In a textbox/password box, backspace always sends an input event unless - // the box has no text. Delete behaves the same way in Firefox 3.0, but - // in later versions it only fires an input event if no text changes. - if (!goog.userAgent.IE && textChanged || + if (textChanged || (goog.userAgent.GECKO && key == bot.Keyboard.Keys.BACKSPACE)) { this.fireHtmlEvent(bot.events.EventType.INPUT); }
diff --git a/javascript/atoms/locators/css.js b/javascript/atoms/locators/css.js index d141294..52598c8 100644 --- a/javascript/atoms/locators/css.js +++ b/javascript/atoms/locators/css.js
@@ -37,13 +37,6 @@ * such element could be found. */ bot.locators.css.single = function (target, root) { - if (!goog.isFunction(root['querySelector']) && - // IE8 in non-compatibility mode reports querySelector as an object. - goog.userAgent.IE && bot.userAgent.isEngineVersion(8) && - !goog.isObject(root['querySelector'])) { - throw Error('CSS selection is not supported'); - } - if (!target) { throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR, 'No selector specified'); @@ -73,13 +66,6 @@ * @return {!IArrayLike} All matching elements, or an empty list. */ bot.locators.css.many = function (target, root) { - if (!goog.isFunction(root['querySelectorAll']) && - // IE8 in non-compatibility mode reports querySelector as an object. - goog.userAgent.IE && bot.userAgent.isEngineVersion(8) && - !goog.isObject(root['querySelector'])) { - throw Error('CSS selection is not supported'); - } - if (!target) { throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR, 'No selector specified');
diff --git a/javascript/atoms/test/focus_test.html b/javascript/atoms/test/focus_test.html index 7e10b1d..2e9415e 100644 --- a/javascript/atoms/test/focus_test.html +++ b/javascript/atoms/test/focus_test.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <html> + <head> <title>focus_test.html</title> <script src="test_bootstrap.js"></script> @@ -45,7 +46,7 @@ } function recordBlurAndFocus(el) { - events.listen(el, [eventType.FOCUS, eventType.BLUR], function(e) { + events.listen(el, [eventType.FOCUS, eventType.BLUR], function (e) { actualEvents.push(buildRecord(e.target.id, e.type)); }); } @@ -67,7 +68,7 @@ // "'constructor' is null or not an object". // The following assertions give us the same check without this error. var msg = 'Expected "' + expected.id + '" to be the activeElement, ' + - 'but was "' + actual.id + '".'; + 'but was "' + actual.id + '".'; assertTrue(msg, expected == actual); } } @@ -77,18 +78,12 @@ * is scheduled for the next event loop after element.focus() is called. */ function timeout() { - return new goog.Promise(function(done) { + return new goog.Promise(function (done) { setTimeout(done, 5); }); } function testShouldBeAbleToFocusOnAnElement() { - // NOTE(jleyba): Test does not work on IE 8 with the new IE Driver, - // I suspect due to something similar to - // http://support.microsoft.com/kb/973528 - if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8')) { - return; - } if (!bot.test.isWindowFocused()) { return; } @@ -97,7 +92,7 @@ expect(eventType.FOCUS, text1); bot.action.focusOnElement(text1); - return timeout().then(function() { + return timeout().then(function () { assertHasExpectedEventOrder(); assertElementIsActiveElement(text1); @@ -105,7 +100,7 @@ expect(eventType.FOCUS, text2); bot.action.focusOnElement(text2); return timeout(); - }).then(function() { + }).then(function () { assertHasExpectedEventOrder(); assertElementIsActiveElement(text2); @@ -113,7 +108,7 @@ expect(eventType.FOCUS, text1); bot.action.focusOnElement(text1); return timeout(); - }).then(function() { + }).then(function () { assertHasExpectedEventOrder(); assertElementIsActiveElement(text1); }); @@ -129,13 +124,13 @@ expect(eventType.FOCUS, text1); bot.action.focusOnElement(text1); - return timeout().then(function() { + return timeout().then(function () { assertHasExpectedEventOrder(); assertElementIsActiveElement(text1); bot.action.focusOnElement(text1); return timeout(); - }).then(function() { + }).then(function () { assertHasExpectedEventOrder(); assertElementIsActiveElement(text1); }); @@ -152,21 +147,21 @@ expect(eventType.FOCUS, parent); bot.action.focusOnElement(parent); - return timeout().then(function() { + return timeout().then(function () { assertHasExpectedEventOrder(); assertElementIsActiveElement(parent); bot.action.focusOnElement(child); // No additional events expected. The parent should retain focus. return timeout(); - }).then(function() { + }).then(function () { assertHasExpectedEventOrder(); assertElementIsActiveElement(parent); bot.action.focusOnElement(text1); expect(eventType.BLUR, parent); return timeout(); - }).then(function() { + }).then(function () { assertHasExpectedEventOrder(); }); } @@ -182,10 +177,6 @@ } function testIsFocusable() { - if (goog.userAgent.IE) { - // TODO: Don't skip this. - return; - } function assertIsFocusable(element, opt_reason) { assertTrue(opt_reason || '', bot.dom.isFocusable(element)); } @@ -194,9 +185,9 @@ assertFalse(opt_reason || '', bot.dom.isFocusable(element)); } - goog.array.forEach(bot.dom.FOCUSABLE_FORM_FIELDS_, function(tagName) { + goog.array.forEach(bot.dom.FOCUSABLE_FORM_FIELDS_, function (tagName) { assertIsFocusable(goog.dom.createDom(tagName), - tagName + ' is a focusable form field'); + tagName + ' is a focusable form field'); }); var div = goog.dom.createDom('DIV'); @@ -219,77 +210,77 @@ } </script> </head> + <body> -<form action="javascript:void(0)"> - <input id="text1" type="text"/> - <input id="text2" type="text"/> - <input id="dummyFocusHolder" type="text"/> - <div> - <div>Input fields for manual testing. Each will report when they receive or - lose focus.</div> - Test 1: <input id="test1" type="text"/> - Test 2: <input id="test2" type="text"/> + <form action="javascript:void(0)"> + <input id="text1" type="text" /> + <input id="text2" type="text" /> + <input id="dummyFocusHolder" type="text" /> <div> - <button id="focusDance">Click to simulate focus change</button> - <button id="clearTestLog">Click to clear log</button> - <button id="opennewwindow" onclick="window.open(window.location)"> - Re-run test in a new window</button> - </div> - <div style="border:1px solid black; margin: 5px; padding: 5px; width:50%"> - <div style="border-bottom: 1px solid black">Test Log</div> - <div id="testLog"></div> - </div> - <div> - <div><strong>Invisible textbox</strong></div> - <input id="invisibleText" type="text" style="visibility:hidden"/> - </div> - <div> - <div><strong>Disabled textbox</strong></div> - <input id="disabledText" type="text" value="I'm disabled" disabled/> - </div> - <div id="hideOnBlur" tabindex="0" - style="width: 100px; height: 100px; border: 1px solid red" - onblur="this.style.display = 'none';"> - <div id="hideOnBlurChild" - style="width: 30px; height: 30px; border: 1px solid blue"> - x + <div>Input fields for manual testing. Each will report when they receive or + lose focus.</div> + Test 1: <input id="test1" type="text" /> + Test 2: <input id="test2" type="text" /> + <div> + <button id="focusDance">Click to simulate focus change</button> + <button id="clearTestLog">Click to clear log</button> + <button id="opennewwindow" onclick="window.open(window.location)"> + Re-run test in a new window</button> </div> - Focusable. Will hide when focus is lost. - </div> - <script type="text/javascript"> - function log(msg) { - goog.dom.$('testLog').appendChild( + <div style="border:1px solid black; margin: 5px; padding: 5px; width:50%"> + <div style="border-bottom: 1px solid black">Test Log</div> + <div id="testLog"></div> + </div> + <div> + <div><strong>Invisible textbox</strong></div> + <input id="invisibleText" type="text" style="visibility:hidden" /> + </div> + <div> + <div><strong>Disabled textbox</strong></div> + <input id="disabledText" type="text" value="I'm disabled" disabled /> + </div> + <div id="hideOnBlur" tabindex="0" style="width: 100px; height: 100px; border: 1px solid red" + onblur="this.style.display = 'none';"> + <div id="hideOnBlurChild" style="width: 30px; height: 30px; border: 1px solid blue"> + x + </div> + Focusable. Will hide when focus is lost. + </div> + <script type="text/javascript"> + function log(msg) { + goog.dom.$('testLog').appendChild( goog.dom.createDom('div', null, goog.dom.createTextNode(msg))); - } + } - function reportBlurFocus(e) { - var et = eventType; - goog.events.listen(e, [et.FOCUS, et.BLUR], function(e) { - log(e.type + ' on ' + e.target.id); - }); - } - reportBlurFocus(goog.dom.$('test1')); - reportBlurFocus(goog.dom.$('test2')); + function reportBlurFocus(e) { + var et = eventType; + goog.events.listen(e, [et.FOCUS, et.BLUR], function (e) { + log(e.type + ' on ' + e.target.id); + }); + } + reportBlurFocus(goog.dom.$('test1')); + reportBlurFocus(goog.dom.$('test2')); - goog.events.listen(goog.dom.$('focusDance'), eventType.CLICK, - function(e) { - log('starting focus dance in .5s'); - log(' will focus on 1, then 2, then 1 again'); - window.setTimeout(function() { - bot.action.focusOnElement(goog.dom.$('test1')); - bot.action.focusOnElement(goog.dom.$('test2')); - bot.action.focusOnElement(goog.dom.$('test1')); - log('if you see this before event logs, then events are ' + + goog.events.listen(goog.dom.$('focusDance'), eventType.CLICK, + function (e) { + log('starting focus dance in .5s'); + log(' will focus on 1, then 2, then 1 again'); + window.setTimeout(function () { + bot.action.focusOnElement(goog.dom.$('test1')); + bot.action.focusOnElement(goog.dom.$('test2')); + bot.action.focusOnElement(goog.dom.$('test1')); + log('if you see this before event logs, then events are ' + 'fired in a separate event loop'); - }, 500); - }); - goog.events.listen(goog.dom.$('clearTestLog'), eventType.CLICK, - function(e) { - goog.dom.removeChildren(goog.dom.$('testLog')); - }); - </script> - </div> -</form> + }, 500); + }); + goog.events.listen(goog.dom.$('clearTestLog'), eventType.CLICK, + function (e) { + goog.dom.removeChildren(goog.dom.$('testLog')); + }); + </script> + </div> + </form> </body> + </html>
diff --git a/javascript/atoms/test/keyboard_test.html b/javascript/atoms/test/keyboard_test.html index f096658..f25c844 100644 --- a/javascript/atoms/test/keyboard_test.html +++ b/javascript/atoms/test/keyboard_test.html
@@ -21,8 +21,6 @@ function setUpPage() { if (goog.userAgent.GECKO) { browser = 'GECKO'; - } else if (goog.userAgent.IE) { - browser = 'IE'; } else if (goog.userAgent.WEBKIT || goog.userAgent.EDGE) { browser = 'WEBKIT'; } else {
diff --git a/javascript/atoms/test/mouse_test.html b/javascript/atoms/test/mouse_test.html index cfc8469..35a8fb2 100644 --- a/javascript/atoms/test/mouse_test.html +++ b/javascript/atoms/test/mouse_test.html
@@ -1,465 +1,405 @@ <!DOCTYPE html> <html> + <head> -<title>mouse_test</title> -<script src="test_bootstrap.js"></script> -<script type="text/javascript"> - goog.require('bot.Mouse'); - goog.require('bot.action'); - goog.require('bot.userAgent'); - goog.require('goog.Promise'); - goog.require('goog.array'); - goog.require('goog.dom'); - goog.require('goog.events'); - goog.require('goog.events.EventType'); - goog.require('goog.math.Coordinate'); - goog.require('goog.style'); - goog.require('goog.testing.jsunit'); - goog.require('goog.userAgent'); -</script> + <title>mouse_test</title> + <script src="test_bootstrap.js"></script> + <script type="text/javascript"> + goog.require('bot.Mouse'); + goog.require('bot.action'); + goog.require('bot.userAgent'); + goog.require('goog.Promise'); + goog.require('goog.array'); + goog.require('goog.dom'); + goog.require('goog.events'); + goog.require('goog.events.EventType'); + goog.require('goog.math.Coordinate'); + goog.require('goog.style'); + goog.require('goog.testing.jsunit'); + goog.require('goog.userAgent'); + </script> + <body> -<div id="green" style="background-color:green; width:100px; height:50px"> -<div id="red" style="background-color:red; width:50px; height:25px; + <div id="green" style="background-color:green; width:100px; height:50px"> + <div id="red" style="background-color:red; width:50px; height:25px; position: relative; top:25px;">Red</div> -</div> -<div id="capture" style="background-color:blue; width:100px; height:50px"> - <div id="innerCapture" style="background-color:cyan; + </div> + <div id="capture" style="background-color:blue; width:100px; height:50px"> + <div id="innerCapture" style="background-color:cyan; width:50px; height:25px;"> + </div> </div> -</div> -<script type="text/javascript"> - // The goog.events.EventType enum is missing mouse scrolling event types. - // This a little hacky but gives us some stylistic consistency :). - goog.events.EventType.MOUSEWHEEL = - goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel'; - goog.events.EventType.MOUSEPIXELSCROLL = 'MozMousePixelScroll'; + <script type="text/javascript"> + // The goog.events.EventType enum is missing mouse scrolling event types. + // This a little hacky but gives us some stylistic consistency :). + goog.events.EventType.MOUSEWHEEL = + goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel'; + goog.events.EventType.MOUSEPIXELSCROLL = 'MozMousePixelScroll'; - var events = []; - var greenDiv, redDiv, captureDiv, innerCaptureDiv; - var MOUSE_EVENTS = [ - goog.events.EventType.MOUSEOUT, - goog.events.EventType.MOUSEOVER, - goog.events.EventType.MOUSEMOVE, - goog.events.EventType.MOUSEDOWN, - goog.events.EventType.MOUSEUP, - goog.events.EventType.MOUSEWHEEL, - goog.events.EventType.MOUSEPIXELSCROLL, - goog.events.EventType.CLICK, - goog.events.EventType.CONTEXTMENU, - goog.events.EventType.DBLCLICK, - goog.events.EventType.MSPOINTERDOWN, - goog.events.EventType.MSPOINTERMOVE, - goog.events.EventType.MSPOINTEROVER, - goog.events.EventType.MSPOINTEROUT, - goog.events.EventType.MSPOINTERUP - ]; + var events = []; + var greenDiv, redDiv, captureDiv, innerCaptureDiv; + var MOUSE_EVENTS = [ + goog.events.EventType.MOUSEOUT, + goog.events.EventType.MOUSEOVER, + goog.events.EventType.MOUSEMOVE, + goog.events.EventType.MOUSEDOWN, + goog.events.EventType.MOUSEUP, + goog.events.EventType.MOUSEWHEEL, + goog.events.EventType.MOUSEPIXELSCROLL, + goog.events.EventType.CLICK, + goog.events.EventType.CONTEXTMENU, + goog.events.EventType.DBLCLICK, + goog.events.EventType.MSPOINTERDOWN, + goog.events.EventType.MSPOINTERMOVE, + goog.events.EventType.MSPOINTEROVER, + goog.events.EventType.MSPOINTEROUT, + goog.events.EventType.MSPOINTERUP + ]; - function setUpPage() { - greenDiv = bot.locators.findElement({id: 'green'}); - redDiv = bot.locators.findElement({id: 'red'}); - captureDiv = bot.locators.findElement({id: 'capture'}); - innerCaptureDiv = bot.locators.findElement({id: 'innerCapture'}); - goog.testing.TestCase.getActiveTestCase().promiseTimeout = 30000; // 30s - } + function setUpPage() { + greenDiv = bot.locators.findElement({ id: 'green' }); + redDiv = bot.locators.findElement({ id: 'red' }); + captureDiv = bot.locators.findElement({ id: 'capture' }); + innerCaptureDiv = bot.locators.findElement({ id: 'innerCapture' }); + goog.testing.TestCase.getActiveTestCase().promiseTimeout = 30000; // 30s + } - function setUp() { - bot.getDocument().documentElement.focus(); - events = []; - goog.events.removeAll(greenDiv); - goog.events.removeAll(redDiv); - goog.events.removeAll(captureDiv); - goog.events.removeAll(innerCaptureDiv); + function setUp() { + bot.getDocument().documentElement.focus(); + events = []; + goog.events.removeAll(greenDiv); + goog.events.removeAll(redDiv); + goog.events.removeAll(captureDiv); + goog.events.removeAll(innerCaptureDiv); - goog.events.listen(greenDiv, MOUSE_EVENTS, function(e) { - events.push(e.type); - events.push(e.target); - events.push(e.button); - }); + goog.events.listen(greenDiv, MOUSE_EVENTS, function (e) { + events.push(e.type); + events.push(e.target); + events.push(e.button); + }); - goog.events.listen(captureDiv, MOUSE_EVENTS, function(e) { - events.push(e.type); - events.push(e.target); - events.push(e.button); - if (e.type == goog.events.EventType.MSPOINTERDOWN) { - captureDiv.msSetPointerCapture(e.getBrowserEvent().pointerId); + goog.events.listen(captureDiv, MOUSE_EVENTS, function (e) { + events.push(e.type); + events.push(e.target); + events.push(e.button); + if (e.type == goog.events.EventType.MSPOINTERDOWN) { + captureDiv.msSetPointerCapture(e.getBrowserEvent().pointerId); + } + }); + } + + /** + * Returns the button value in the object depending on the current useragent. + * Returns the 'wk' property for WebKit and IE9 in standards mode, the 'ie' + * property for IE, and the 'ff' property for Firefox. + */ + function b(button) { + return goog.userAgent.WEBKIT ? button['wk'] : button['ff']; // Firefox + } + + function assertEvents(var_args) { + var expectedEvents = goog.array.concat.apply(null, arguments); + assertArrayEquals(expectedEvents, events); + events = []; + } + + function mousedownEvents(elem, button) { + return [goog.events.EventType.MOUSEDOWN, elem, button]; + } + + function mousemoveEvents(elem, button) { + return [goog.events.EventType.MOUSEMOVE, elem, button]; + } + + function mouseoutEvents(elem, button) { + return [goog.events.EventType.MOUSEOUT, elem, button]; + } + + function mouseupEvents(elem, button) { + return [goog.events.EventType.MOUSEUP, elem, button]; + } + + function mouseoverAndMoveEvents(elem, button) { + function mouseoverEvents(elem, button) { + return [goog.events.EventType.MOUSEOVER, elem, button]; + } - }); - } - /** - * Returns the button value in the object depending on the current useragent. - * Returns the 'wk' property for WebKit and IE9 in standards mode, the 'ie' - * property for IE, and the 'ff' property for Firefox. - */ - function b(button) { - return bot.userAgent.IE_DOC_9 || goog.userAgent.WEBKIT ? button['wk'] : - (goog.userAgent.IE ? button['ie'] : - button['ff']); // Firefox - } - - function assertEvents(var_args) { - var expectedEvents = goog.array.concat.apply(null, arguments); - assertArrayEquals(expectedEvents, events); - events = []; - } - - function mousedownEvents(elem, button) { - var events = [goog.events.EventType.MOUSEDOWN, elem, button]; - return !bot.userAgent.IE_DOC_10 ? events : - [goog.events.EventType.MSPOINTERDOWN, elem, button].concat(events); - } - - function mousemoveEvents(elem, button) { - var events = [goog.events.EventType.MOUSEMOVE, elem, button]; - return bot.userAgent.IE_DOC_10 ? - [goog.events.EventType.MSPOINTERMOVE, elem, -1].concat(events) : - events; - } - - function mouseoutEvents(elem, button) { - var events = [goog.events.EventType.MOUSEOUT, elem, button]; - return bot.userAgent.IE_DOC_10 ? - [goog.events.EventType.MSPOINTEROUT, elem, -1].concat(events) : - events; - } - - function mouseupEvents(elem, button) { - var events = [goog.events.EventType.MOUSEUP, elem, button]; - return bot.userAgent.IE_DOC_10 ? - [goog.events.EventType.MSPOINTERUP, elem, button].concat(events) : - events; - } - - function mouseoverAndMoveEvents(elem, button) { - function mouseoverEvents(elem, button) { - var events = [goog.events.EventType.MOUSEOVER, elem, button]; - return bot.userAgent.IE_DOC_10 ? - [goog.events.EventType.MSPOINTEROVER, elem, -1].concat(events) : - events; + return mouseoverEvents(elem, button) + .concat(mousemoveEvents(elem, button)); } - // IE fires the movemove *before* the mouseover event, and - // IE < 9 always supplies a mouseover button value of 0. - return goog.userAgent.IE ? - mousemoveEvents(elem, button).concat( - mouseoverEvents(elem, bot.userAgent.IE_DOC_9 ? button : 0)) : - mouseoverEvents(elem, button).concat(mousemoveEvents(elem, button)); - } - function testNoClickWhenPressHiddenElement() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(greenDiv, coords); - goog.style.showElement(greenDiv, false); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.releaseButton(); + function testNoClickWhenPressHiddenElement() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(greenDiv, coords); + goog.style.showElement(greenDiv, false); + mouse.pressButton(bot.Mouse.Button.LEFT); + mouse.releaseButton(); - assertEvents(mouseoverAndMoveEvents(greenDiv, 0)); - goog.style.showElement(greenDiv, true); - } + assertEvents(mouseoverAndMoveEvents(greenDiv, 0)); + goog.style.showElement(greenDiv, true); + } - function testLeftClick() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(redDiv, coords); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.releaseButton(); + function testLeftClick() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(redDiv, coords); + mouse.pressButton(bot.Mouse.Button.LEFT); + mouse.releaseButton(); - assertEvents( - mouseoverAndMoveEvents(redDiv, 0), - mousedownEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - mouseupEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - goog.events.EventType.CLICK, redDiv, 0 - ); - } + assertEvents( + mouseoverAndMoveEvents(redDiv, 0), + mousedownEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + mouseupEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + goog.events.EventType.CLICK, redDiv, 0 + ); + } - function testNoLeftClickWhenReleasedOverOtherElement() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(greenDiv, coords); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.move(redDiv, coords); - mouse.releaseButton(); + function testNoLeftClickWhenReleasedOverOtherElement() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(greenDiv, coords); + mouse.pressButton(bot.Mouse.Button.LEFT); + mouse.move(redDiv, coords); + mouse.releaseButton(); - // No click if we released on another element. - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - mousedownEvents(greenDiv, b({ie: 1, wk: 0, ff: 0})), - mouseoutEvents(greenDiv, 0), - mouseoverAndMoveEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - mouseupEvents(redDiv, b({ie: 1, wk: 0, ff: 0})) - ); - } + // No click if we released on another element. + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + mousedownEvents(greenDiv, b({ ie: 1, wk: 0, ff: 0 })), + mouseoutEvents(greenDiv, 0), + mouseoverAndMoveEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + mouseupEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })) + ); + } - function testRightClick() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(greenDiv, coords); - mouse.pressButton(bot.Mouse.Button.RIGHT); - mouse.move(redDiv, coords); - mouse.releaseButton(); + function testRightClick() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(greenDiv, coords); + mouse.pressButton(bot.Mouse.Button.RIGHT); + mouse.move(redDiv, coords); + mouse.releaseButton(); - // In https://chromium.googlesource.com/chromium/src/+/bafc23e1920cc799c03159c39e29878e26071db0 - // Chrome adopted the same values as IE and FF. - var expectUninitializedButtons = + // In https://chromium.googlesource.com/chromium/src/+/bafc23e1920cc799c03159c39e29878e26071db0 + // Chrome adopted the same values as IE and FF. + var expectUninitializedButtons = goog.userAgent.product.CHROME && goog.userAgent.product.isVersion(60); - var wkButtonData; - if (expectUninitializedButtons) { - wkButtonData = 0; - } else { - wkButtonData = 2; + var wkButtonData; + if (expectUninitializedButtons) { + wkButtonData = 0; + } else { + wkButtonData = 2; + } + + // Right click triggers contextmenu even when released over another element. + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + mousedownEvents(greenDiv, 2), + mouseoutEvents(greenDiv, b({ ie: 2, wk: wkButtonData, ff: 0 })), + mouseoverAndMoveEvents(redDiv, b({ ie: 2, wk: wkButtonData, ff: 0 })), + mouseupEvents(redDiv, 2), + goog.events.EventType.CONTEXTMENU, redDiv, b({ ie: 0, wk: 2, ff: 2 }) + ); } - // Right click triggers contextmenu even when released over another element. - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - mousedownEvents(greenDiv, 2), - mouseoutEvents(greenDiv, b({ie: 2, wk: wkButtonData, ff: 0})), - mouseoverAndMoveEvents(redDiv, b({ie: 2, wk: wkButtonData, ff: 0})), - mouseupEvents(redDiv, 2), - goog.events.EventType.CONTEXTMENU, redDiv, b({ie: 0, wk: 2, ff: 2}) - ); - } + function testDoubleClick() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(redDiv, coords); + mouse.pressButton(bot.Mouse.Button.LEFT); + mouse.releaseButton(); + mouse.pressButton(bot.Mouse.Button.LEFT); + mouse.releaseButton(); - function testDoubleClick() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(redDiv, coords); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.releaseButton(); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.releaseButton(); + assertEvents( + mouseoverAndMoveEvents(redDiv, 0), + mousedownEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + mouseupEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + goog.events.EventType.CLICK, redDiv, 0, + mousedownEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + mouseupEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + goog.events.EventType.CLICK, redDiv, 0, + goog.events.EventType.DBLCLICK, redDiv, 0 + ); + } - assertEvents( - mouseoverAndMoveEvents(redDiv, 0), - mousedownEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - mouseupEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - goog.events.EventType.CLICK, redDiv, 0, - mousedownEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - mouseupEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - goog.events.EventType.CLICK, redDiv, 0, - goog.events.EventType.DBLCLICK, redDiv, 0 - ); - } + function testNoDoubleClickWhenTheMouseMovesBetweenClicks() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(greenDiv, coords); + mouse.pressButton(bot.Mouse.Button.LEFT); + mouse.releaseButton(); + mouse.move(redDiv, coords); + mouse.pressButton(bot.Mouse.Button.LEFT); + mouse.releaseButton(); - function testNoDoubleClickWhenTheMouseMovesBetweenClicks() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(greenDiv, coords); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.releaseButton(); - mouse.move(redDiv, coords); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.releaseButton(); + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + mousedownEvents(greenDiv, b({ ie: 1, wk: 0, ff: 0 })), + mouseupEvents(greenDiv, b({ ie: 1, wk: 0, ff: 0 })), + goog.events.EventType.CLICK, greenDiv, 0, + mouseoutEvents(greenDiv, 0), + mouseoverAndMoveEvents(redDiv, 0), + mousedownEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + mouseupEvents(redDiv, b({ ie: 1, wk: 0, ff: 0 })), + goog.events.EventType.CLICK, redDiv, 0 + ); + } - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - mousedownEvents(greenDiv, b({ie: 1, wk: 0, ff: 0})), - mouseupEvents(greenDiv, b({ie: 1, wk: 0, ff: 0})), - goog.events.EventType.CLICK, greenDiv, 0, - mouseoutEvents(greenDiv, 0), - mouseoverAndMoveEvents(redDiv, 0), - mousedownEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - mouseupEvents(redDiv, b({ie: 1, wk: 0, ff: 0})), - goog.events.EventType.CLICK, redDiv, 0 - ); - } + function testMoveOnSameElement() { + var coords1 = new goog.math.Coordinate(5, 5); + var coords2 = new goog.math.Coordinate(10, 5); + var mouse = new bot.Mouse(); + mouse.move(greenDiv, coords1); + mouse.move(greenDiv, coords2); - function testMoveOnSameElement() { - var coords1 = new goog.math.Coordinate(5, 5); - var coords2 = new goog.math.Coordinate(10, 5); - var mouse = new bot.Mouse(); - mouse.move(greenDiv, coords1); - mouse.move(greenDiv, coords2); + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + mousemoveEvents(greenDiv, 0) + ); + } - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - mousemoveEvents(greenDiv, 0) - ); - } + function testMoveToAnotherElement() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(greenDiv, coords); + mouse.move(redDiv, coords); - function testMoveToAnotherElement() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(greenDiv, coords); - mouse.move(redDiv, coords); + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + mouseoutEvents(greenDiv, 0), + mouseoverAndMoveEvents(redDiv, 0) + ); + } - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - mouseoutEvents(greenDiv, 0), - mouseoverAndMoveEvents(redDiv, 0) - ); - } + function testFirstMoveHasNullRelated() { + var mouse = new bot.Mouse(); - function testFirstMoveHasNullRelated() { - var mouse = new bot.Mouse(); + var fired = 0; - var fired = 0; - - goog.events.listenOnce(greenDiv, goog.events.EventType.MOUSEOVER, - function(e) { + goog.events.listenOnce(greenDiv, goog.events.EventType.MOUSEOVER, + function (e) { fired++; // Even though bot.events.fire explicitly sets relatedTarget to null, // it sometimes becomes undefined in Firefox. assertEvaluatesToFalse(e.relatedTarget); }); - mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); + mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); - assertEquals(1, fired); - } + assertEquals(1, fired); + } - function testSecondMoveHasRelatedSet() { - var mouse = new bot.Mouse(); - mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); + function testSecondMoveHasRelatedSet() { + var mouse = new bot.Mouse(); + mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); - var fired = 0; - var relatedTarget; - goog.events.listen(redDiv, goog.events.EventType.MOUSEOVER, - function(e) { + var fired = 0; + var relatedTarget; + goog.events.listen(redDiv, goog.events.EventType.MOUSEOVER, + function (e) { fired++; // Catch the relatedTarget here, but check it below so any errors are // handled correctly in IE. relatedTarget = e.relatedTarget; }); - mouse.move(redDiv, new goog.math.Coordinate(5, 5)); - assertEquals('mouseover event not fired', 1, fired); - assertNotNull(relatedTarget); - assertNotEquals(redDiv, relatedTarget); - } + mouse.move(redDiv, new goog.math.Coordinate(5, 5)); + assertEquals('mouseover event not fired', 1, fired); + assertNotNull(relatedTarget); + assertNotEquals(redDiv, relatedTarget); + } - function testMoveMouseFromClosedWindowDoesNotError() { - var mouse = new bot.Mouse(); - var coord = new goog.math.Coordinate(0, 0); - var iframe = document.createElement('iframe'); + function testMoveMouseFromClosedWindowDoesNotError() { + var mouse = new bot.Mouse(); + var coord = new goog.math.Coordinate(0, 0); + var iframe = document.createElement('iframe'); - return new goog.Promise(function(loaded) { - goog.events.listenOnce(iframe, 'load', loaded); - iframe.src = 'testdata/blank_page.html'; - document.body.appendChild(iframe); - }).then(function() { - mouse.move(iframe.contentWindow.document.body, coord); - return new goog.Promise(function(loaded) { + return new goog.Promise(function (loaded) { goog.events.listenOnce(iframe, 'load', loaded); - iframe.src = 'testdata/iframe_page.html'; + iframe.src = 'testdata/blank_page.html'; + document.body.appendChild(iframe); + }).then(function () { + mouse.move(iframe.contentWindow.document.body, coord); + return new goog.Promise(function (loaded) { + goog.events.listenOnce(iframe, 'load', loaded); + iframe.src = 'testdata/iframe_page.html'; + }); + }).then(function () { + mouse.move(iframe.contentWindow.document.body, coord); + document.body.removeChild(iframe); }); - }).then(function() { - mouse.move(iframe.contentWindow.document.body, coord); - document.body.removeChild(iframe); - }); - } + } - function testMoveMouseFiresAllEventsOnElementHiddenMidSequence() { - var coords = new goog.math.Coordinate(5, 5); - var mouse = new bot.Mouse(); - mouse.move(greenDiv, coords); - goog.events.listen(greenDiv, 'mouseout', function() { - goog.style.showElement(redDiv, false); - }); - mouse.move(redDiv, coords); - goog.style.showElement(redDiv, true); + function testMoveMouseFiresAllEventsOnElementHiddenMidSequence() { + var coords = new goog.math.Coordinate(5, 5); + var mouse = new bot.Mouse(); + mouse.move(greenDiv, coords); + goog.events.listen(greenDiv, 'mouseout', function () { + goog.style.showElement(redDiv, false); + }); + mouse.move(redDiv, coords); + goog.style.showElement(redDiv, true); - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - mouseoutEvents(greenDiv, 0), - mouseoverAndMoveEvents(redDiv, 0) - ); - } - - function testScrollMouseZeroTicksThrowsError() { - var mouse = new bot.Mouse(); - mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); - assertThrows(function() { - mouse.scroll(0); - }); - } - - function testScrollMouseDown() { - var mouse = new bot.Mouse(); - mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); - mouse.scroll(1); - - if (goog.userAgent.GECKO) { assertEvents( mouseoverAndMoveEvents(greenDiv, 0), - goog.events.EventType.MOUSEWHEEL, greenDiv, 0, - goog.events.EventType.MOUSEPIXELSCROLL, greenDiv, 0 - ); - } else { - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - goog.events.EventType.MOUSEWHEEL, greenDiv, 0 + mouseoutEvents(greenDiv, 0), + mouseoverAndMoveEvents(redDiv, 0) ); } - } - function testScrollMouseUp() { - var mouse = new bot.Mouse(); - mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); - mouse.scroll(-2); - - if (goog.userAgent.GECKO) { - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - goog.events.EventType.MOUSEWHEEL, greenDiv, 0, - goog.events.EventType.MOUSEPIXELSCROLL, greenDiv, 0, - goog.events.EventType.MOUSEWHEEL, greenDiv, 0, - goog.events.EventType.MOUSEPIXELSCROLL, greenDiv, 0 - ); - } else { - assertEvents( - mouseoverAndMoveEvents(greenDiv, 0), - goog.events.EventType.MOUSEWHEEL, greenDiv, 0, - goog.events.EventType.MOUSEWHEEL, greenDiv, 0 - ); + function testScrollMouseZeroTicksThrowsError() { + var mouse = new bot.Mouse(); + mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); + assertThrows(function () { + mouse.scroll(0); + }); } - } - function testMsSetPointerCapture() { - if (!bot.userAgent.IE_DOC_10) { - return; + function testScrollMouseDown() { + var mouse = new bot.Mouse(); + mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); + mouse.scroll(1); + + if (goog.userAgent.GECKO) { + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + goog.events.EventType.MOUSEWHEEL, greenDiv, 0, + goog.events.EventType.MOUSEPIXELSCROLL, greenDiv, 0 + ); + } else { + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + goog.events.EventType.MOUSEWHEEL, greenDiv, 0 + ); + } } - var coords = new goog.math.Coordinate(75, 5); - var mouse = new bot.Mouse(); - mouse.move(captureDiv, coords); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.move(greenDiv, coords); - mouse.releaseButton(); - // The captureDiv will call msSetPointerCapture on MSPointerDown and as a - // result, subsequent events should be fired on captureDiv instead of - // greenDiv. - assertEvents( - mouseoverAndMoveEvents(captureDiv, 0), - mousedownEvents(captureDiv, 0), - mouseoutEvents(captureDiv, 0), - mouseoverAndMoveEvents(captureDiv, 0), - mouseupEvents(captureDiv, 0) - ); - } + function testScrollMouseUp() { + var mouse = new bot.Mouse(); + mouse.move(greenDiv, new goog.math.Coordinate(5, 5)); + mouse.scroll(-2); - function testClickDoesNotFireOnCapturedPointer() { - if (!bot.userAgent.IE_DOC_10) { - return; + if (goog.userAgent.GECKO) { + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + goog.events.EventType.MOUSEWHEEL, greenDiv, 0, + goog.events.EventType.MOUSEPIXELSCROLL, greenDiv, 0, + goog.events.EventType.MOUSEWHEEL, greenDiv, 0, + goog.events.EventType.MOUSEPIXELSCROLL, greenDiv, 0 + ); + } else { + assertEvents( + mouseoverAndMoveEvents(greenDiv, 0), + goog.events.EventType.MOUSEWHEEL, greenDiv, 0, + goog.events.EventType.MOUSEWHEEL, greenDiv, 0 + ); + } } - var mouse = new bot.Mouse(); - mouse.move(innerCaptureDiv, new goog.math.Coordinate(5, 5)); - mouse.pressButton(bot.Mouse.Button.LEFT); - mouse.move(innerCaptureDiv, new goog.math.Coordinate(6, 6)); - mouse.releaseButton(); - - // The MSPointerDown event on innerCaptureDiv bubbles up to the - // captureDiv element which calls msSetPointerCapture, so subsequent - // events should fire on captureTarget except for the click event. - assertEvents( - mouseoverAndMoveEvents(innerCaptureDiv, 0), - mousedownEvents(innerCaptureDiv, 0), - mousemoveEvents(captureDiv, 0), - mouseupEvents(captureDiv, 0), - goog.events.EventType.CLICK, innerCaptureDiv, 0 - ); - } -</script> + </script> </body> + </html>
diff --git a/javascript/atoms/test/scrolling_test.html b/javascript/atoms/test/scrolling_test.html index 91a3c78..3c51fbe 100644 --- a/javascript/atoms/test/scrolling_test.html +++ b/javascript/atoms/test/scrolling_test.html
@@ -118,9 +118,6 @@ var topContainer = findElement({id: 'scrollable-but-unscrolled-top-container'}); - expectedFailures.expectFailureFor( - goog.userAgent.IE, - 'IE scrollIntoView scrolls quite eagerly.'); expectedFailures.run(function() { assertNotEquals(0, topContainer.scrollLeft); assertEquals(0, middleContainer.scrollLeft); @@ -224,7 +221,6 @@ // there are no scroll bars that get displayed. expectedFailures.expectFailureFor( goog.labs.userAgent.device.isMobile() || goog.labs.userAgent.device.isTablet() || - (goog.userAgent.IE && !goog.userAgent.isVersion(7)) || (goog.userAgent.product.CHROME && goog.userAgent.MAC)); expectedFailures.run(function() {
diff --git a/javascript/atoms/test/text_box_test.html b/javascript/atoms/test/text_box_test.html index 24a35f0..67c7184 100644 --- a/javascript/atoms/test/text_box_test.html +++ b/javascript/atoms/test/text_box_test.html
@@ -16,29 +16,42 @@ limitations under the License. --> <html> + <head> <title>bot.dom.getVisibleText Box Model Test</title> <script src="test_bootstrap.js"></script> <script src="text_util.js"></script> - <style><!-- -div.example { width: 25em; } + <style> + <!-- + div.example { + width: 25em; + } -div.example div.red { - margin: 0 0.5em 0.5em 0.5em; - padding: 0.5em; -} + div.example div.red { + margin: 0 0.5em 0.5em 0.5em; + padding: 0.5em; + } -div.example div.header { - margin: 0 0.5em; - padding: 0; - font-style: italic; - color: gray; -} + div.example div.header { + margin: 0 0.5em; + padding: 0; + font-style: italic; + color: gray; + } -.red { border: 1px solid #c00; } -.green { border: 1px solid #0c0;} -.blue { border: 1px solid #00c;} ---></style> + .red { + border: 1px solid #c00; + } + + .green { + border: 1px solid #0c0; + } + + .blue { + border: 1px solid #00c; + } + --> + </style> <script type="text/javascript"> goog.require('bot.dom'); goog.require('bot.userAgent'); @@ -48,225 +61,227 @@ goog.require('goog.userAgent'); goog.require('goog.userAgent.product'); </script> - </head> - <body> +</head> + +<body> <div>This test page is based on the information and examples available at <a href="http://www.quirksmode.org/css/display.html"> - http://www.quirksmode.org/css/display.html</a></div> + http://www.quirksmode.org/css/display.html</a> + </div> <!-- All dynamically generated DOM structures should be added here. --> <script type="text/javascript"> -/** - * Configures and runs visible text tests against elements with various - * display styles. - * @param {string} display The display type (e.g. "inline", "block", etc.). - * @constructor - */ -var DisplayBoxTester = function(display) { - // Find where to insert our test DOM tree into the body. If a section - // has not been generated yet for this display type, add it now. - var parent = goog.dom.$(display); - if (!parent) { - var container = getTestContainer(); - goog.dom.appendChild(container, - goog.dom.createDom('h4', null, 'display: ' + display)); - parent = goog.dom.createDom('div', {id: display}); - goog.dom.appendChild(container, parent); - } + /** + * Configures and runs visible text tests against elements with various + * display styles. + * @param {string} display The display type (e.g. "inline", "block", etc.). + * @constructor + */ + var DisplayBoxTester = function (display) { + // Find where to insert our test DOM tree into the body. If a section + // has not been generated yet for this display type, add it now. + var parent = goog.dom.$(display); + if (!parent) { + var container = getTestContainer(); + goog.dom.appendChild(container, + goog.dom.createDom('h4', null, 'display: ' + display)); + parent = goog.dom.createDom('div', { id: display }); + goog.dom.appendChild(container, parent); + } - var ex = goog.dom.createDom('div', {className:'example'}, - goog.dom.createDom('div', {className:'header'}, + var ex = goog.dom.createDom('div', { className: 'example' }, + goog.dom.createDom('div', { className: 'header' }, goog.testing.TestCase.currentTestName), - goog.dom.createDom('div', {className:'red'})); + goog.dom.createDom('div', { className: 'red' })); - parent.appendChild(ex); + parent.appendChild(ex); - /** - * The root of our test DOM tree upon which all new nodes - * will be inserted and assertions performed. - * @type {!Element} - */ - this.dom = ex.firstChild.nextSibling; + /** + * The root of our test DOM tree upon which all new nodes + * will be inserted and assertions performed. + * @type {!Element} + */ + this.dom = ex.firstChild.nextSibling; - /** - * The display type for this tester (e.g. "block", "inline", etc.). - * @type {string} - */ - this.display = display; -}; + /** + * The display type for this tester (e.g. "block", "inline", etc.). + * @type {string} + */ + this.display = display; + }; -/** - * Adds a new text node to the test DOM tree. - * @param {string} text The text node content. - * @return {!DisplayBoxTester} A self reference. - */ -DisplayBoxTester.prototype.addTextNode = function(text) { - this.dom.appendChild(goog.dom.createTextNode(text)); - return this; -}; + /** + * Adds a new text node to the test DOM tree. + * @param {string} text The text node content. + * @return {!DisplayBoxTester} A self reference. + */ + DisplayBoxTester.prototype.addTextNode = function (text) { + this.dom.appendChild(goog.dom.createTextNode(text)); + return this; + }; -/** - * Adds a new element to the test DOM with this tester's display type. - * @param {!goog.dom.TagName} tagName The element tag name. - * @param {string} color The element border color (for debugging). - * @param {string} text The element's text content. - * @return {!DisplayBoxTester} A self reference. - */ -DisplayBoxTester.prototype.addTestNode = function(tagName, color, text) { - this.dom.appendChild(goog.dom.createDom(tagName, { - className: color, - style: 'display: ' + this.display - }, text)); - return this; -}; + /** + * Adds a new element to the test DOM with this tester's display type. + * @param {!goog.dom.TagName} tagName The element tag name. + * @param {string} color The element border color (for debugging). + * @param {string} text The element's text content. + * @return {!DisplayBoxTester} A self reference. + */ + DisplayBoxTester.prototype.addTestNode = function (tagName, color, text) { + this.dom.appendChild(goog.dom.createDom(tagName, { + className: color, + style: 'display: ' + this.display + }, text)); + return this; + }; -/** - * Appends a new node to the test DOM. - * @param {string} tagName Tag to create. - * @param {Object|Array.<string>|string=} opt_attributes If object, then a map - * of name-value pairs for attributes. If a string, then this is the - * className of the new element. If an array, the elements will be joined - * together as the className of the new element. - * @param {...Object|string|Array|NodeList} var_args Further DOM nodes or - * strings for text nodes. If one of the var_args is an array or NodeList,i - * its elements will be added as childNodes instead. - * @return {!DisplayBoxTester} A self reference. - */ -DisplayBoxTester.prototype.addNode = function(tagName, opt_attributes, var_args) { - this.dom.appendChild(goog.dom.createDom.apply(null, arguments)); - return this; -}; + /** + * Appends a new node to the test DOM. + * @param {string} tagName Tag to create. + * @param {Object|Array.<string>|string=} opt_attributes If object, then a map + * of name-value pairs for attributes. If a string, then this is the + * className of the new element. If an array, the elements will be joined + * together as the className of the new element. + * @param {...Object|string|Array|NodeList} var_args Further DOM nodes or + * strings for text nodes. If one of the var_args is an array or NodeList,i + * its elements will be added as childNodes instead. + * @return {!DisplayBoxTester} A self reference. + */ + DisplayBoxTester.prototype.addNode = function (tagName, opt_attributes, var_args) { + this.dom.appendChild(goog.dom.createDom.apply(null, arguments)); + return this; + }; -/** - * Verifies that the visible text for the test DOM structure. - * @param {...string} var_args Variadic args for the expected lines - * of visible text. - */ -DisplayBoxTester.prototype.assertTextIs = function(var_args) { - var args = goog.array.slice(arguments, 0); - args.unshift(this.dom); - assertTextIs.apply(null, args); -}; + /** + * Verifies that the visible text for the test DOM structure. + * @param {...string} var_args Variadic args for the expected lines + * of visible text. + */ + DisplayBoxTester.prototype.assertTextIs = function (var_args) { + var args = goog.array.slice(arguments, 0); + args.unshift(this.dom); + assertTextIs.apply(null, args); + }; -function testBlock() { - new DisplayBoxTester('block'). - addTextNode('pre'). - addTestNode(goog.dom.TagName.DIV, 'green', 'div.block'). - addTextNode('mid'). - addTestNode(goog.dom.TagName.SPAN, 'blue', 'span.block'). - addTextNode('post'). - assertTextIs('pre', - 'div.block', - 'mid', - 'span.block', - 'post'); -} + function testBlock() { + new DisplayBoxTester('block'). + addTextNode('pre'). + addTestNode(goog.dom.TagName.DIV, 'green', 'div.block'). + addTextNode('mid'). + addTestNode(goog.dom.TagName.SPAN, 'blue', 'span.block'). + addTextNode('post'). + assertTextIs('pre', + 'div.block', + 'mid', + 'span.block', + 'post'); + } -function testInline() { - new DisplayBoxTester('inline'). - addTextNode('pre-'). - addTestNode(goog.dom.TagName.DIV, 'green', 'div.inline'). - addTextNode('-mid-'). - addNode(goog.dom.TagName.SPAN, 'blue', 'span.inline'). - addTextNode('-post'). - assertTextIs('pre-div.inline-mid-span.inline-post'); -} + function testInline() { + new DisplayBoxTester('inline'). + addTextNode('pre-'). + addTestNode(goog.dom.TagName.DIV, 'green', 'div.inline'). + addTextNode('-mid-'). + addNode(goog.dom.TagName.SPAN, 'blue', 'span.inline'). + addTextNode('-post'). + assertTextIs('pre-div.inline-mid-span.inline-post'); + } -function testInlineBetweenTwoBlocks() { - new DisplayBoxTester('inline'). - addTextNode('display:block '). - addTestNode(goog.dom.TagName.DIV, 'green', 'display:inline'). - addNode(goog.dom.TagName.DIV, { - className: 'blue', - style: 'display: block' - }, 'display:block'). - addTestNode(goog.dom.TagName.DIV, 'green', 'display:inline'). - assertTextIs('display:block display:inline', - 'display:block', - 'display:inline'); -} + function testInlineBetweenTwoBlocks() { + new DisplayBoxTester('inline'). + addTextNode('display:block '). + addTestNode(goog.dom.TagName.DIV, 'green', 'display:inline'). + addNode(goog.dom.TagName.DIV, { + className: 'blue', + style: 'display: block' + }, 'display:block'). + addTestNode(goog.dom.TagName.DIV, 'green', 'display:inline'). + assertTextIs('display:block display:inline', + 'display:block', + 'display:inline'); + } -function testNone() { - new DisplayBoxTester('none'). - addTextNode('pre-'). - addTestNode(goog.dom.TagName.DIV, 'green', 'div.none'). - addTextNode('-mid-'). - addTestNode(goog.dom.TagName.SPAN, 'blue', 'span.none'). - addTextNode('-post'). - assertTextIs('pre--mid--post'); -} + function testNone() { + new DisplayBoxTester('none'). + addTextNode('pre-'). + addTestNode(goog.dom.TagName.DIV, 'green', 'div.none'). + addTextNode('-mid-'). + addTestNode(goog.dom.TagName.SPAN, 'blue', 'span.none'). + addTextNode('-post'). + assertTextIs('pre--mid--post'); + } -function testInlineBlock() { - new DisplayBoxTester('inline-block'). - addTextNode('pre-'). - addTestNode(goog.dom.TagName.DIV, 'green', 'a'). - addTextNode('-mid-'). - addTestNode(goog.dom.TagName.SPAN, 'blue', 'b'). - addTextNode('-post'). - assertTextIs('pre-a-mid-b-post'); -} + function testInlineBlock() { + new DisplayBoxTester('inline-block'). + addTextNode('pre-'). + addTestNode(goog.dom.TagName.DIV, 'green', 'a'). + addTextNode('-mid-'). + addTestNode(goog.dom.TagName.SPAN, 'blue', 'b'). + addTextNode('-post'). + assertTextIs('pre-a-mid-b-post'); + } -function testListItem() { - new DisplayBoxTester('list-item'). - addTextNode('pre-'). - addTestNode(goog.dom.TagName.DIV, 'green', 'a'). - addTextNode('-mid-'). - addTestNode(goog.dom.TagName.SPAN, 'blue', 'b'). - addTextNode('-post'). - assertTextIs('pre-', - 'a', - '-mid-', - 'b', - '-post'); -} + function testListItem() { + new DisplayBoxTester('list-item'). + addTextNode('pre-'). + addTestNode(goog.dom.TagName.DIV, 'green', 'a'). + addTextNode('-mid-'). + addTestNode(goog.dom.TagName.SPAN, 'blue', 'b'). + addTextNode('-post'). + assertTextIs('pre-', + 'a', + '-mid-', + 'b', + '-post'); + } -function testRunIn_followedByBlock() { - // Currently, only IE supports this use of display:run-in, having supported it - // starting with IE 8. See http://quirksmode.org/css/css2/display.html. The - // Android native browser also supports it. - // - // No other major desktop browsers support this now: - // - Firefox has never supported it. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=2056 - // - Blink removed support, effective with Chrome 32. - // See https://code.google.com/p/chromium/issues/detail?id=260388 - // - Safari appears to have dropped support in Safari 7.1. - // - Edge does not support it. - var supportsRunIn = - (goog.userAgent.IE && bot.userAgent.isProductVersion(8)) || - (goog.userAgent.product.CHROME && !bot.userAgent.isProductVersion(32)) || - (goog.userAgent.product.SAFARI && !bot.userAgent.isProductVersion(7.1)) || - (goog.userAgent.product.ANDROID); + function testRunIn_followedByBlock() { + // Currently, only IE supports this use of display:run-in, having supported it + // starting with IE 8. See http://quirksmode.org/css/css2/display.html. The + // Android native browser also supports it. + // + // No other major desktop browsers support this now: + // - Firefox has never supported it. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=2056 + // - Blink removed support, effective with Chrome 32. + // See https://code.google.com/p/chromium/issues/detail?id=260388 + // - Safari appears to have dropped support in Safari 7.1. + // - Edge does not support it. + var supportsRunIn = + (goog.userAgent.product.CHROME && !bot.userAgent.isProductVersion(32)) || + (goog.userAgent.product.SAFARI && !bot.userAgent.isProductVersion(7.1)) || + (goog.userAgent.product.ANDROID); - var expectedText = supportsRunIn ? 'Hello, world.' : 'Hello\n, world.'; - new DisplayBoxTester('run-in'). - addTestNode(goog.dom.TagName.H3, 'green', 'Hello'). - addNode(goog.dom.TagName.DIV, { - className: 'blue', - style: 'display: block' - }, ', world.'). - assertTextIs(expectedText); -} + var expectedText = supportsRunIn ? 'Hello, world.' : 'Hello\n, world.'; + new DisplayBoxTester('run-in'). + addTestNode(goog.dom.TagName.H3, 'green', 'Hello'). + addNode(goog.dom.TagName.DIV, { + className: 'blue', + style: 'display: block' + }, ', world.'). + assertTextIs(expectedText); + } -function testRunIn_followedByFloat() { - new DisplayBoxTester('run-in'). - addTestNode(goog.dom.TagName.H3, 'green', 'Hello'). - addNode(goog.dom.TagName.DIV, { - className: 'blue', - style: 'float: right; width: 50%; clear: right;' - }, ', world.'). - assertTextIs('Hello\n, world.'); -} + function testRunIn_followedByFloat() { + new DisplayBoxTester('run-in'). + addTestNode(goog.dom.TagName.H3, 'green', 'Hello'). + addNode(goog.dom.TagName.DIV, { + className: 'blue', + style: 'float: right; width: 50%; clear: right;' + }, ', world.'). + assertTextIs('Hello\n, world.'); + } </script> </body> + </html>
diff --git a/javascript/atoms/userAgent.js b/javascript/atoms/userAgent.js index 6551076..7beba88 100644 --- a/javascript/atoms/userAgent.js +++ b/javascript/atoms/userAgent.js
@@ -42,12 +42,7 @@ * than the given version. */ bot.userAgent.isEngineVersion = function (version) { - if (goog.userAgent.IE) { - return goog.string.compareVersions( - /** @type {number} */(goog.userAgent.DOCUMENT_MODE), version) >= 0; - } else { - return goog.userAgent.isVersionOrHigher(version); - } + return goog.userAgent.isVersionOrHigher(version); }; @@ -125,50 +120,6 @@ } })(); - -/** - * Whether the current document is IE in a documentMode older than 8. - * @type {boolean} - * @const - */ -bot.userAgent.IE_DOC_PRE8 = goog.userAgent.IE && - !goog.userAgent.isDocumentModeOrHigher(8); - - -/** - * Whether the current document is IE in IE9 (or newer) standards mode. - * @type {boolean} - * @const - */ -bot.userAgent.IE_DOC_9 = goog.userAgent.isDocumentModeOrHigher(9); - - -/** - * Whether the current document is IE in a documentMode older than 9. - * @type {boolean} - * @const - */ -bot.userAgent.IE_DOC_PRE9 = goog.userAgent.IE && - !goog.userAgent.isDocumentModeOrHigher(9); - - -/** - * Whether the current document is IE in IE10 (or newer) standards mode. - * @type {boolean} - * @const - */ -bot.userAgent.IE_DOC_10 = goog.userAgent.isDocumentModeOrHigher(10); - - -/** - * Whether the current document is IE in a documentMode older than 10. - * @type {boolean} - * @const - */ -bot.userAgent.IE_DOC_PRE10 = goog.userAgent.IE && - !goog.userAgent.isDocumentModeOrHigher(10); - - /** * Whether the current browser is Android pre-gingerbread. * @type {boolean}
diff --git a/javascript/atoms/window.js b/javascript/atoms/window.js index 2e28003..f98c868 100644 --- a/javascript/atoms/window.js +++ b/javascript/atoms/window.js
@@ -42,7 +42,7 @@ * @private {boolean} * @const */ -bot.window.HISTORY_LENGTH_INCLUDES_NEW_PAGE_ = !goog.userAgent.IE; +bot.window.HISTORY_LENGTH_INCLUDES_NEW_PAGE_ = true; /** @@ -307,13 +307,8 @@ var win = opt_win || bot.getWindow(); var x, y; - if (goog.userAgent.IE) { - x = win.screenLeft; - y = win.screenTop; - } else { - x = win.screenX; - y = win.screenY; - } + x = win.screenX; + y = win.screenY; return new goog.math.Coordinate(x, y); };