(function(){ var BOOLEAN_PROPERTIES = [ "allowfullscreen", "allowpaymentrequest", "allowusermedia", "async", "autofocus", "autoplay", "checked", "compact", "complete", "controls", "declare", "default", "defaultchecked", "defaultselected", "defer", "disabled", "ended", "formnovalidate", "hidden", "indeterminate", "iscontenteditable", "ismap", "itemscope", "loop", "multiple", "muted", "nohref", "nomodule", "noresize", "noshade", "novalidate", "nowrap", "open", "paused", "playsinline", "pubdate", "readonly", "required", "reversed", "scoped", "seamless", "seeking", "selected", "truespeed", "typemustmatch", "willvalidate" ]; var PROPERTY_ALIASES = { "class": "className", "readonly": "readOnly" }; function isSelectable(element){ var tagName = element.tagName.toUpperCase(); if (tagName == "OPTION"){ return true; } if (tagName == "INPUT") { var type = element.type.toLowerCase(); return type == "checkbox" || type == "radio"; } return false; } function isSelected(element){ var propertyName = "selected"; var type = element.type && element.type.toLowerCase(); if ("checkbox" == type || "radio" == type) { propertyName = "checked"; } return !!element[propertyName]; } function getAttributeValue(element, name){ var attr = element.getAttributeNode(name); return (attr && attr.specified) ? attr.value : null; } return function get(element, attribute){ var value = null; var name = attribute.toLowerCase(); if ("style" == name) { value = element.style; if (value && (typeof value != "string")) { value = value.cssText; } return value; } if (("selected" == name || "checked" == name) && isSelectable(element)) { return isSelected(element) ? "true" : null; } tagName = element.tagName.toUpperCase(); // The property is consistent. Return that in preference to the attribute for links and images. if (((tagName == "IMG") && name == "src") || ((tagName == "A") && name == "href")) { value = getAttributeValue(element, name); if (value) { // We want the full URL if present value = element[name]; } return value; } if ("spellcheck" == name) { value = getAttributeValue(element, name); if (!(value === null)) { if (value.toLowerCase() == "false") { return "false"; } else if (value.toLowerCase() == "true") { return "true"; } } // coerce the property value to a string return element[name] + ""; } var propName = PROPERTY_ALIASES[attribute] || attribute; if (BOOLEAN_PROPERTIES.some(function(prop){ prop == name })) { value = getAttributeValue(element, name); value = !(value === null) || element[propName]; return value ? "true" : null; } var property; try { property = element[propName] } catch (e) { // Leaves property undefined or null } // 1- Call getAttribute if getProperty fails, // i.e. property is null or undefined. // This happens for event handlers in Firefox. // For example, calling getProperty for 'onclick' would // fail while getAttribute for 'onclick' will succeed and // return the JS code of the handler. // // 2- When property is an object we fall back to the // actual attribute instead. // See issue http://code.google.com/p/selenium/issues/detail?id=966 if ((property == null) || (typeof property == "object") || (typeof property == "function")) { value = getAttributeValue(element, attribute); } else { value = property; }; // The empty string is a valid return value. return value != null ? value.toString() : null; }; })()