Add a transparent mask to the image and text elements by injecting JS into the page

background

Recently, I have been working on a small tool to manipulate the Dom.

A little exercise was pulled out of it:

  1. Highlight all image elements on the page
  2. Highlight all text elements on the page
  3. When the page triggers show/hide, convert text/image highlighting color

The final effect is as follows:

Injection of js

There are many ways to inject JS into third-party pages

Here demo uses the DevTools console for injection

The simple code is as follows

var a=document.createElement('script');
a.src="http://127.0.0.1:8080/index.js";
window.document.head.append(a)
Copy the code

Images highlight

There are two ways to display regular pictures:

  1. use<img>The label
  2. Set elementbackgroundorbackground-imageattribute

Is a

Wrap it around a

tag, and then add a

mask

<div>
    <img src="url">
</div>
Copy the code

After adding the mask layer structure

<div>
    <div style="position:relative">
        <img src="url">
        <div class="cover"></div>
    </div>
</div>
Copy the code

The code for adding a mask is as follows:

    function addImgCover(img, bgc = 'rgba (255,0,0,0.2)') {
        // If there is a mask, use a new color
        if (img.getAttribute('cover')) {
            img.nextElementSibling.style.backgroundColor = bgc
            return
        }

        // The flag has been masked
        img.setAttribute('cover'.'1')

        const divParent = document.createElement('div')
        divParent.style.position = 'relative'

        const divChild = document.createElement('div')
        divChild.style.position = 'absolute'
        divChild.style.top = '0'
        divChild.style.width = '100%'
        divChild.style.height = '100%'
        divChild.style.backgroundColor = bgc

        divParent.appendChild(img.cloneNode())
        divParent.appendChild(divChild)

        img.replaceWith(divParent)
    }
Copy the code

Case 2

As a background image, you can add a child

as a mask
<div>
    <div style="background-image:url(xxxx)"></div>
</div>
Copy the code

After adding the mask layer structure

<div>
    <div style="background-image:url(xxxx)">
        <div class="cover"></div>
    </div>
</div>
Copy the code

The code for adding a mask is as follows:

    function addBgImgCover(bgImg, bgc = 'rgba (255,0,0,0.2)') {
        // If there is a mask, use a new color
        if (bgImg.getAttribute('cover')) {
            bgImg.children[0].style.backgroundColor = bgc
            return
        }

        // The flag has been masked
        bgImg.setAttribute('cover'.'1')

        const divChild = document.createElement('div')
        divChild.style.width = '100%'
        divChild.style.height = '100%'
        divChild.style.backgroundColor = bgc
        bgImg.appendChild(divChild)
    }
Copy the code

Text highlighted

Text is relatively simple, you can directly set background-color implementation

function addTextCover(textEl, bgc = 'rgba (255,0,0,0.2)') {
    textEl.style.backgroundColor = bgc
}
Copy the code

Gets all picture elements

Get the IMG element using querySelectorAll

A simple recursive method to get elements that use background-image attributes

To achieve the following

    function judgeBgImgEl(el) {
        returnel && !! el.style.backgroundImage }function getAllImgEls() {
        / / routine
        const imgs = document.querySelectorAll('img')

        // Recursively get unconventional
        const getBgIms = (el = document.body) = > {
            const res = []
            if (el.childElementCount > 0) {
                Array.from(el.children).forEach(v= >{ res.push(... getBgIms(v)) }) }if (judgeBgImgEl(el)) {
                res.push(el)
            }
            return res
        }
        const bgImgs = getBgIms()
        return {
            imgs,
            bgImgs
        }
    }
Copy the code

Gets all text elements

The idea is consistent with recursive image acquisition, with slightly different conditions

  1. throughtextContentYou can get the text content of an element (including descendant elements)
  2. throughchildElementCountCan get the number of child elements
  3. If there are no children and the content is not empty, the element is the target element

To achieve the following

function getAllTextEls() {
    // Recursive fetch
    const getTextEls = (el = document.body) = > {
        const res = []
        if (el.childElementCount === 0) { el.textContent.trim().length ! = =0 && res.push(el)
        } else {
            Array.from(el.children).forEach(e= >{ res.push(... getTextEls(e)) }) }return res
    }
    return getTextEls()
}
Copy the code

Listen for the page to appear/disappear

Call the native listener event (visibilityChange) directly:

    let theme = 'red'

    // Theme switch
    window.addEventListener('visibilitychange'.(e) = > {
        if (document.hidden) {
            theme = theme === 'red' ? 'blue' : 'red'
            changeTheme(theme)
        }
    })
Copy the code

The last

This article is just a simple brick, do a simple demo

There must be some inconsiderate places in the above method, which is left for interested students to explore

Full source code address