Path: blob/trunk/javascript/atoms/locators/classname.js
2884 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617goog.provide('bot.locators.className');1819goog.require('bot.Error');20goog.require('bot.ErrorCode');21goog.require('goog.dom');22goog.require('goog.string');232425/**26* Tests whether the standardized W3C Selectors API are available on an27* element.28* @param {!(Document|Element)} root The document or element to test for CSS29* selector support.30* @return {boolean} Whether or not the root supports query selector APIs.31* @see http://www.w3.org/TR/selectors-api/32* @private33*/34bot.locators.className.canUseQuerySelector_ = function (root) {35return !!(root.querySelectorAll && root.querySelector);36};373839/**40* Find an element by its class name.41* @param {string} target The class name to search for.42* @param {!(Document|Element)} root The document or element to perform the43* search under.44* @return {Element} The first matching element found in the DOM, or null if no45* such element could be found.46*/47bot.locators.className.single = function (target, root) {48if (!target) {49throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR,50'No class name specified');51}5253target = goog.string.trim(target);54if (target.indexOf(' ') !== -1) {55throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR,56'Compound class names not permitted');57}5859// Closure will not properly escape class names that contain a '.' when using60// the native selectors API, so we have to handle this ourselves.61if (bot.locators.className.canUseQuerySelector_(root)) {62try {63return root.querySelector('.' + target.replace(/\./g, '\\.')) || null;64} catch (e) {65throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR,66'An invalid or illegal class name was specified');67}68}69var elements = goog.dom.getDomHelper(root).getElementsByTagNameAndClass(70/*tagName=*/'*', /*className=*/target, root);71return elements.length ? elements[0] : null;72};737475/**76* Find an element by its class name.77* @param {string} target The class name to search for.78* @param {!(Document|Element)} root The document or element to perform the79* search under.80* @return {!IArrayLike} All matching elements, or an empty list.81*/82bot.locators.className.many = function (target, root) {83if (!target) {84throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR,85'No class name specified');86}8788target = goog.string.trim(target);89if (target.indexOf(' ') !== -1) {90throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR,91'Compound class names not permitted');92}9394// Closure will not properly escape class names that contain a '.' when using95// the native selectors API, so we have to handle this ourselves.96if (bot.locators.className.canUseQuerySelector_(root)) {97try {98return root.querySelectorAll('.' + target.replace(/\./g, '\\.'));99} catch (e) {100throw new bot.Error(bot.ErrorCode.INVALID_SELECTOR_ERROR,101'An invalid or illegal class name was specified');102}103}104return goog.dom.getDomHelper(root).getElementsByTagNameAndClass(105/*tagName=*/'*', /*className=*/target, root);106};107108109