Updating CSS variable with JavaScript not happening at runtime - javascript

I have an odd issue. I am attempting to set a CSS variable and change this dynamically on page load.
It works fine in my rudimentary jsfiddle here: https://jsfiddle.net/lharby/jw6t0krm/
The basic code is:
const colours = ['#ee4800','#60c600','#00ffff','#ff7f00','#ff6ccc','#848382','#d2dd26'];
const rndColour = Math.floor(Math.random() * colours.length);
document.documentElement.style.setProperty("--selection-background", colours[rndColour]);
My app is more complex in using transpiling, so my setColourFunction looks like this:
const colours = ['#ee4800','#60c600'...]; // same as previous array
const rndColour = Math.floor(Math.random() * colours.length);
const setRandomColour = () => {
document.documentElement.style.setProperty(
'--selection-background',
colours[rndColour]
);
};
export { setRandomColour };
Then, in my main app, I am importing like so:
import { setRandomColour } from './js/randomColours';
$(document).ready(() => {
if (DOM.classList.contains('high-contrast')) {
setRandomColour();
}
}
In the browser, the background colour is set as a pink tone by default (which is one of the items inside the colour array). If I hover over the scrollbar or click the navigation, the scrollbar changes colour to the correct value in the variable. I assumed this might be some Chrome bug, but the jsfiddle seems to work fine.
You can see an example of the live app here: https://studiomalarkey.co.uk/
At one time, I did have a reference to my minified script using the defer method, and thought this might be the issue, but I have removed that property now.
Does anyone know why this might be happening?

Related

Android Webview not showing backgroundImage from Javascript

I know it's a silly mistake but I can't figure it out. I have been searching for it for the past 3 days. Basically, I have a function that changes the theme of a page by modifying CSS using Javascript. All properties are modified correctly, except the backgroundImage, don't know why. Here's the function:
function enforceTheme() {
document.body.style.backgroundColor = theme["bgColor"];
const background = "https://via.placeholder.com/300/09f/fff.png";
document.body.style.backgroundImage = 'url('+background+');';
document.getElementById("upBtn").style.color = theme["upBtnColor"];
document.getElementById("downBtn").style.color = theme["downBtnColor"];
}
The strange thing is that the code gives no error and works fine, except for the backgroundImage not showing. And it works if I set it using CSS stylesheet. But I need to change it dynamically, so using Javascript.
You have to use Template Literals
Try this
function enforceTheme() {
document.body.style.backgroundColor = theme["bgColor"];
const background = "https://via.placeholder.com/300/09f/fff.png";
document.body.style.backgroundImage = `url('${background}')`;
document.getElementById("upBtn").style.color = theme["upBtnColor"];
document.getElementById("downBtn").style.color = theme["downBtnColor"];
}

Injecting gatsby-image into html created from markdown using ReactDOMServer.renderToString

Minimum Reproducible Example on Github
I'm trying to inject some images into my pages created from markdown. I'm trying to do this using ReactDomServer.renderToString()
const componentCreatedFromMarkdown = ({data}) => {
...
useEffect(() => {
const injectDivs = Array.from(document.getElementsByClassName('injectDivs'))
injectDivs.forEach((aDiv) => {
aDiv.innerHTML = ReactDOMServer.renderToString(<Img fluid={data.allFile.edges[0].node.childImageSharp.fluid} />)
}
})
...
}
The img is showing as a black box, if I right click the image I can open it in a new tab, which shows the image as it is supposed to be.
How I understand the problem
The image html is correctly inserted into the page
gatsby-image loads the lowest quality image and applies some inline
styles. All that information is present in the html) This is done to
enable the blur-up effect on the image for a better UX.
The client side code that would load a higher resolution image and remove the inline styles is never applied.
Useful diagnostic information
The function inside useEffect does not get run on the server-side, but rather on the client after the component has mounted. It's possible to verify this by adding a console.log statement inside the effect and seeing that it is logged on the browser's console.
Source of the problem
ReactDOMServer.renderToString() only builds the HTML that's required by a component, it then requires the component to be hydrated.
Direct fix
You can use ReactDOM.render to put the image on the page, given that the effect will execute client side. I have a PR showing that here.
Recommended approach
You could instead import the image inside the mdx component and directly render it there. Your gatsby config can already support this 👍 In content/blog/hello-world/index.mdx, you can replace the injectImage div with this ![A salty egg, yummm](./salty_egg.jpg) (where the text inside the [] is the alt text)
This documentation might be helpful
https://www.gatsbyjs.org/docs/working-with-images-in-markdown/
https://www.gatsbyjs.org/packages/gatsby-remark-images/
Hope that helps! 😄
I have faced this problem before with my first Gatsby project.
The problem similar to this chat and the error image issue here.
If you replace GatsbyImageSharpFixed_withWebp_tracedSVG like they talked in spectrum chat above, or this is my current code for example, basically is related to WebP new image format.
export const query = graphql`
query {
allImageSharp {
edges {
node {
fluid(maxWidth: 110) {
aspectRatio
originalName
sizes
src
srcSet
srcWebp
tracedSVG
}
}
}
}
}
`;
Hope this help.
I think the problem could be in the useEffect
const componentCreatedFromMarkdown = ({data}) => {
...
useEffect(() => {
const injectDivs = Array.from(document.getElementsByClassName('injectDivs'))
injectDivs.forEach((aDiv) => {
aDiv.innerHTML = ReactDOMServer.renderToString(<MyComponent args={myArgs} />)
}
},[])
...
}
I think you should try to add useEffect(()=>{},[]), the second argument to refresh the image only when the component is mounted, without this the image will be refreshed each time.

Ag-grid - having expandable height cells causes rendering issues

I have an Ionic/Angular project where I wish to use the Ag-grid as a (virtual) container for my potentially very large list of items. I am very new the the ag-grid, I have played a little in the past, but still relatively new to it
Ag-grid is the has come the closest by far to being able to do what I am trying to achieve.
Basically I have a list of items, where I wish to use an Angular component in each cell, and this component has an "expander", with a varying number of sub items.
To get a component in the grid, I followed this excellent tutorial, which seemed to work perfectly.
It almost all works, but I find when I expand items down the list a bit (eg item position say 50), the UI starts to jump around, and not render properly. If you expand the first few, it is ok, it is only when you get down the list a bit I have problems.
I have a sample project here on Github.
It looks like the following...
My setup of the grid is in home.page.ts, where I have the following gridOptions
gridOptions: GridOptions = {
// Makes col take up full grid
onGridSizeChanged: () => {
this.gridOptions.api.sizeColumnsToFit();
} ,
getRowHeight(params) {
return params.data.getHeight();
},
getRowNodeId: function (data) {
return data.equipment;
},
}
The getRowHeight above will call ListItem.getHeight, and you can see this returns the height based on whether or not is it expanded...
public getHeight(): number {
let height = 72;
if (this.isOpen)
height += (this.jobs.length - 1) * 40;
return height;
}
Also, when the expander is clicked the refresh function passed into the constructor is called.
public setIsOpen(val: boolean) {
this.isOpen = val;
this.refresh();
}
And this call the following in the home.page.ts to try and refresh the grid cells..
private refreshCells(): void {
this.gridOptions.api.refreshCells({ force: true });
this.gridOptions.api.resetRowHeights();
}
And that's basically it.
It is close to working, ie click the initial items works, but when I scroll down, sometimes the view just does not refresh properly (sometimes it does, other times not).
Is this achievable, and if so, what can I do get get it to work better?

How to apply filters on top of each other in Camanjs?

I have few questions regarding Camanjs library.
1. How can we import camanjs in React?
I have tried installing caman through npm but no success,I have also installed all the addition dependency mentioned(node-gyp & Installing GTK 2) but nothing seems to work.
So does anyone know how to use Camanjs in React??.
2. Scenario: I applied brightness(10) and then contrast(10) using camanjs.
Issue Now if I apply brightness this works fine but when I apply contrast it removes brightness and only applies contrast.
This must be because I'm using revert(false) before applying any new filter.
this.revert(false)
I want to apply both the filters simultaneously.
How can I do this. Can this be acheived using the this.newLayer(function(){}) with some blendingMode?
Or I have to save filters value in some array and then loop over and apply filters and then render canvas?
I also tried to use
this.reloadCanvasData();
Although this worked but when I reduced the value to 0 of both brightness and contrast, ideally it should render original image but instead the canvas turns grey or black.
Can anyone me guide or provide a suitable approach to tackle this problem.
Thanks in advance!!
Note: In below code you see since I was unable to install camanjs through npm, I have to take it into window object via CDN. This is working but create 'this' issue if I try to use 'this' inside
this.newLayer(function(){
/*Somewhere here(this refers to React component instead of Caman) */
})
My code:
onChangeHandler = (e, val) => {
e.persist();
let valInLowercase = 'stackBlur';
if(val !== 'Blur'){
valInLowercase = val.toLowerCase();
}
let canvas = document.querySelector("canvas")
let canavsID = canvas.getAttribute("id");
canavsID = "#" + canavsID;
window.caman(canavsID, function() {
this.revert(false)
this.reloadCanvasData();
if (val !== "Contrast") {
this[valInLowercase](e.target.value).render();
} else {
if(val === 'Contrast'){
this[valInLowercase](e.target.value/2).render();
}
}
})
if(e.type === "mouseup"){
canvas.setAttribute(valInLowercase, e.target.value)
}
};

VS Code MarkdownString Won't Display Links

I've been working on a custom extension for Visual Studio Code recently and am trying to show a link to the user when hovering over a specific phrase but it hasn't been working. The hover shows up but the link isn't "actionable".
My extension is registering a HoverProvider and is returning a new Hover object which contains a string with a link inside of it like so:
return new vscode.Hover({language: 'markdown', value: '[test-link](https://www.google.com)'});
I've tried switching the language between "markdown" and "HTML", but in either case, although the link was in the correct format, it was never actionable. I suspect this is because the value being fed in as a parameter to the Hover constructor is a MarkdownString which has the following note:
Note that markdown strings will be sanitized - that means html will be
escaped.
I could've sworn I've seen this feature elsewhere in VS Code like in a package.json file where a link to a repository was shown when hovering over a dependency name, but I can't seem to find a working example.
Here's an example of what the hover looks like:
Is there any way to get this feature working?
This is working for me:
let disposable1 = vscode.languages.registerHoverProvider('javascript', {
provideHover(document, position, token) {
const word = document.getText(document.getWordRangeAtPosition(position));
const searchOptions = {
query: word
};
const contents = new vscode.MarkdownString(`[test-link](https://www.google.com)`);
contents.isTrusted = true;
return new vscode.Hover(contents);
}
});
Note that new Hover() has this signature:
new Hover(contents: MarkdownString | MarkedString | Array<MarkdownString | MarkedString>, range?: Range): Hover
See Hover api reference.
You were trying to give it an object (with a language key).
With vscode v1.61 this will also work within the provider:
const contents = new vscode.MarkdownString(`[test-link](https://www.google.com)`);
contents.appendMarkdown("<a href='https://www.google.com'>test-link2</a>");
contents.supportHtml = true;
contents.isTrusted = true;
return new vscode.Hover(contents);
See https://stackoverflow.com/a/67954180/836330 for more on newly supported html tags.

Categories