    /*

    Siesta 5.3.0
    Copyright(c) 2009-2019 Bryntum AB
    https://bryntum.com/contact
    https://bryntum.com/products/siesta/license

    */
    // requires "global" attribute
    Role('Siesta.Test.Browser.Role.CanWorkWithKeyboard', {

        has : {
        },

        methods : {

            isTextInput : function(node) {
                // somehow "node.nodeName" is empty sometimes in IE10
                var name    = node.nodeName && node.nodeName.toLowerCase();

                if (name === 'textarea') return true;

                if (name === 'input') {
                    var type    = String(node.type).toLowerCase()

                    return type === 'password' ||
                        type === 'number' ||
                        type === 'search' ||
                        type === 'text' ||
                        type === 'url' ||
                        type === 'tel' ||
                        type === 'month' ||
                        type === 'time' ||
                        type === 'date' ||
                        type === 'datetime' ||
                        type === 'week' ||
                        type === 'email';
                }

                return false
            },

            isEditableNode : function(node) {
                return node.ownerDocument.designMode.toLowerCase() === 'on' || node.isContentEditable;
            },

            // private
            isReadableKey: function (keyCode) {
                var KC = Siesta.Test.UserAgent.KeyCodes();

                return !KC.isNav(keyCode) && !KC.isSpecial(keyCode);
            },

            activeElement : function (notAllowBody, fallbackEl, elOrDoc) {
                var doc         = elOrDoc ? elOrDoc.ownerDocument || elOrDoc : this.global.document

                var focusedEl   = doc.activeElement;

                // 1. In IE10,11 it seems activeElement cannot be trusted as it sometimes returns an empty object with no properties.
                // Try to detect this case and use the fallback el
                // 2. Sometimes receiving <body> from this method does not make sense either - use fallback el as well
                if (!focusedEl || !focusedEl.nodeName || !focusedEl.tagName || (focusedEl === doc.body && notAllowBody)) {
                    focusedEl   = fallbackEl;
                }

                // For iframes, we need to grab the activeElement of the frame (if in the same domain)
                if (focusedEl && String(focusedEl.tagName).toLowerCase() == 'iframe') {
                    try {
                        if (focusedEl.contentDocument && focusedEl.contentDocument.body) {
                            focusedEl = this.activeElement(notAllowBody, fallbackEl, focusedEl.contentDocument)
                        }
                    }
                    catch(e) {}
                }

                return focusedEl || doc.body
            }
        }
    });