opal/browser/support.rb
# backtick_javascript: true
# The engine the browser is running on.
#
# Keep in mind it uses the user agent to know, so it's not reliable in case of
# spoofing.
BROWSER_ENGINE = `/MSIE|WebKit|Presto|Gecko/.exec(navigator.userAgent)[0]`.downcase rescue :unknown
module Browser
# @private
@support = `{}`
# Check if the browser supports the given feature.
def self.supports?(feature)
if defined?(`#@support[#{feature}]`)
return `#@support[#{feature}]`
end
support = case feature
when 'MutationObserver'
defined?(`window.MutationObserver`)
when 'WebSocket'
defined?(`window.WebSocket`)
when 'EventSource'
defined?(`window.EventSource`)
when 'XHR'
defined?(`window.XMLHttpRequest`)
when 'ActiveX'
defined?(`window.ActiveXObject`)
when 'WebSQL'
defined?(`window.openDatabase`)
when 'Query.css'
defined?(`document.querySelectorAll`)
when 'Query.xpath'
defined?(`document.evaluate`)
when 'Storage.local'
defined?(`window.localStorage`)
when 'Storage.global'
defined?(`window.globalStorage`)
when 'Storage.session'
defined?(`window.sessionStorage`)
when 'Immediate'
defined?(`window.setImmediate`)
when 'Immediate (Internet Explorer)'
defined?(`window.msSetImmediate`)
when 'Immediate (Firefox)'
defined?(`window.mozSetImmediate`)
when 'Immediate (Opera)'
defined?(`window.oSetImmediate`)
when 'Immediate (Chrome)', 'setImmediate (Safari)'
defined?(`window.webkitSetImmediate`)
when 'CSS.computed'
defined?(`window.getComputedStyle`)
when 'CSS.current'
defined?(`document.documentElement.currentStyle`)
when 'Window.send'
defined?(`window.postMessage`)
when 'Window.send (Asynchronous)'
if defined?(`window.postMessage`) && !defined?(`window.importScripts`)
%x{
var ok = true,
old = window.onmessage;
window.onmessage = function() { ok = false; };
window.postMessage("", "*")
window.onmessage = old;
return ok;
}
end
when 'Window.send (Synchronous)'
!supports?('Window.send (Asynchronous)')
when 'Window.innerSize'
defined?(`window.innerHeight`)
when 'Window.outerSize'
defined?(`window.outerHeight`)
when 'Window.scroll'
defined?(`document.documentElement.scrollLeft`)
when 'Window.scrollBy'
defined?(`document.documentElement.scrollBy`)
when 'Window.pageOffset'
defined?(`window.pageXOffset`)
when 'Attr.isId'
%x{
var div = document.createElement('div');
div.setAttribute('id', 'xxxxxxxxxxxxx');
return typeof(div.attributes['id'].isId) !== "undefined";
}
when 'Element.addBehavior'
defined?(`document.documentElement.addBehavior`)
when 'Element.className'
%x{
var div = document.createElement("div");
div.setAttribute('className', 'x');
return div.className === 'x';
}
when 'Element.class'
%x{
var div = document.createElement("div");
div.setAttribute('class', 'x');
return div.className === 'x';
}
when 'Element.for'
%x{
var label = document.createElement("label");
label.setAttribute('for', 'x');
return label.htmlFor === 'x';
}
when 'Element.htmlFor'
%x{
var label = document.createElement("label");
label.setAttribute('htmlFor', 'x');
return label.htmlFor === 'x';
}
when 'Element.clientSize'
defined?(`document.documentElement.clientHeight`)
when 'Element.scroll'
defined?(`document.documentElement.scrollLeft`)
when 'Element.textContent'
defined?(`document.documentElement.textContent`)
when 'Element.innerText'
defined?(`document.documentElement.innerText`)
when 'Element.matches'
defined?(`document.documentElement.matches`)
when 'Element.matches (Internet Explorer)'
defined?(`document.documentElement.msMatchesSelector`)
when 'Element.matches (Firefox)'
defined?(`document.documentElement.mozMatchesSelector`)
when 'Element.matches (Opera)'
defined?(`document.documentElement.oMatchesSelector`)
when 'Element.matches (Chrome)', 'Element.matches (Safari)'
defined?(`document.documentElement.webkitMatchesSelector`)
when 'Element.getBoundingClientRect'
defined?(`document.documentElement.getBoundingClientRect`)
when 'Event.readystatechange'
`"onreadystatechange" in window.document.createElement("script")`
when 'Event.constructor'
begin
`new MouseEvent("click")`
true
rescue StandardError, JS::Error
false
end
when 'Event.create'
defined?(`document.createEvent`)
when 'Event.createObject'
defined?(`document.createEventObject`)
when 'Event.addListener'
defined?(`document.addEventListener`)
when 'Event.attach'
defined?(`document.attachEvent`)
when 'Event.removeListener'
defined?(`document.removeEventListener`)
when 'Event.detach'
defined?(`document.detachEvent`)
when 'Event.dispatch'
defined?(`document.dispatchEvent`)
when 'Event.fire'
defined?(`document.fireEvent`)
when /^Event\.([A-Z].*?)$/
`(#{$1} + "Event") in window`
when 'Document.view'
defined?(`document.defaultView`)
when 'Document.window'
defined?(`document.parentWindow`)
when 'History'
defined?(`window.history.pushState`)
when 'History.state'
defined?(`window.history.state`)
when 'Animation.request'
defined?(`window.requestAnimationFrame`)
when 'Animation.request (Internet Explorer)'
defined?(`window.msRequestAnimationFrame`)
when 'Animation.request (Firefox)'
defined?(`window.mozRequestAnimationFrame`)
when 'Animation.request (Opera)'
defined?(`window.oRequestAnimationFrame`)
when 'Animation.request (Chrome)', 'Animation.request (Safari)'
defined?(`window.webkitRequestAnimationFrame`)
when 'Animation.cancel'
defined?(`window.cancelAnimationFrame`)
when 'Animation.cancel (Internet Explorer)'
defined?(`window.msCancelAnimationFrame`)
when 'Animation.cancel (Firefox)'
defined?(`window.mozCancelAnimationFrame`)
when 'Animation.cancel (Opera)'
defined?(`window.oCancelAnimationFrame`)
when 'Animation.cancel (Chrome)', 'Animation.cancel (Safari)'
defined?(`window.webkitCancelAnimationFrame`)
when 'Animation.cancelRequest'
defined?(`window.cancelRequestAnimationFrame`)
when 'Animation.cancelRequest (Internet Explorer)'
defined?(`window.msCancelRequestAnimationFrame`)
when 'Animation.cancelRequest (Firefox)'
defined?(`window.mozCancelRequestAnimationFrame`)
when 'Animation.cancelRequest (Opera)'
defined?(`window.oCancelRequestAnimationFrame`)
when 'Animation.cancelRequest (Chrome)', 'Animation.cancelRequest (Safari)'
defined?(`window.webkitCancelRequestAnimationFrame`)
when 'Audio'
defined?(`window.AudioContext`)
when 'Audio (Safari)', 'Audio (Chrome)'
defined?(`window.webkitAudioContext`)
when 'Custom Elements'
defined?(`window.customElements`)
end
`#@support[#{feature}] = #{support}`
end
# Check if the given polyfill is loaded.
def self.loaded?(name)
case name
when 'Sizzle'
defined?(`window.Sizzle`)
when 'wicked-good-xpath'
defined?(`window.wgxpath`)
end
end
end