Skip to content

Instantly share code, notes, and snippets.

@kissarat
Last active March 11, 2019 15:26
Show Gist options
  • Save kissarat/b979c322bf3ced4c21009b60160b20fa to your computer and use it in GitHub Desktop.
Save kissarat/b979c322bf3ced4c21009b60160b20fa to your computer and use it in GitHub Desktop.
function *$combine(...seq) {
for (let i = 1; i <= seq.length; i++) {
for (let j = 0; j <= seq.length - i; j++) {
yield seq.slice(j, j + i)
}
}
}
const denyAttrs = ['class', 'style', 'width', 'height', 'value', 'd', 'viewBox', 'transform']
const rareTags = ['form',
'footer',
'header', 'article', 'section', 'aside', 'img', 'cite', 'optgroup', 'tbody', 'tr', 'td',
'table', 'acronym', 'address', 'ul', 'ins', 'fieldset', 'abbr', 'rel', 'wbr', 'svg']
function *y(el) {
const tagName = el.tagName.toLowerCase()
const names = [].filter.call(el.attributes, a => a.value && denyAttrs.indexOf(a.name) < 0
&& a.name.indexOf(':') < 0
&& a.value.indexOf('{') < 0)
for (const attrs of $combine(...names)) {
yield attrs.map(a => `[${a.name}="${a.value}"]`).join('')
}
for (const c of $combine(...el.classList.values())) {
yield c.map(cc => '.' + cc).join('')
}
const count = el.parentNode.childElementCount
if (count > 1) {
let i
switch (tagName) {
case 'td':
i = el.cellIndex + 1
break
case 'tr':
i = el.rowIndex + 1
break
default:
i = [].indexOf.call(el.parentNode.children, el) + 1
break
}
if (i > 0) {
yield tagName + `:nth-child(${i})`
}
}
if (rareTags.indexOf(tagName) >= 0) {
yield tagName
}
}
function $check(selector) {
return document.querySelectorAll(selector).length === 1 ? selector : false
}
function * $identity(el) {
if (el.id) {
yield el.id.indexOf(':') >= 0 ? `[id="${el.id}"]` : '#' + el.id
}
for (const parts of y(el)) {
yield parts
}
}
function * deep(array, ...head) {
if (head.length > 0) {
for (const a of array) {
for (const b of deep(...head)) {
yield [a, ...b]
}
}
}
else {
for (const a of array) {
yield [a]
}
}
}
function * parental(el) {
let parent = el
while ((parent = parent.parentNode) && parent !== document.documentElement) {
yield parent
}
}
function checkElement(el) {
for (const selector of $identity(el)) {
if ($check(selector)) {
return selector
}
}
}
function * group(...parents) {
for (let i = 1; i <= parents.length; i++) {
for (const comb of deep(...(parents.slice(0, i).reverse().map($identity)))) {
yield comb.join(' ')
// if (comb.length > 1) {
// yield comb.join('>')
// }
}
}
}
function $selector(el) {
for (const selector of group(el, ...parental(el))) {
// console.log(selector)
if ($check(selector)) {
return selector
}
}
}
const css = `
#zen {
position: fixed;
top: 0;
border: 2px dotted black;
pointer-events: none;
}
#zen > div {
position: absolute;
top: -20px;
width: 300px;
font-family: Courier New;
font-size: 12px;
padding: 2px 4px;
border: 1px solid black;
background-color: white;
}
`
// addEventListener('load', function () {
const style = document.createElement('style')
style.innerHTML = css
document.head.appendChild(style)
const zen = document.createElement('div')
zen.id = 'zen'
const informer = document.createElement('div')
zen.appendChild(informer)
document.body.appendChild(zen)
addEventListener('mousemove', function (e) {
const el = document.elementFromPoint(e.x, e.y)
const selector = $selector(el)
if (selector) {
const el = document.querySelector(selector)
const rect = el.getBoundingClientRect()
// if (e.y < 70) {
// informer.style.top = '100px'
// }
informer.innerHTML = selector
Object.assign(zen.style, {
left: rect.left - 1 + 'px',
top: rect.top - 1 + 'px',
width: rect.width + 'px',
height: rect.height + 'px'
})
}
})
// })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment