Обговорення » Розробка

How do I prevent CSS interference in an injected js element?

§
Опубліковано: 09.02.2021
Edited: 09.02.2021

My script Search/copy menu works fine on most websites when any text is selected
https://greasyfork.org/en/scripts/419825-opera-browser-rocker-mouse-gestures-search-highlight

But sometimes some websites like this one
https://www.epicdope.com/how-to-watch-free-easy-watch-order-guide/

Style the whole elements.
How can I make sure that the page css won't change my script css?

woxxomMod
§
Опубліковано: 09.02.2021
Edited: 09.02.2021

Either use ShadowDOM (look for tutorials on style isolation via ShadowDOM) or add explicit style attribute on your added elements that specify the basic parameters like color, background, margins, padding - all with !important priority.

§
Опубліковано: 09.02.2021

Do you mean that your script menu styles was changed by a website css styles? You can use an iframe for your script menu. Some styles still could be overrided though, but less likely

§
Опубліковано: 09.02.2021

@wOxxOm
Thanks. I will search for that.

@Konf

Yes that's what I mean. Interesting idea, I may also try your idea.

I'm adding the menu styles of my script to the page using insertadjacenthtml, when I searched on google someone said that using append would stop sites from changing my script menu style.

§
Опубліковано: 10.02.2021

@wOxxOm

I've tried what you said, but anything I tried with the code below just makes the whole website white.

https://www.epicdope.com/how-to-watch-free-easy-watch-order-guide/

var Element = document.createElement('a');
Element.innerHTML = 'Whatever';

document.body.attachShadow({ mode: 'open' }).append(Element);

woxxomMod
§
Опубліковано: 10.02.2021

That's because you need to attach the shadow to a separate div, then document.body.appendChild(div).

§
Опубліковано: 10.02.2021
Edited: 10.02.2021

@wOxxOm

I tried changing
var Element = document.createElement('a');
to
var Element = document.createElement('div');
But this makes the same result

The codes below works, but the element css are still being changed.
*The menu should be "search | copy" side by side, not one above the other.

let shadowRoot = document.createElement('div').attachShadow({ mode: 'open' });

shadowRoot.innerHTML = https://pastebin.com/bBpEyAQ6

document.body.appendChild(shadowRoot);

woxxomMod
§
Опубліковано: 10.02.2021

You're inventing something instead of using code from a tutorial which is why it doesn't work.

const el = document.createElement('div');
const root = el.attachShadow({ mode: 'open' });
root.innerHTML = '<div>foo</div>';
document.body.appendChild(el);
§
Опубліковано: 10.02.2021
Edited: 10.02.2021

@wOxxOm

By looking and testing your code I was finally able to understand it, thanks!
I was able to manage it to work, but the problem is that my script relies on jquery to display the menu on the correct page position, and for some reason the jquery commands aren't working with the selected shadown element.

https://pastebin.com/ePBZg88d After the shadown element is appended I get some errors like
$("#highlight_menu_div")[0].shadowRoot.querySelector("#highlight_menu").height()
$("#highlight_menu_div")[0].shadowRoot.querySelector("#highlight_menu").width()
$("#highlight_menu_div")[0].shadowRoot.querySelector("#highlight_menu").css()

"are not a function"

Is there an easy way to fix this, or would I need to rewrite this function from 0?

woxxomMod
§
Опубліковано: 10.02.2021

querySelector returns a standard DOM element, not a jQuery object so to use height() and other jQuery methods you should wrap the result like this:

$("#highlight_menu", $("#highlight_menu_div")[0].shadowRoot).height()
§
Опубліковано: 10.02.2021
Edited: 10.02.2021

@wOxxOm

That makes sense. Everything is working fine now, but the previous style that I appended to the page
.highlight_menu_animate .popuptext::after {
content: ""; height: 35px !important; top: 100%; left: 50%; margin-left: -10px !important; border-width: 10px !important; position: absolute; border-style: solid; border-color: #292929 transparent transparent transparent;
}

Isn't working now.

§
Опубліковано: 10.02.2021
Edited: 10.02.2021

**
I've fixed that by doing this
https://pastebin.com/UntLAk8P

But I'm not sure if what I did is "wrong" or if there's a better method of doing this.

woxxomMod
§
Опубліковано: 10.02.2021
Edited: 10.02.2021

That's because you need to add the style inside the ShadowDOM. It should have been explained in tutorials. Style isolation was the entire point of my suggestion to use ShadowDOM.

§
Опубліковано: 10.02.2021
Edited: 10.02.2021

@wOxxOm

Got it, so there's no better method of doing this...

Btw do you know why the advent listener of mouseup isn't being added to text areas?
This is making the script not show the menu when a text is selected on this reply box for example

woxxomMod
§
Опубліковано: 10.02.2021

If the textarea is inside ShadowDOM then you need to listen to events inside this shadow root e.g. something like $('#highlight_menu', root).on('mouseup', yourFunction)

§
Опубліковано: 10.02.2021

@wOxxOm

This greasyfork reply text area isn't inside ShadowDOM, even though the script doesn't add the mouseup advent listener to the textbox, only to the document.body.

And I also had that same problem with all previous versions (12 and less) of my script

Опублікувати відповідь

Sign in to post a reply.