Merge pull request #12189 from hashicorp/ds.ie11-warning
website: display warning in IE 11
This commit is contained in:
commit
99399c6bf3
|
@ -19,7 +19,7 @@ export default class MyDocument extends Document {
|
||||||
<script
|
<script
|
||||||
noModule
|
noModule
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: `window.MSInputMethodContext && document.documentMode && document.write('<script src="/ie-custom-properties.js"><\\x2fscript>');`,
|
__html: `window.MSInputMethodContext && document.documentMode && document.write('<script src="/ie-warning.js"><\\x2fscript>');`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,639 +0,0 @@
|
||||||
/*! ie11CustomProperties.js v2.7.2 | MIT License | https://git.io/fjXMN */
|
|
||||||
// c1.onElement helper
|
|
||||||
!(function () {
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
if (!Element.prototype.matches)
|
|
||||||
Element.prototype.matches = Element.prototype.msMatchesSelector
|
|
||||||
|
|
||||||
var w = window
|
|
||||||
if (!w.c1) w.c1 = {}
|
|
||||||
var listeners = [],
|
|
||||||
root = document,
|
|
||||||
Observer
|
|
||||||
|
|
||||||
c1.onElement = function (selector, options /*, disconnectedCallback*/) {
|
|
||||||
if (typeof options === 'function') {
|
|
||||||
options = { parsed: options }
|
|
||||||
}
|
|
||||||
var listener = {
|
|
||||||
selector: selector,
|
|
||||||
immediate: options.immediate,
|
|
||||||
//disconnectedCallback: disconnectedCallback,
|
|
||||||
elements: new WeakMap(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.parsed) {
|
|
||||||
listener.parsed = function (el) {
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
options.parsed(el)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var els = root.querySelectorAll(listener.selector),
|
|
||||||
i = 0,
|
|
||||||
el
|
|
||||||
while ((el = els[i++])) {
|
|
||||||
listener.elements.set(el, true)
|
|
||||||
listener.parsed && listener.parsed.call(el, el)
|
|
||||||
listener.immediate && listener.immediate.call(el, el)
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners.push(listener)
|
|
||||||
if (!Observer) {
|
|
||||||
Observer = new MutationObserver(checkMutations)
|
|
||||||
Observer.observe(root, {
|
|
||||||
childList: true,
|
|
||||||
subtree: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
checkListener(listener)
|
|
||||||
}
|
|
||||||
function checkListener(listener, target) {
|
|
||||||
var i = 0,
|
|
||||||
el,
|
|
||||||
els = []
|
|
||||||
target && target.matches(listener.selector) && els.push(target)
|
|
||||||
if (loaded) {
|
|
||||||
// ok? check inside node on innerHTML - only when loaded
|
|
||||||
Array.prototype.push.apply(
|
|
||||||
els,
|
|
||||||
(target || root).querySelectorAll(listener.selector)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
while ((el = els[i++])) {
|
|
||||||
if (listener.elements.has(el)) continue
|
|
||||||
listener.elements.set(el, true)
|
|
||||||
//listener.connectedCallback.call(el, el);
|
|
||||||
listener.parsed && listener.parsed.call(el, el)
|
|
||||||
listener.immediate && listener.immediate.call(el, el)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function checkListeners(inside) {
|
|
||||||
var i = 0,
|
|
||||||
listener
|
|
||||||
while ((listener = listeners[i++])) checkListener(listener, inside)
|
|
||||||
}
|
|
||||||
function checkMutations(mutations) {
|
|
||||||
var j = 0,
|
|
||||||
i,
|
|
||||||
mutation,
|
|
||||||
nodes,
|
|
||||||
target
|
|
||||||
while ((mutation = mutations[j++])) {
|
|
||||||
;(nodes = mutation.addedNodes), (i = 0)
|
|
||||||
while ((target = nodes[i++]))
|
|
||||||
target.nodeType === 1 && checkListeners(target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var loaded = false
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
loaded = true
|
|
||||||
})
|
|
||||||
|
|
||||||
// svg polyfills
|
|
||||||
function copyProperty(prop, from, to) {
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(from, prop)
|
|
||||||
Object.defineProperty(to, prop, desc)
|
|
||||||
}
|
|
||||||
if (!('classList' in Element.prototype)) {
|
|
||||||
copyProperty('classList', HTMLElement.prototype, Element.prototype)
|
|
||||||
}
|
|
||||||
if (!('innerHTML' in Element.prototype)) {
|
|
||||||
copyProperty('innerHTML', HTMLElement.prototype, Element.prototype)
|
|
||||||
}
|
|
||||||
if (!('sheet' in SVGStyleElement.prototype)) {
|
|
||||||
Object.defineProperty(SVGStyleElement.prototype, 'sheet', {
|
|
||||||
get: function () {
|
|
||||||
var all = document.styleSheets
|
|
||||||
for (var i = 0, sheet; (sheet = all[i++]); ) {
|
|
||||||
if (sheet.ownerNode === this) return sheet
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// if ('children' in HTMLElement.prototype && !('children' in Element.prototype)) {
|
|
||||||
// copyProperty('children', HTMLElement.prototype, Element.prototype);
|
|
||||||
// }
|
|
||||||
// if ('contains' in HTMLElement.prototype && !('contains' in Element.prototype)) {
|
|
||||||
// copyProperty('contains', HTMLElement.prototype, Element.prototype);
|
|
||||||
// }
|
|
||||||
// if ('getElementsByClassName' in HTMLElement.prototype && !('getElementsByClassName' in Element.prototype)) {
|
|
||||||
// copyProperty('getElementsByClassName', HTMLElement.prototype, Element.prototype);
|
|
||||||
// }
|
|
||||||
})()
|
|
||||||
|
|
||||||
// main logic
|
|
||||||
!(function () {
|
|
||||||
'use strict'
|
|
||||||
var testEl = document.createElement('i')
|
|
||||||
testEl.style.setProperty('--x', 'y')
|
|
||||||
if (testEl.style.getPropertyValue('--x') === 'y' || !testEl.msMatchesSelector)
|
|
||||||
return
|
|
||||||
|
|
||||||
// cached regexps, better performance
|
|
||||||
const regFindSetters = /([\s{;])(--([A-Za-z0-9-_]+\s*:[^;!}{]+)(!important)?)(?=\s*([;}]|$))/g
|
|
||||||
const regFindGetters = /([{;]\s*)([A-Za-z0-9-_]+\s*:[^;}{]*var\([^!;}{]+)(!important)?(?=\s*([;}$]|$))/g
|
|
||||||
const regRuleIEGetters = /-ieVar-([^:]+):/g
|
|
||||||
const regRuleIESetters = /-ie-([^};]+)/g
|
|
||||||
const regHasVar = /var\(/
|
|
||||||
const regPseudos = /:(hover|active|focus|target|:before|:after)/
|
|
||||||
|
|
||||||
c1.onElement('link[rel="stylesheet"]', {
|
|
||||||
immediate: function (el) {
|
|
||||||
fetchCss(el.href, function (css) {
|
|
||||||
var newCss = rewriteCss(css)
|
|
||||||
if (css === newCss) return
|
|
||||||
newCss = relToAbs(el.href, newCss)
|
|
||||||
el.disabled = true
|
|
||||||
var style = document.createElement('style')
|
|
||||||
el.parentNode.insertBefore(style, el)
|
|
||||||
activateStyleElement(style, newCss)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
c1.onElement('style', {
|
|
||||||
immediate: function (el) {
|
|
||||||
if (el.hasAttribute('ie-polyfilled')) return
|
|
||||||
if (el.ieCP_elementSheet) return
|
|
||||||
var css = el.innerHTML
|
|
||||||
var newCss = rewriteCss(css)
|
|
||||||
if (css === newCss) return
|
|
||||||
activateStyleElement(el, newCss)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
c1.onElement('[ie-style]', {
|
|
||||||
immediate: function (el) {
|
|
||||||
var newCss = rewriteCss('{' + el.getAttribute('ie-style')).substr(1)
|
|
||||||
el.style.cssText += ';' + newCss
|
|
||||||
var found = parseRewrittenStyle(el.style)
|
|
||||||
if (found.getters) addGetterElement(el, found.getters, '%styleAttr')
|
|
||||||
if (found.setters) addSetterElement(el, found.setters)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
function relToAbs(base, css) {
|
|
||||||
return css.replace(/url\(([^)]+)\)/g, function ($0, $1) {
|
|
||||||
$1 = $1.trim().replace(/(^['"]|['"]$)/g, '')
|
|
||||||
if ($1.match(/^([a-z]+:|\/)/)) return $0
|
|
||||||
base = base.replace(/\?.*/, '')
|
|
||||||
return 'url(' + base + './../' + $1 + ')'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ie has a bug, where unknown properties at pseudo-selectors are computed at the element
|
|
||||||
// #el::after { -content:'x'; } => getComputedStyle(el)['-content'] == 'x'
|
|
||||||
// should we add something like -ieVar-pseudo_after-content:'x'?
|
|
||||||
function rewriteCss(css) {
|
|
||||||
/* uncomment if spec finished and needed by someone
|
|
||||||
css = css.replace(/@property ([^{]+){([^}]+)}/, function($0, prop, body){
|
|
||||||
prop = prop.trim();
|
|
||||||
const declaration = {name:prop};
|
|
||||||
body.split(';').forEach(function(pair){
|
|
||||||
const x = pair.split(':');
|
|
||||||
if (x[1]) declaration[ x[0].trim() ] = x[1];
|
|
||||||
});
|
|
||||||
declaration['inherits'] = declaration['inherits'].trim()==='true' ? true : false;
|
|
||||||
declaration['initialValue'] = declaration['initial-value'];
|
|
||||||
CSS.registerProperty(declaration)
|
|
||||||
return '/*\n @property ... removed \n*'+'/';
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
return css
|
|
||||||
.replace(regFindSetters, function ($0, $1, $2, $3, important) {
|
|
||||||
return $1 + '-ie-' + (important ? '❗' : '') + $3
|
|
||||||
})
|
|
||||||
.replace(regFindGetters, function ($0, $1, $2, important) {
|
|
||||||
return $1 + '-ieVar-' + (important ? '❗' : '') + $2 + '; ' + $2 // keep the original, so chaining works "--x:var(--y)"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// beta
|
|
||||||
const styles_of_getter_properties = {}
|
|
||||||
|
|
||||||
function parseRewrittenStyle(style) {
|
|
||||||
// less memory then parameter cssText?
|
|
||||||
|
|
||||||
// beta
|
|
||||||
style['z-index'] // ie11 can access unknown properties in stylesheets only if accessed a dashed known property
|
|
||||||
|
|
||||||
const cssText = style.cssText
|
|
||||||
var matchesGetters = cssText.match(regRuleIEGetters),
|
|
||||||
j,
|
|
||||||
match
|
|
||||||
if (matchesGetters) {
|
|
||||||
var getters = [] // eg. [border,color]
|
|
||||||
for (j = 0; (match = matchesGetters[j++]); ) {
|
|
||||||
let propName = match.slice(7, -1)
|
|
||||||
if (propName[0] === '❗') propName = propName.substr(1)
|
|
||||||
getters.push(propName)
|
|
||||||
|
|
||||||
// beta
|
|
||||||
if (!styles_of_getter_properties[propName])
|
|
||||||
styles_of_getter_properties[propName] = []
|
|
||||||
styles_of_getter_properties[propName].push(style)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var matchesSetters = cssText.match(regRuleIESetters)
|
|
||||||
if (matchesSetters) {
|
|
||||||
var setters = {} // eg. [--color:#fff, --padding:10px];
|
|
||||||
for (j = 0; (match = matchesSetters[j++]); ) {
|
|
||||||
let x = match.substr(4).split(':')
|
|
||||||
let propName = x[0]
|
|
||||||
let propValue = x[1]
|
|
||||||
if (propName[0] === '❗') propName = propName.substr(1)
|
|
||||||
setters[propName] = propValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { getters: getters, setters: setters }
|
|
||||||
}
|
|
||||||
function activateStyleElement(style, css) {
|
|
||||||
style.innerHTML = css
|
|
||||||
style.setAttribute('ie-polyfilled', true)
|
|
||||||
var rules = style.sheet.rules,
|
|
||||||
i = 0,
|
|
||||||
rule // cssRules = CSSRuleList, rules = MSCSSRuleList
|
|
||||||
while ((rule = rules[i++])) {
|
|
||||||
const found = parseRewrittenStyle(rule.style)
|
|
||||||
if (found.getters) addGettersSelector(rule.selectorText, found.getters)
|
|
||||||
if (found.setters) addSettersSelector(rule.selectorText, found.setters)
|
|
||||||
|
|
||||||
// mediaQueries: redraw the hole document
|
|
||||||
// better add events for each element?
|
|
||||||
const media =
|
|
||||||
rule.parentRule &&
|
|
||||||
rule.parentRule.media &&
|
|
||||||
rule.parentRule.media.mediaText
|
|
||||||
if (media && (found.getters || found.setters)) {
|
|
||||||
matchMedia(media).addListener(function () {
|
|
||||||
drawTree(document.documentElement)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// beta
|
|
||||||
redrawStyleSheets()
|
|
||||||
}
|
|
||||||
|
|
||||||
function addGettersSelector(selector, properties) {
|
|
||||||
selectorAddPseudoListeners(selector)
|
|
||||||
c1.onElement(unPseudo(selector), {
|
|
||||||
immediate: function (el) {
|
|
||||||
addGetterElement(el, properties, selector)
|
|
||||||
drawElement(el)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function addGetterElement(el, properties, selector) {
|
|
||||||
var i = 0,
|
|
||||||
prop,
|
|
||||||
j
|
|
||||||
const selectors = selector.split(',') // split grouped selectors
|
|
||||||
el.setAttribute('iecp-needed', true)
|
|
||||||
if (!el.ieCPSelectors) el.ieCPSelectors = {}
|
|
||||||
while ((prop = properties[i++])) {
|
|
||||||
for (j = 0; (selector = selectors[j++]); ) {
|
|
||||||
const parts = selector.trim().split('::')
|
|
||||||
if (!el.ieCPSelectors[prop]) el.ieCPSelectors[prop] = []
|
|
||||||
el.ieCPSelectors[prop].push({
|
|
||||||
selector: parts[0],
|
|
||||||
pseudo: parts[1] ? '::' + parts[1] : '',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function addSettersSelector(selector, propVals) {
|
|
||||||
selectorAddPseudoListeners(selector)
|
|
||||||
c1.onElement(unPseudo(selector), {
|
|
||||||
immediate: function (el) {
|
|
||||||
addSetterElement(el, propVals)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function addSetterElement(el, propVals) {
|
|
||||||
if (!el.ieCP_setters) el.ieCP_setters = {}
|
|
||||||
for (var prop in propVals) {
|
|
||||||
// eg. {foo:#fff, bar:baz}
|
|
||||||
el.ieCP_setters['--' + prop] = 1
|
|
||||||
}
|
|
||||||
drawTree(el)
|
|
||||||
}
|
|
||||||
|
|
||||||
//beta
|
|
||||||
function redrawStyleSheets() {
|
|
||||||
for (var prop in styles_of_getter_properties) {
|
|
||||||
let styles = styles_of_getter_properties[prop]
|
|
||||||
for (var i = 0, style; (style = styles[i++]); ) {
|
|
||||||
if (style.owningElement) continue
|
|
||||||
var value = style['-ieVar-' + prop]
|
|
||||||
if (!value) continue
|
|
||||||
var value = styleComputeValueWidthVars(
|
|
||||||
getComputedStyle(document.documentElement),
|
|
||||||
value
|
|
||||||
)
|
|
||||||
if (value === '') continue
|
|
||||||
style[prop] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pseudos = {
|
|
||||||
hover: {
|
|
||||||
on: 'mouseenter',
|
|
||||||
off: 'mouseleave',
|
|
||||||
},
|
|
||||||
focus: {
|
|
||||||
on: 'focusin',
|
|
||||||
off: 'focusout',
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
on: 'CSSActivate',
|
|
||||||
off: 'CSSDeactivate',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
function selectorAddPseudoListeners(selector) {
|
|
||||||
// ie11 has the strange behavoir, that groups of selectors are individual rules, but starting with the full selector:
|
|
||||||
// td, th, button { color:red } results in this rules:
|
|
||||||
// "td, th, button" | "th, th" | "th"
|
|
||||||
selector = selector.split(',')[0]
|
|
||||||
for (var pseudo in pseudos) {
|
|
||||||
var parts = selector.split(':' + pseudo)
|
|
||||||
if (parts.length > 1) {
|
|
||||||
var ending = parts[1].match(/^[^\s]*/) // ending elementpart of selector (used for not(:active))
|
|
||||||
let sel = unPseudo(parts[0] + ending)
|
|
||||||
const listeners = pseudos[pseudo]
|
|
||||||
c1.onElement(sel, function (el) {
|
|
||||||
el.addEventListener(listeners.on, drawTreeEvent)
|
|
||||||
el.addEventListener(listeners.off, drawTreeEvent)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let CSSActive = null
|
|
||||||
document.addEventListener('mousedown', function (e) {
|
|
||||||
setTimeout(function () {
|
|
||||||
if (e.target === document.activeElement) {
|
|
||||||
var evt = document.createEvent('Event')
|
|
||||||
evt.initEvent('CSSActivate', true, true)
|
|
||||||
CSSActive = e.target
|
|
||||||
CSSActive.dispatchEvent(evt)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
document.addEventListener('mouseup', function () {
|
|
||||||
if (CSSActive) {
|
|
||||||
var evt = document.createEvent('Event')
|
|
||||||
evt.initEvent('CSSDeactivate', true, true)
|
|
||||||
CSSActive.dispatchEvent(evt)
|
|
||||||
CSSActive = null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
function unPseudo(selector) {
|
|
||||||
return selector.replace(regPseudos, '').replace(':not()', '')
|
|
||||||
}
|
|
||||||
|
|
||||||
var uniqueCounter = 0
|
|
||||||
|
|
||||||
function _drawElement(el) {
|
|
||||||
if (!el.ieCP_unique) {
|
|
||||||
// use el.uniqueNumber? but needs class for the css-selector => test performance
|
|
||||||
el.ieCP_unique = ++uniqueCounter
|
|
||||||
el.classList.add('iecp-u' + el.ieCP_unique)
|
|
||||||
}
|
|
||||||
var style = getComputedStyle(el)
|
|
||||||
if (el.ieCP_sheet)
|
|
||||||
while (el.ieCP_sheet.rules[0]) el.ieCP_sheet.deleteRule(0)
|
|
||||||
for (var prop in el.ieCPSelectors) {
|
|
||||||
var important = style['-ieVar-❗' + prop]
|
|
||||||
let valueWithVar = important || style['-ieVar-' + prop]
|
|
||||||
if (!valueWithVar) continue // todo, what if '0'
|
|
||||||
|
|
||||||
var details = {}
|
|
||||||
var value = styleComputeValueWidthVars(style, valueWithVar, details)
|
|
||||||
|
|
||||||
if (important) value += ' !important'
|
|
||||||
for (var i = 0, item; (item = el.ieCPSelectors[prop][i++]); ) {
|
|
||||||
// todo: split and use requestAnimationFrame?
|
|
||||||
if (item.selector === '%styleAttr') {
|
|
||||||
el.style[prop] = value
|
|
||||||
} else {
|
|
||||||
// beta
|
|
||||||
if (!important && details.allByRoot !== false) continue // dont have to draw root-properties
|
|
||||||
|
|
||||||
//let selector = item.selector.replace(/>? \.[^ ]+/, ' ', item.selector); // todo: try to equalize specificity
|
|
||||||
let selector = item.selector
|
|
||||||
elementStyleSheet(el).insertRule(
|
|
||||||
selector +
|
|
||||||
'.iecp-u' +
|
|
||||||
el.ieCP_unique +
|
|
||||||
item.pseudo +
|
|
||||||
' {' +
|
|
||||||
prop +
|
|
||||||
':' +
|
|
||||||
value +
|
|
||||||
'}',
|
|
||||||
0
|
|
||||||
) // faster then innerHTML
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function elementStyleSheet(el) {
|
|
||||||
if (!el.ieCP_sheet) {
|
|
||||||
var tag = document.createElement('style')
|
|
||||||
tag.ieCP_elementSheet = 1
|
|
||||||
//el.appendChild(tag); // yes! self-closing tags can have style as children, but - if i set innerHTML, the stylesheet is lost
|
|
||||||
document.head.appendChild(tag)
|
|
||||||
el.ieCP_sheet = tag.sheet
|
|
||||||
}
|
|
||||||
return el.ieCP_sheet
|
|
||||||
}
|
|
||||||
function drawTree(target) {
|
|
||||||
if (!target) return
|
|
||||||
var els = target.querySelectorAll('[iecp-needed]')
|
|
||||||
if (target.hasAttribute && target.hasAttribute('iecp-needed'))
|
|
||||||
drawElement(target) // self
|
|
||||||
for (var i = 0, el; (el = els[i++]); ) drawElement(el) // tree
|
|
||||||
}
|
|
||||||
// draw queue
|
|
||||||
let drawQueue = new Set()
|
|
||||||
let collecting = false
|
|
||||||
let drawing = false
|
|
||||||
function drawElement(el) {
|
|
||||||
drawQueue.add(el)
|
|
||||||
if (collecting) return
|
|
||||||
collecting = true
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
collecting = false
|
|
||||||
drawing = true
|
|
||||||
drawQueue.forEach(_drawElement)
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
// mutationObserver will trigger delayed
|
|
||||||
drawing = false
|
|
||||||
})
|
|
||||||
drawQueue.clear()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawTreeEvent(e) {
|
|
||||||
drawTree(e.target)
|
|
||||||
}
|
|
||||||
|
|
||||||
const regValueGetters = /var\(([^),]+)(\,(.+))?\)/g
|
|
||||||
function styleComputeValueWidthVars(style, valueWithVar, details) {
|
|
||||||
return valueWithVar.replace(regValueGetters, function (
|
|
||||||
full,
|
|
||||||
variable,
|
|
||||||
x,
|
|
||||||
fallback
|
|
||||||
) {
|
|
||||||
variable = variable.trim()
|
|
||||||
var pValue = style.getPropertyValue(variable)
|
|
||||||
if (details && style.lastPropertyServedBy !== document.documentElement)
|
|
||||||
details.allByRoot = false
|
|
||||||
if (pValue === '' && fallback !== undefined) pValue = fallback.trim() // fallback
|
|
||||||
return pValue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// mutation listener
|
|
||||||
var observer = new MutationObserver(function (mutations) {
|
|
||||||
if (drawing) return
|
|
||||||
for (var i = 0, mutation; (mutation = mutations[i++]); ) {
|
|
||||||
if (mutation.attributeName === 'ie-polyfilled') continue
|
|
||||||
if (mutation.attributeName === 'iecp-needed') continue
|
|
||||||
// recheck all selectors if it targets new elements?
|
|
||||||
drawTree(mutation.target)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
setTimeout(function () {
|
|
||||||
observer.observe(document, { attributes: true, subtree: true })
|
|
||||||
})
|
|
||||||
|
|
||||||
// :target listener
|
|
||||||
var oldHash = location.hash
|
|
||||||
addEventListener('hashchange', function (e) {
|
|
||||||
var newEl = document.getElementById(location.hash.substr(1))
|
|
||||||
if (newEl) {
|
|
||||||
var oldEl = document.getElementById(oldHash.substr(1))
|
|
||||||
drawTree(newEl)
|
|
||||||
drawTree(oldEl)
|
|
||||||
} else {
|
|
||||||
drawTree(document)
|
|
||||||
}
|
|
||||||
oldHash = location.hash
|
|
||||||
})
|
|
||||||
|
|
||||||
// add owningElement to Element.style
|
|
||||||
var descriptor = Object.getOwnPropertyDescriptor(
|
|
||||||
HTMLElement.prototype,
|
|
||||||
'style'
|
|
||||||
)
|
|
||||||
var styleGetter = descriptor.get
|
|
||||||
descriptor.get = function () {
|
|
||||||
const style = styleGetter.call(this)
|
|
||||||
style.owningElement = this
|
|
||||||
return style
|
|
||||||
}
|
|
||||||
Object.defineProperty(HTMLElement.prototype, 'style', descriptor)
|
|
||||||
|
|
||||||
// add computedFor to computed style-objects
|
|
||||||
var originalGetComputed = getComputedStyle
|
|
||||||
window.getComputedStyle = function (el) {
|
|
||||||
var style = originalGetComputed.apply(this, arguments)
|
|
||||||
style.computedFor = el
|
|
||||||
//style.pseudoElt = pseudoElt; //not needed at the moment
|
|
||||||
return style
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPropertyValue / setProperty hooks
|
|
||||||
const StyleProto = CSSStyleDeclaration.prototype
|
|
||||||
|
|
||||||
const oldGetP = StyleProto.getPropertyValue
|
|
||||||
StyleProto.getPropertyValue = function (property) {
|
|
||||||
this.lastPropertyServedBy = false
|
|
||||||
if (property[0] !== '-' || property[1] !== '-')
|
|
||||||
return oldGetP.apply(this, arguments)
|
|
||||||
const undashed = property.substr(2)
|
|
||||||
const ieProperty = '-ie-' + undashed
|
|
||||||
const iePropertyImportant = '-ie-❗' + undashed
|
|
||||||
let value = this[iePropertyImportant] || this[ieProperty]
|
|
||||||
if (this.computedFor) {
|
|
||||||
// computedStyle
|
|
||||||
if (value !== undefined) {
|
|
||||||
if (regHasVar.test(value)) {
|
|
||||||
value = styleComputeValueWidthVars(this, value)
|
|
||||||
}
|
|
||||||
this.lastPropertyServedBy = this.computedFor
|
|
||||||
} else {
|
|
||||||
if (!register[property] || register[property].inherits) {
|
|
||||||
// inherited
|
|
||||||
//let el = this.pseudoElt ? this.computedFor : this.computedFor.parentNode;
|
|
||||||
let el = this.computedFor.parentNode
|
|
||||||
while (el.nodeType === 1) {
|
|
||||||
// how slower would it be to getComputedStyle for every element, not just with defined ieCP_setters
|
|
||||||
if (el.ieCP_setters && el.ieCP_setters[property]) {
|
|
||||||
// i could make
|
|
||||||
// value = el.nodeType ? getComputedStyle(this.computedFor.parentNode).getPropertyValue(property)
|
|
||||||
// but i fear performance, stupid?
|
|
||||||
var style = getComputedStyle(el)
|
|
||||||
var tmpVal = style[iePropertyImportant] || style[ieProperty]
|
|
||||||
if (tmpVal !== undefined) {
|
|
||||||
value = tmpVal
|
|
||||||
if (regHasVar.test(value)) {
|
|
||||||
// calculated style from current element not from the element the value was inherited from! (style, value)
|
|
||||||
value = styleComputeValueWidthVars(this, value)
|
|
||||||
}
|
|
||||||
this.lastPropertyServedBy = el
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
el = el.parentNode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (value === undefined && register[property])
|
|
||||||
value = register[property].initialValue
|
|
||||||
if (value === undefined) value = ''
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldSetP = StyleProto.setProperty
|
|
||||||
StyleProto.setProperty = function (property, value, prio) {
|
|
||||||
if (property[0] !== '-' || property[1] !== '-')
|
|
||||||
return oldSetP.apply(this, arguments)
|
|
||||||
if (this.owningElement) {
|
|
||||||
const el = this.owningElement
|
|
||||||
if (!el.ieCP_setters) el.ieCP_setters = {}
|
|
||||||
el.ieCP_setters[property] = 1
|
|
||||||
drawTree(el)
|
|
||||||
}
|
|
||||||
property = '-ie-' + (prio === 'important' ? '❗' : '') + property.substr(2)
|
|
||||||
this.cssText += '; ' + property + ':' + value + ';'
|
|
||||||
//this[property] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!window.CSS) window.CSS = {}
|
|
||||||
const register = {}
|
|
||||||
CSS.registerProperty = function (options) {
|
|
||||||
register[options.name] = options
|
|
||||||
}
|
|
||||||
|
|
||||||
// utils
|
|
||||||
function fetchCss(url, callback) {
|
|
||||||
var request = new XMLHttpRequest()
|
|
||||||
request.open('GET', url)
|
|
||||||
request.overrideMimeType('text/css')
|
|
||||||
request.onload = function () {
|
|
||||||
if (request.status >= 200 && request.status < 400) {
|
|
||||||
callback(request.responseText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.send()
|
|
||||||
}
|
|
||||||
})()
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
!(function () {
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.innerHTML =
|
||||||
|
'<div class="ie-warning">' +
|
||||||
|
' <p class="ie-warning-description">' +
|
||||||
|
' Internet Explorer is no longer supported.' +
|
||||||
|
' <a href="https://support.hashicorp.com/hc/en-us/articles/4416485547795">' +
|
||||||
|
' Learn more.' +
|
||||||
|
' </a>' +
|
||||||
|
' </p>' +
|
||||||
|
'</div>' +
|
||||||
|
'<style>' +
|
||||||
|
' .ie-warning {' +
|
||||||
|
' background-color: #FCF0F2;' +
|
||||||
|
' border-bottom: 1px solid #FFD4D6;' +
|
||||||
|
' color: #BA2226;' +
|
||||||
|
' text-align: center;' +
|
||||||
|
' font-family: "Segoe UI", sans-serif;' +
|
||||||
|
' font-weight: bold;' +
|
||||||
|
' }' +
|
||||||
|
' .ie-warning-description {' +
|
||||||
|
' padding: 16px 0;' +
|
||||||
|
' margin: 0;' +
|
||||||
|
' color: #BA2226;' +
|
||||||
|
' }' +
|
||||||
|
'</style>';
|
||||||
|
|
||||||
|
document.body.insertBefore(el, document.body.childNodes[0]);
|
||||||
|
})();
|
Loading…
Reference in New Issue